fsdb 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.txt +1 -1
- data/lib/fsdb/database.rb +1 -1
- data/rakefile +5 -3
- data/test/test-concurrency.rb +5 -3
- data/test/test-formats.rb +3 -1
- data/test/test-fsdb.rb +5 -3
- metadata +10 -148
- data/junk/OLDRakefile +0 -98
- data/junk/OLDRakefile2 +0 -55
- data/junk/check-cache.rb +0 -18
- data/junk/create-lock.rb +0 -25
- data/junk/doc/old-api/classes/FSDB.html +0 -139
- data/junk/doc/old-api/classes/FSDB/Database.html +0 -953
- data/junk/doc/old-api/classes/FSDB/Database.src/M000029.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000030.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000031.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000032.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000033.html +0 -33
- data/junk/doc/old-api/classes/FSDB/Database.src/M000034.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000035.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000036.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000037.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000038.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000039.html +0 -25
- data/junk/doc/old-api/classes/FSDB/Database.src/M000040.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000041.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000042.html +0 -22
- data/junk/doc/old-api/classes/FSDB/Database.src/M000043.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000044.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000045.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000046.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000047.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000048.html +0 -16
- data/junk/doc/old-api/classes/FSDB/Database.src/M000049.html +0 -71
- data/junk/doc/old-api/classes/FSDB/Database.src/M000050.html +0 -43
- data/junk/doc/old-api/classes/FSDB/Database.src/M000051.html +0 -53
- data/junk/doc/old-api/classes/FSDB/Database.src/M000052.html +0 -44
- data/junk/doc/old-api/classes/FSDB/Database.src/M000053.html +0 -39
- data/junk/doc/old-api/classes/FSDB/Database.src/M000054.html +0 -72
- data/junk/doc/old-api/classes/FSDB/Database.src/M000055.html +0 -39
- data/junk/doc/old-api/classes/FSDB/Database.src/M000056.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000057.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000058.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000059.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000060.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000061.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000062.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Database.src/M000063.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database.src/M000064.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Database/AbortedTransaction.html +0 -118
- data/junk/doc/old-api/classes/FSDB/Database/CreateFileError.html +0 -120
- data/junk/doc/old-api/classes/FSDB/Database/DirIsImmutableError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/DirNotEmptyError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/FormatError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/MissingFileError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/MissingObjectError.html +0 -117
- data/junk/doc/old-api/classes/FSDB/Database/NotDirError.html +0 -118
- data/junk/doc/old-api/classes/FSDB/Database/PathComponentError.html +0 -120
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.html +0 -148
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.src/M000005.html +0 -21
- data/junk/doc/old-api/classes/FSDB/DatabaseDebuggable.src/M000007.html +0 -21
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.html +0 -210
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000006.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000007.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000008.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000009.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000010.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000011.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000012.html +0 -22
- data/junk/doc/old-api/classes/FSDB/DirectoryIterators.src/M000013.html +0 -22
- data/junk/doc/old-api/classes/FSDB/ForkSafely.html +0 -126
- data/junk/doc/old-api/classes/FSDB/Modex.html +0 -237
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000024.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000025.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000026.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000027.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000028.html +0 -44
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000029.html +0 -26
- data/junk/doc/old-api/classes/FSDB/Modex.src/M000030.html +0 -48
- data/junk/doc/old-api/classes/FSDB/Modex/ForkSafely.html +0 -105
- data/junk/doc/old-api/classes/FSDB/Mutex.html +0 -244
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000018.html +0 -19
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000019.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000020.html +0 -19
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000021.html +0 -18
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000022.html +0 -23
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000023.html +0 -30
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000024.html +0 -26
- data/junk/doc/old-api/classes/FSDB/Mutex.src/M000025.html +0 -21
- data/junk/doc/old-api/classes/FSDB/Mutex/ForkSafely.html +0 -105
- data/junk/doc/old-api/classes/FSDB/PathUtilities.html +0 -257
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000012.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000013.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000014.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000015.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000016.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000017.html +0 -22
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000018.html +0 -23
- data/junk/doc/old-api/classes/FSDB/PathUtilities.src/M000019.html +0 -18
- data/junk/doc/old-api/classes/FSDB/PathUtilities/InvalidPathError.html +0 -111
- data/junk/doc/old-api/classes/File.html +0 -272
- data/junk/doc/old-api/classes/File.src/M000001.html +0 -17
- data/junk/doc/old-api/classes/File.src/M000002.html +0 -17
- data/junk/doc/old-api/classes/File.src/M000003.html +0 -20
- data/junk/doc/old-api/classes/File.src/M000004.html +0 -20
- data/junk/doc/old-api/classes/File.src/M000005.html +0 -32
- data/junk/doc/old-api/classes/File.src/M000006.html +0 -32
- data/junk/doc/old-api/created.rid +0 -1
- data/junk/doc/old-api/files/README.html +0 -112
- data/junk/doc/old-api/files/RELEASE-NOTES.html +0 -233
- data/junk/doc/old-api/files/fsdb_txt.html +0 -888
- data/junk/doc/old-api/files/lib/fsdb/database_rb.html +0 -115
- data/junk/doc/old-api/files/lib/fsdb/file-lock_rb.html +0 -109
- data/junk/doc/old-api/files/lib/fsdb/modex_rb.html +0 -121
- data/junk/doc/old-api/files/lib/fsdb/mutex_rb.html +0 -108
- data/junk/doc/old-api/files/lib/fsdb/util_rb.html +0 -108
- data/junk/doc/old-api/fr_class_index.html +0 -47
- data/junk/doc/old-api/fr_file_index.html +0 -34
- data/junk/doc/old-api/fr_method_index.html +0 -90
- data/junk/doc/old-api/index.html +0 -24
- data/junk/doc/old-api/rdoc-style.css +0 -208
- data/junk/file-lock-nb.rb +0 -15
- data/junk/fl.rb +0 -144
- data/junk/flock-test.rb +0 -39
- data/junk/fsdb.kateproject +0 -47
- data/junk/fsdb.prj +0 -196
- data/junk/fsdb.sf +0 -46
- data/junk/insert-dir.rb +0 -48
- data/junk/lock-test-bug.rb +0 -150
- data/junk/lock-test-too-simple.rb +0 -136
- data/junk/lock-test.rb +0 -151
- data/junk/mkrdoc +0 -7
- data/junk/restore-fsdb.rb +0 -37
- data/junk/rf.txt +0 -5
- data/junk/solaris-bug-fixed.rb +0 -184
- data/junk/solaris-bug.rb +0 -182
- data/junk/solaris-bug.txt +0 -43
- data/junk/sync.rb +0 -327
- data/junk/test-file-lock.html +0 -86
- data/junk/test-file-lock.rb +0 -84
- data/junk/test-processes.rb +0 -131
- data/junk/test-threads.rb +0 -113
- data/junk/wiki-mutex.rb +0 -108
- data/misc/fsdb-blorubu.txt +0 -47
- data/misc/mtime-and-file-id.txt +0 -23
- data/misc/posixlock.txt +0 -148
data/junk/insert-dir.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
def insert(path, object)
|
2
|
-
abs_path = absolute(path)
|
3
|
-
file_id = make_file_id(abs_path)
|
4
|
-
object_exclusive file_id do |cache_entry|
|
5
|
-
open_write_lock(path) do |f|
|
6
|
-
dump(object, f)
|
7
|
-
cache_entry.update(f.mtime, inc_version_of(f, cache_entry), object)
|
8
|
-
object
|
9
|
-
end
|
10
|
-
end
|
11
|
-
rescue DirIsImmutableError
|
12
|
-
begin
|
13
|
-
ary = object.to_a
|
14
|
-
# when default to_a becomes obsolete, this will be reported as
|
15
|
-
# an error, which is ok--it will be caught and reported below.
|
16
|
-
raise unless ary.all?{|x|x.size == 2}
|
17
|
-
rescue StandardError
|
18
|
-
raise DirIsImmutableError,
|
19
|
-
"Cannot insert given object at dir #{path} in #{inspect}"
|
20
|
-
end
|
21
|
-
ary.each do |k,v|
|
22
|
-
insert(File.join(path, k), v)
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
def test_insert_dir
|
27
|
-
@db['insert_dir/'] = {
|
28
|
-
'path1' => 1,
|
29
|
-
'path2' => 2
|
30
|
-
}
|
31
|
-
assert_equal(1, @db['insert_dir/path1'])
|
32
|
-
assert_equal(2, @db['insert_dir/path2'])
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
__END__
|
37
|
-
|
38
|
-
- FSDB::Database#insert now allows
|
39
|
-
|
40
|
-
db['dir/'] = {
|
41
|
-
'path1' => obj1,
|
42
|
-
'path2' => obj2
|
43
|
-
}
|
44
|
-
|
45
|
-
as a shorthand for
|
46
|
-
|
47
|
-
db['dir/path1'] = obj1
|
48
|
-
db['dir/path2'] = obj2
|
data/junk/lock-test-bug.rb
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'thread'
|
4
|
-
require 'sync'
|
5
|
-
|
6
|
-
@path = '/tmp/foo'
|
7
|
-
|
8
|
-
@cache_mutex = Mutex.new
|
9
|
-
|
10
|
-
def make_entry
|
11
|
-
@cache_mutex.synchronize do
|
12
|
-
@cache = Mutex.new
|
13
|
-
@sync = Synchronizer.new
|
14
|
-
@object = nil
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# This is just for housekeeping, so that stale entries don't result
|
19
|
-
# in unused, but uncollectable, CacheEntry objects.
|
20
|
-
def clear_entry
|
21
|
-
@cache_mutex.synchronize do
|
22
|
-
@cache = nil
|
23
|
-
@sync = nil
|
24
|
-
@object = nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def object(f)
|
29
|
-
@cache.synchronize do
|
30
|
-
@object ||= f.read
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def sync_object_shared
|
35
|
-
@sync.synchronize(Synchronizer::SH) {yield}
|
36
|
-
end
|
37
|
-
|
38
|
-
def sync_object_exclusive
|
39
|
-
@sync.synchronize(Synchronizer::EX) {yield}
|
40
|
-
end
|
41
|
-
|
42
|
-
def browse
|
43
|
-
make_entry
|
44
|
-
sync_object_shared do
|
45
|
-
open_read_lock(@path) do |f|
|
46
|
-
yield object(f)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def change
|
52
|
-
make_entry
|
53
|
-
sync_object_exclusive do
|
54
|
-
open_write_lock(@path) do |f|
|
55
|
-
object = object(f)
|
56
|
-
yield object
|
57
|
-
f.write(object)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def open_read_lock(path)
|
63
|
-
File.open(path, "r") do |f|
|
64
|
-
begin
|
65
|
-
f.flock(File::LOCK_SH)
|
66
|
-
yield f
|
67
|
-
ensure
|
68
|
-
f.flock(File::LOCK_UN)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def open_write_lock(path)
|
74
|
-
File.open(path, "r+") do |f|
|
75
|
-
f.rewind
|
76
|
-
begin
|
77
|
-
f.flock(File::LOCK_EX) ## need to use fcntl for Linux NFS
|
78
|
-
yield f
|
79
|
-
ensure
|
80
|
-
f.flush ## is this necessary? [ruby-talk:16721]
|
81
|
-
f.flock(File::LOCK_UN)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def do_test
|
87
|
-
$stdout.sync = true
|
88
|
-
Thread.abort_on_exception = true
|
89
|
-
|
90
|
-
srand(3765)
|
91
|
-
|
92
|
-
thread_count = 2
|
93
|
-
rep_count = 100
|
94
|
-
max_sleep = 0.01
|
95
|
-
|
96
|
-
File.open(@path, "w") do |f|
|
97
|
-
f.write("0")
|
98
|
-
end
|
99
|
-
|
100
|
-
threads = (0..thread_count).map do |thread_index|
|
101
|
-
Thread.new(thread_index) do |ti|
|
102
|
-
Thread.current[:number] = ti
|
103
|
-
rep_count.times do |iter|
|
104
|
-
Thread.current[:iter] = iter
|
105
|
-
|
106
|
-
case rand(3)
|
107
|
-
|
108
|
-
when 0
|
109
|
-
browse do |tester|
|
110
|
-
old_tester = tester
|
111
|
-
sleep(rand*max_sleep)
|
112
|
-
unless old_tester == tester
|
113
|
-
fail "browse: #{old_tester} != #{tester}"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
when 1
|
118
|
-
change do |tester|
|
119
|
-
tester.replace (tester.to_i + 1).to_s
|
120
|
-
old_tester = tester
|
121
|
-
sleep(rand*max_sleep)
|
122
|
-
unless old_tester == tester
|
123
|
-
fail "browse: #{old_tester} != #{tester}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
else
|
128
|
-
sleep(rand*max_sleep)
|
129
|
-
if rand(20) == 0
|
130
|
-
clear_entry
|
131
|
-
end
|
132
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
sleep(rep_count * max_sleep * 2)
|
140
|
-
if threads.any? {|t|t.alive?}
|
141
|
-
$stderr.puts "Deadlock!"
|
142
|
-
exit!
|
143
|
-
end
|
144
|
-
|
145
|
-
threads.each do |thread|
|
146
|
-
thread.join
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
do_test
|
@@ -1,136 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'thread'
|
4
|
-
require 'sync'
|
5
|
-
#require 'ftools'
|
6
|
-
|
7
|
-
@path = '/tmp/foo'
|
8
|
-
|
9
|
-
@cache_mutex = Mutex.new
|
10
|
-
@sync = Synchronizer.new
|
11
|
-
@object = nil
|
12
|
-
|
13
|
-
def object(f)
|
14
|
-
@cache_mutex.synchronize do
|
15
|
-
@object ||= f.read
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def clear_cache
|
20
|
-
@object = nil
|
21
|
-
end
|
22
|
-
|
23
|
-
def sync_object_shared
|
24
|
-
@sync.synchronize(Synchronizer::SH) {yield}
|
25
|
-
end
|
26
|
-
def sync_object_exclusive
|
27
|
-
@sync.synchronize(Synchronizer::EX) {yield}
|
28
|
-
end
|
29
|
-
|
30
|
-
def browse
|
31
|
-
sync_object_shared do
|
32
|
-
open_read_lock(@path) do |f|
|
33
|
-
yield object(f)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def change
|
39
|
-
sync_object_exclusive do
|
40
|
-
open_write_lock(@path) do |f|
|
41
|
-
object = object(f)
|
42
|
-
yield object
|
43
|
-
f.write(object)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def open_read_lock(path)
|
49
|
-
File.open(path, "r") do |f|
|
50
|
-
begin
|
51
|
-
f.flock(File::LOCK_SH)
|
52
|
-
yield f
|
53
|
-
ensure
|
54
|
-
f.flock(File::LOCK_UN)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def open_write_lock(path)
|
60
|
-
File.open(path, "r+") do |f|
|
61
|
-
f.rewind
|
62
|
-
begin
|
63
|
-
f.flock(File::LOCK_EX) ## need to use fcntl for Linux NFS
|
64
|
-
yield f
|
65
|
-
ensure
|
66
|
-
f.flush ## is this necessary? [ruby-talk:16721]
|
67
|
-
f.flock(File::LOCK_UN)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def do_test
|
73
|
-
$stdout.sync = true
|
74
|
-
Thread.abort_on_exception = true
|
75
|
-
|
76
|
-
srand(3765)
|
77
|
-
|
78
|
-
thread_count = 2
|
79
|
-
rep_count = 100
|
80
|
-
max_sleep = 0.01
|
81
|
-
|
82
|
-
File.open(@path, "w") do |f|
|
83
|
-
f.write "0"
|
84
|
-
end
|
85
|
-
|
86
|
-
threads = (0..thread_count).map do |thread_index|
|
87
|
-
Thread.new(thread_index) do |ti|
|
88
|
-
Thread.current[:number] = ti
|
89
|
-
rep_count.times do |iter|
|
90
|
-
Thread.current[:iter] = iter
|
91
|
-
|
92
|
-
case rand(3)
|
93
|
-
|
94
|
-
when 0
|
95
|
-
browse do |tester|
|
96
|
-
old_tester = tester
|
97
|
-
sleep(rand*max_sleep)
|
98
|
-
unless old_tester == tester
|
99
|
-
fail "browse: #{old_tester} != #{tester}"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
when 1
|
104
|
-
change do |tester|
|
105
|
-
tester.replace (tester.to_i + 1).to_s
|
106
|
-
old_tester = tester
|
107
|
-
sleep(rand*max_sleep)
|
108
|
-
unless old_tester == tester
|
109
|
-
fail "browse: #{old_tester} != #{tester}"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
else
|
114
|
-
sleep(rand*max_sleep)
|
115
|
-
if rand(20) == 0
|
116
|
-
clear_cache
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
sleep(rep_count * max_sleep * 2)
|
126
|
-
if threads.any? {|t|t.alive?}
|
127
|
-
$stderr.puts "Deadlock!"
|
128
|
-
exit!
|
129
|
-
end
|
130
|
-
|
131
|
-
threads.each do |thread|
|
132
|
-
thread.join
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
do_test
|
data/junk/lock-test.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'thread'
|
4
|
-
require 'sync'
|
5
|
-
|
6
|
-
@path = '/tmp/foo'
|
7
|
-
|
8
|
-
@cache_mutex = Mutex.new
|
9
|
-
|
10
|
-
def make_entry
|
11
|
-
@cache_mutex.synchronize do
|
12
|
-
unless @mutex
|
13
|
-
@mutex ||= Mutex.new
|
14
|
-
@sync ||= Synchronizer.new
|
15
|
-
@object = nil
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# This is just for housekeeping, so that stale entries don't result
|
21
|
-
# in unused, but uncollectable, CacheEntry objects.
|
22
|
-
def clear_entry
|
23
|
-
@cache_mutex.synchronize do
|
24
|
-
@mutex = nil
|
25
|
-
@sync = nil
|
26
|
-
@object = nil
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def object(f)
|
31
|
-
@mutex.synchronize do
|
32
|
-
@object ||= f.read
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def sync_object_shared
|
37
|
-
@sync.synchronize(Synchronizer::SH) {yield}
|
38
|
-
end
|
39
|
-
|
40
|
-
def sync_object_exclusive
|
41
|
-
@sync.synchronize(Synchronizer::EX) {yield}
|
42
|
-
end
|
43
|
-
|
44
|
-
def browse
|
45
|
-
make_entry
|
46
|
-
sync_object_shared do
|
47
|
-
open_read_lock(@path) do |f|
|
48
|
-
yield object(f)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def change
|
54
|
-
make_entry
|
55
|
-
sync_object_exclusive do
|
56
|
-
open_write_lock(@path) do |f|
|
57
|
-
object = object(f)
|
58
|
-
yield object
|
59
|
-
f.write(object)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def open_read_lock(path)
|
65
|
-
File.open(path, "r") do |f|
|
66
|
-
begin
|
67
|
-
f.flock(File::LOCK_SH)
|
68
|
-
yield f
|
69
|
-
ensure
|
70
|
-
f.flock(File::LOCK_UN)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def open_write_lock(path)
|
76
|
-
File.open(path, "r+") do |f|
|
77
|
-
begin
|
78
|
-
f.flock(File::LOCK_EX) ## need to use fcntl for Linux NFS
|
79
|
-
yield f
|
80
|
-
ensure
|
81
|
-
f.flush ## is this necessary? [ruby-talk:16721]
|
82
|
-
f.flock(File::LOCK_UN)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def do_test
|
88
|
-
$stdout.sync = true
|
89
|
-
Thread.abort_on_exception = true
|
90
|
-
|
91
|
-
srand(3765)
|
92
|
-
|
93
|
-
thread_count = 2
|
94
|
-
rep_count = 100
|
95
|
-
max_sleep = 0.01
|
96
|
-
|
97
|
-
File.open(@path, "w") do |f|
|
98
|
-
f.write("0")
|
99
|
-
end
|
100
|
-
|
101
|
-
threads = (0..thread_count).map do |thread_index|
|
102
|
-
Thread.new(thread_index) do |ti|
|
103
|
-
Thread.current[:number] = ti
|
104
|
-
rep_count.times do |iter|
|
105
|
-
Thread.current[:iter] = iter
|
106
|
-
|
107
|
-
case rand(3)
|
108
|
-
|
109
|
-
when 0
|
110
|
-
browse do |tester|
|
111
|
-
old_tester = tester
|
112
|
-
sleep(rand*max_sleep)
|
113
|
-
unless old_tester == tester
|
114
|
-
fail "browse: #{old_tester} != #{tester}"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
when 1
|
119
|
-
change do |tester|
|
120
|
-
tester.replace (tester.to_i + 1).to_s
|
121
|
-
old_tester = tester
|
122
|
-
sleep(rand*max_sleep)
|
123
|
-
unless old_tester == tester
|
124
|
-
fail "browse: #{old_tester} != #{tester}"
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
else
|
129
|
-
sleep(rand*max_sleep)
|
130
|
-
if rand(20) == 0
|
131
|
-
clear_entry
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
sleep(rep_count * max_sleep * 2)
|
141
|
-
if threads.any? {|t|t.alive?}
|
142
|
-
$stderr.puts "Deadlock!"
|
143
|
-
exit!
|
144
|
-
end
|
145
|
-
|
146
|
-
threads.each do |thread|
|
147
|
-
thread.join
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
do_test
|