jio 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/.travis.yml +18 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/LICENSE +16 -0
- data/README.rdoc +92 -0
- data/Rakefile +45 -0
- data/ext/jio/extconf.rb +123 -0
- data/ext/jio/file.c +488 -0
- data/ext/jio/file.h +20 -0
- data/ext/jio/jio_ext.c +119 -0
- data/ext/jio/jio_ext.h +46 -0
- data/ext/jio/jio_prelude.h +22 -0
- data/ext/jio/jruby.h +20 -0
- data/ext/jio/rubinius.h +22 -0
- data/ext/jio/ruby18.h +43 -0
- data/ext/jio/ruby19.h +15 -0
- data/ext/jio/transaction.c +260 -0
- data/ext/jio/transaction.h +26 -0
- data/ext/libjio.tar.gz +0 -0
- data/jio.gemspec +22 -0
- data/lib/jio.rb +12 -0
- data/lib/jio/file.rb +24 -0
- data/lib/jio/version.rb +5 -0
- data/test/helper.rb +32 -0
- data/test/test_file.rb +116 -0
- data/test/test_jio.rb +23 -0
- data/test/test_transaction.rb +111 -0
- metadata +90 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
#ifndef JIO_TRANSACTION_H
|
2
|
+
#define JIO_TRANSACTION_H
|
3
|
+
|
4
|
+
#define JIO_TRANSACTION_RELEASED 0x01
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
jtrans_t *trans;
|
8
|
+
VALUE views;
|
9
|
+
int flags;
|
10
|
+
} jio_jtrans_wrapper;
|
11
|
+
|
12
|
+
#define JioAssertTransaction(obj) JioAssertType(obj, rb_cJioTransaction, "JIO::Transaction")
|
13
|
+
#define JioGetTransaction(obj) \
|
14
|
+
jio_jtrans_wrapper *trans = NULL; \
|
15
|
+
JioAssertTransaction(obj); \
|
16
|
+
Data_Get_Struct(obj, jio_jtrans_wrapper, trans); \
|
17
|
+
if (!trans) rb_raise(rb_eTypeError, "uninitialized JIO transaction handle!");
|
18
|
+
|
19
|
+
void rb_jio_mark_transaction(void *ptr);
|
20
|
+
void rb_jio_free_transaction(void *ptr);
|
21
|
+
|
22
|
+
VALUE rb_jio_file_new_transaction(VALUE obj, VALUE flags);
|
23
|
+
|
24
|
+
void _init_rb_jio_transaction();
|
25
|
+
|
26
|
+
#endif
|
data/ext/libjio.tar.gz
ADDED
Binary file
|
data/jio.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('../lib/jio/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "jio"
|
7
|
+
s.version = JIO::VERSION
|
8
|
+
s.summary = "jio - transactional, journaled file I/O for Ruby"
|
9
|
+
s.description = "jio - transactional, journaled file I/O for Ruby"
|
10
|
+
s.authors = ["Lourens Naudé"]
|
11
|
+
s.email = ["lourens@methodmissing.com"]
|
12
|
+
s.homepage = "http://github.com/methodmissing/jio"
|
13
|
+
s.date = Time.now.utc.strftime('%Y-%m-%d')
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.extensions = Dir["ext/jio/extconf.rb"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.files = `git ls-files`.split
|
18
|
+
s.test_files = `git ls-files test`.split("\n")
|
19
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.add_development_dependency('rake-compiler', '~> 0.8.1')
|
22
|
+
end
|
data/lib/jio.rb
ADDED
data/lib/jio/file.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module JIO
|
4
|
+
class File
|
5
|
+
alias orig_transaction transaction
|
6
|
+
def transaction(flags)
|
7
|
+
if block_given?
|
8
|
+
begin
|
9
|
+
trans = orig_transaction(flags)
|
10
|
+
yield trans
|
11
|
+
rescue
|
12
|
+
trans.rollback
|
13
|
+
error = true
|
14
|
+
raise
|
15
|
+
ensure
|
16
|
+
trans.commit if !error && !trans.committed?
|
17
|
+
trans.release
|
18
|
+
end
|
19
|
+
else
|
20
|
+
orig_transaction(flags)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/jio/version.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'jio'
|
5
|
+
require 'fileutils' #19
|
6
|
+
require 'timeout'
|
7
|
+
|
8
|
+
TMP = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp'))
|
9
|
+
SANDBOX = File.join(TMP, 'sandbox')
|
10
|
+
FileUtils.rm_rf SANDBOX
|
11
|
+
FileUtils.mkdir_p SANDBOX
|
12
|
+
|
13
|
+
class JioTestCase < Test::Unit::TestCase
|
14
|
+
FILE = File.join(SANDBOX, 'file.jio')
|
15
|
+
OPEN_ARGS = [FILE, JIO::RDWR | JIO::CREAT | JIO::TRUNC, 0644, JIO::J_LINGER]
|
16
|
+
|
17
|
+
undef_method :default_test if method_defined? :default_test
|
18
|
+
|
19
|
+
def setup
|
20
|
+
File.unlink(FILE) if File.exists?(FILE)
|
21
|
+
end
|
22
|
+
|
23
|
+
if ENV['STRESS_GC']
|
24
|
+
def setup
|
25
|
+
GC.stress = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def teardown
|
29
|
+
GC.stress = false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/test/test_file.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestFile < JioTestCase
|
6
|
+
def test_open_close
|
7
|
+
file = JIO.open(*OPEN_ARGS)
|
8
|
+
assert_instance_of JIO::File, file
|
9
|
+
ensure
|
10
|
+
assert file.close
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_sync
|
14
|
+
file = JIO.open(*OPEN_ARGS)
|
15
|
+
assert file.sync
|
16
|
+
ensure
|
17
|
+
assert file.close
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_move_journal
|
21
|
+
file = JIO.open(*OPEN_ARGS)
|
22
|
+
assert file.move_journal(SANDBOX)
|
23
|
+
ensure
|
24
|
+
assert file.close
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_autosync
|
28
|
+
file = JIO.open(*OPEN_ARGS)
|
29
|
+
assert file.autosync(1, 1024)
|
30
|
+
file.write("CO")
|
31
|
+
file.write("MM")
|
32
|
+
file.write("IT")
|
33
|
+
sleep 1.1
|
34
|
+
file.rewind
|
35
|
+
assert_equal "COMMIT", file.read(6)
|
36
|
+
assert file.stop_autosync
|
37
|
+
ensure
|
38
|
+
assert file.close
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_read_write
|
42
|
+
file = JIO.open(*OPEN_ARGS)
|
43
|
+
assert_equal "", file.read(0)
|
44
|
+
assert_equal 4, file.write('ABCD')
|
45
|
+
assert_equal 'ABCD', file.pread(4, 0)
|
46
|
+
file.pwrite('EFGH', 4)
|
47
|
+
assert_equal 'EFGH', file.pread(4, 4)
|
48
|
+
file.pwrite('LMNOPQRS', 0)
|
49
|
+
assert_equal 'LMNOPQRS', file.pread(8, 0)
|
50
|
+
ensure
|
51
|
+
assert file.close
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_lseek
|
55
|
+
file = JIO.open(*OPEN_ARGS)
|
56
|
+
assert_equal 4, file.write('ABCD')
|
57
|
+
file.lseek(2, IO::SEEK_SET)
|
58
|
+
assert_equal 'CD', file.read(2)
|
59
|
+
ensure
|
60
|
+
assert file.close
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_truncate
|
64
|
+
file = JIO.open(*OPEN_ARGS)
|
65
|
+
assert_equal 4, file.write('ABCD')
|
66
|
+
assert_equal 4, File.size(FILE)
|
67
|
+
file.truncate(2)
|
68
|
+
assert_equal 2, File.size(FILE)
|
69
|
+
file.truncate(0)
|
70
|
+
assert_equal 0, File.size(FILE)
|
71
|
+
ensure
|
72
|
+
assert file.close
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_fileno
|
76
|
+
file = JIO.open(*OPEN_ARGS)
|
77
|
+
assert_instance_of Fixnum, file.fileno
|
78
|
+
ensure
|
79
|
+
assert file.close
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_rewind
|
83
|
+
file = JIO.open(*OPEN_ARGS)
|
84
|
+
file.write('ABCD')
|
85
|
+
file.rewind
|
86
|
+
assert_equal 'ABCD', file.read(4)
|
87
|
+
ensure
|
88
|
+
assert file.close
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_tell
|
92
|
+
file = JIO.open(*OPEN_ARGS)
|
93
|
+
file.write('ABCD')
|
94
|
+
assert_equal 4, file.tell
|
95
|
+
ensure
|
96
|
+
assert file.close
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_eof_p
|
100
|
+
file = JIO.open(*OPEN_ARGS)
|
101
|
+
file.write('ABCD')
|
102
|
+
assert file.eof?
|
103
|
+
file.rewind
|
104
|
+
assert !file.eof?
|
105
|
+
ensure
|
106
|
+
assert file.close
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_error
|
110
|
+
file = JIO.open(*OPEN_ARGS)
|
111
|
+
file.write('ABCD')
|
112
|
+
assert !file.error?
|
113
|
+
ensure
|
114
|
+
assert file.close
|
115
|
+
end
|
116
|
+
end
|
data/test/test_jio.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestJio < JioTestCase
|
6
|
+
def test_check
|
7
|
+
file = JIO.open(*OPEN_ARGS)
|
8
|
+
trans = file.transaction(JIO::J_LINGER)
|
9
|
+
trans.write('COMMIT', 0)
|
10
|
+
assert trans.commit
|
11
|
+
assert trans.committed?
|
12
|
+
expected = {:reapplied=>1,
|
13
|
+
:invalid=>2,
|
14
|
+
:corrupt=>0,
|
15
|
+
:total=>3,
|
16
|
+
:in_progress=>0,
|
17
|
+
:broken=>0}
|
18
|
+
assert_equal expected, JIO.check(FILE, 0)
|
19
|
+
ensure
|
20
|
+
trans.release
|
21
|
+
assert file.close
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
4
|
+
|
5
|
+
class TestTransaction < JioTestCase
|
6
|
+
def test_spawn_transaction
|
7
|
+
file = JIO.open(*OPEN_ARGS)
|
8
|
+
trans = file.transaction(JIO::J_LINGER)
|
9
|
+
assert_instance_of JIO::Transaction, trans
|
10
|
+
ensure
|
11
|
+
trans.release
|
12
|
+
assert file.close
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_spawn_transaction_with_block
|
16
|
+
file = JIO.open(*OPEN_ARGS)
|
17
|
+
file.transaction(JIO::J_LINGER) do |trans|
|
18
|
+
assert_instance_of JIO::Transaction, trans
|
19
|
+
trans.write("COMMIT", 0)
|
20
|
+
end
|
21
|
+
assert_equal "COMMIT", file.read(6)
|
22
|
+
ensure
|
23
|
+
assert file.close
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_spawn_transaction_with_block_error
|
27
|
+
file = JIO.open(*OPEN_ARGS)
|
28
|
+
file.transaction(JIO::J_LINGER) do |trans|
|
29
|
+
assert_instance_of JIO::Transaction, trans
|
30
|
+
trans.write("COMMIT", 0)
|
31
|
+
raise "rollback"
|
32
|
+
end rescue nil
|
33
|
+
assert_not_equal "COMMIT", file.read(6)
|
34
|
+
ensure
|
35
|
+
assert file.close
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_transaction_views
|
39
|
+
file = JIO.open(*OPEN_ARGS)
|
40
|
+
trans = file.transaction(JIO::J_LINGER)
|
41
|
+
trans.write('COMMIT', 0)
|
42
|
+
trans.read(2, 2)
|
43
|
+
assert_equal [], trans.views
|
44
|
+
assert_equal nil, trans.release
|
45
|
+
ensure
|
46
|
+
assert file.close
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_commit_transaction
|
50
|
+
file = JIO.open(*OPEN_ARGS)
|
51
|
+
trans = file.transaction(JIO::J_LINGER)
|
52
|
+
trans.write('COMMIT', 0)
|
53
|
+
trans.read(2, 2)
|
54
|
+
trans.read(2, 4)
|
55
|
+
assert_equal [], trans.views
|
56
|
+
assert trans.commit
|
57
|
+
assert_equal %w(MM IT), trans.views
|
58
|
+
ensure
|
59
|
+
trans.release
|
60
|
+
file.close
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_rollback_transaction
|
64
|
+
file = JIO.open(*OPEN_ARGS)
|
65
|
+
trans = file.transaction(JIO::J_LINGER)
|
66
|
+
trans.write('COMMIT', 0)
|
67
|
+
assert trans.commit
|
68
|
+
assert trans.rollback
|
69
|
+
ensure
|
70
|
+
trans.release
|
71
|
+
assert file.close
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_transaction_committed_p
|
75
|
+
file = JIO.open(*OPEN_ARGS)
|
76
|
+
trans = file.transaction(JIO::J_LINGER)
|
77
|
+
trans.write('COMMIT', 0)
|
78
|
+
assert trans.commit
|
79
|
+
assert trans.committed?
|
80
|
+
ensure
|
81
|
+
trans.release
|
82
|
+
assert file.close
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def test_transaction_rollbacked_p
|
87
|
+
file = JIO.open(*OPEN_ARGS)
|
88
|
+
trans = file.transaction(JIO::J_LINGER)
|
89
|
+
trans.write('COMMIT', 0)
|
90
|
+
assert trans.commit
|
91
|
+
assert_equal 'COMMIT', file.read(6)
|
92
|
+
assert trans.rollback
|
93
|
+
# XXX: try to reproduce a rollbacked state
|
94
|
+
assert !trans.rollbacked?
|
95
|
+
ensure
|
96
|
+
trans.release
|
97
|
+
assert file.close
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_transaction_rollbacking_p
|
101
|
+
file = JIO.open(*OPEN_ARGS)
|
102
|
+
trans = file.transaction(JIO::J_LINGER)
|
103
|
+
trans.write('COMMIT', 0)
|
104
|
+
assert trans.commit
|
105
|
+
assert trans.rollback
|
106
|
+
assert !trans.rollbacking?
|
107
|
+
ensure
|
108
|
+
trans.release
|
109
|
+
assert file.close
|
110
|
+
end
|
111
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lourens Naudé
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake-compiler
|
16
|
+
requirement: &70330249254420 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.8.1
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70330249254420
|
25
|
+
description: jio - transactional, journaled file I/O for Ruby
|
26
|
+
email:
|
27
|
+
- lourens@methodmissing.com
|
28
|
+
executables: []
|
29
|
+
extensions:
|
30
|
+
- ext/jio/extconf.rb
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- .gitignore
|
34
|
+
- .travis.yml
|
35
|
+
- Gemfile
|
36
|
+
- Gemfile.lock
|
37
|
+
- LICENSE
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- ext/jio/extconf.rb
|
41
|
+
- ext/jio/file.c
|
42
|
+
- ext/jio/file.h
|
43
|
+
- ext/jio/jio_ext.c
|
44
|
+
- ext/jio/jio_ext.h
|
45
|
+
- ext/jio/jio_prelude.h
|
46
|
+
- ext/jio/jruby.h
|
47
|
+
- ext/jio/rubinius.h
|
48
|
+
- ext/jio/ruby18.h
|
49
|
+
- ext/jio/ruby19.h
|
50
|
+
- ext/jio/transaction.c
|
51
|
+
- ext/jio/transaction.h
|
52
|
+
- ext/libjio.tar.gz
|
53
|
+
- jio.gemspec
|
54
|
+
- lib/jio.rb
|
55
|
+
- lib/jio/file.rb
|
56
|
+
- lib/jio/version.rb
|
57
|
+
- test/helper.rb
|
58
|
+
- test/test_file.rb
|
59
|
+
- test/test_jio.rb
|
60
|
+
- test/test_transaction.rb
|
61
|
+
homepage: http://github.com/methodmissing/jio
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 1.8.10
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: jio - transactional, journaled file I/O for Ruby
|
86
|
+
test_files:
|
87
|
+
- test/helper.rb
|
88
|
+
- test/test_file.rb
|
89
|
+
- test/test_jio.rb
|
90
|
+
- test/test_transaction.rb
|