higgs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/ChangeLog +208 -0
  2. data/LICENSE +26 -0
  3. data/README +2 -0
  4. data/Rakefile +75 -0
  5. data/bin/higgs_backup +67 -0
  6. data/bin/higgs_dump_index +43 -0
  7. data/bin/higgs_dump_jlog +42 -0
  8. data/bin/higgs_verify +37 -0
  9. data/lib/cgi/session/higgs.rb +72 -0
  10. data/lib/higgs/block.rb +192 -0
  11. data/lib/higgs/cache.rb +117 -0
  12. data/lib/higgs/dbm.rb +55 -0
  13. data/lib/higgs/exceptions.rb +31 -0
  14. data/lib/higgs/flock.rb +77 -0
  15. data/lib/higgs/index.rb +164 -0
  16. data/lib/higgs/jlog.rb +159 -0
  17. data/lib/higgs/lock.rb +189 -0
  18. data/lib/higgs/storage.rb +1086 -0
  19. data/lib/higgs/store.rb +228 -0
  20. data/lib/higgs/tar.rb +390 -0
  21. data/lib/higgs/thread.rb +370 -0
  22. data/lib/higgs/tman.rb +513 -0
  23. data/lib/higgs/utils/bman.rb +285 -0
  24. data/lib/higgs/utils.rb +22 -0
  25. data/lib/higgs/version.rb +21 -0
  26. data/lib/higgs.rb +59 -0
  27. data/misc/cache_bench/cache_bench.rb +43 -0
  28. data/misc/dbm_bench/.strc +8 -0
  29. data/misc/dbm_bench/Rakefile +78 -0
  30. data/misc/dbm_bench/dbm_multi_thread.rb +199 -0
  31. data/misc/dbm_bench/dbm_rnd_delete.rb +43 -0
  32. data/misc/dbm_bench/dbm_rnd_read.rb +44 -0
  33. data/misc/dbm_bench/dbm_rnd_update.rb +44 -0
  34. data/misc/dbm_bench/dbm_seq_read.rb +45 -0
  35. data/misc/dbm_bench/dbm_seq_write.rb +44 -0
  36. data/misc/dbm_bench/st_verify.rb +28 -0
  37. data/misc/io_bench/cksum_bench.rb +48 -0
  38. data/misc/io_bench/jlog_bench.rb +71 -0
  39. data/misc/io_bench/write_bench.rb +128 -0
  40. data/misc/thread_bench/lock_bench.rb +132 -0
  41. data/mkrdoc.rb +8 -0
  42. data/rdoc.yml +13 -0
  43. data/sample/count.rb +60 -0
  44. data/sample/dbmtest.rb +38 -0
  45. data/test/Rakefile +45 -0
  46. data/test/run.rb +32 -0
  47. data/test/test_block.rb +163 -0
  48. data/test/test_cache.rb +214 -0
  49. data/test/test_cgi_session.rb +142 -0
  50. data/test/test_flock.rb +162 -0
  51. data/test/test_index.rb +258 -0
  52. data/test/test_jlog.rb +180 -0
  53. data/test/test_lock.rb +320 -0
  54. data/test/test_online_backup.rb +169 -0
  55. data/test/test_storage.rb +439 -0
  56. data/test/test_storage_conf.rb +202 -0
  57. data/test/test_storage_init_opts.rb +89 -0
  58. data/test/test_store.rb +211 -0
  59. data/test/test_tar.rb +432 -0
  60. data/test/test_thread.rb +541 -0
  61. data/test/test_tman.rb +875 -0
  62. data/test/test_tman_init_opts.rb +56 -0
  63. data/test/test_utils_bman.rb +234 -0
  64. metadata +115 -0
data/lib/higgs/jlog.rb ADDED
@@ -0,0 +1,159 @@
1
+ # = journal log writer
2
+ #
3
+ # Author:: $Author: toki $
4
+ # Date:: $Date: 2007-09-26 00:20:20 +0900 (Wed, 26 Sep 2007) $
5
+ # Revision:: $Revision: 559 $
6
+ #
7
+ # == license
8
+ # :include:LICENSE
9
+ #
10
+
11
+ require 'higgs/block'
12
+
13
+ module Higgs
14
+ # = journal log writer
15
+ class JournalLogger
16
+ # for ident(1)
17
+ CVS_ID = '$Id: jlog.rb 559 2007-09-25 15:20:20Z toki $'
18
+
19
+ include Block
20
+
21
+ MAGIC_SYMBOL = 'HIGGS_JLOG'
22
+ EOF_MARK = :END_OF_JLOG
23
+ BIN_EOF_MARK = Marshal.dump(EOF_MARK)
24
+
25
+ # see Higgs::Block#block_write for <tt>hash_type</tt>
26
+ def initialize(out, sync=false, hash_type=:MD5)
27
+ @out = out
28
+ @sync = sync
29
+ @hash_type = hash_type
30
+ end
31
+
32
+ def sync?
33
+ @sync
34
+ end
35
+
36
+ def size
37
+ @out.stat.size
38
+ end
39
+
40
+ def write(log, hash_type=nil)
41
+ bin_log = Marshal.dump(log)
42
+ start_pos = @out.tell
43
+ commit_completed = false
44
+ begin
45
+ block_write(@out, MAGIC_SYMBOL, bin_log, hash_type || @hash_type)
46
+ if (@sync) then
47
+ @out.fsync
48
+ else
49
+ @out.flush
50
+ end
51
+ commit_completed = true
52
+ ensure
53
+ @out.truncate(start_pos) unless commit_completed
54
+ end
55
+
56
+ self
57
+ end
58
+
59
+ def write_EOF
60
+ JournalLogger.eof_mark(@out)
61
+ self
62
+ end
63
+
64
+ def close(eof=true)
65
+ write_EOF if eof
66
+ @out.fsync
67
+ @out.close
68
+ @out = nil
69
+ nil
70
+ end
71
+
72
+ class << self
73
+ def has_eof_mark?(path)
74
+ unless (File.exist? path) then
75
+ return true
76
+ end
77
+
78
+ File.open(path, 'r') {|f|
79
+ f.binmode
80
+ fsiz = f.stat.size
81
+ if (fsiz < Block::BLOCK_SIZE * 2) then
82
+ return false
83
+ end
84
+ f.seek(fsiz - Block::BLOCK_SIZE * 2)
85
+
86
+ begin
87
+ bin_log = Block.block_read(f, MAGIC_SYMBOL) or return
88
+ log = Marshal.load(bin_log)
89
+ if (log == EOF_MARK) then
90
+ return true
91
+ end
92
+ rescue Block::BrokenError
93
+ return false
94
+ end
95
+ }
96
+
97
+ false
98
+ end
99
+
100
+ def need_for_recovery?(path)
101
+ ! (has_eof_mark? path)
102
+ end
103
+
104
+ def open(path, *args)
105
+ begin
106
+ f = File.open(path, File::WRONLY | File::CREAT | File::EXCL, 0660)
107
+ rescue Errno::EEXIST
108
+ if (need_for_recovery? path) then
109
+ raise "need for recovery: #{path}"
110
+ end
111
+ f = File.open(path, File::WRONLY, 0660)
112
+ fsiz = f.stat.size
113
+ f.truncate(fsiz - Block::BLOCK_SIZE * 2)
114
+ end
115
+ f.binmode
116
+ f.seek(0, IO::SEEK_END)
117
+ new(f, *args)
118
+ end
119
+
120
+ def eof_mark(out)
121
+ Block.block_write(out, MAGIC_SYMBOL, BIN_EOF_MARK)
122
+ nil
123
+ end
124
+
125
+ def scan_log(io)
126
+ safe_pos = io.tell
127
+ begin
128
+ while (bin_log = Block.block_read(io, MAGIC_SYMBOL))
129
+ log = Marshal.load(bin_log)
130
+ if (log == EOF_MARK) then
131
+ break
132
+ end
133
+ yield(log)
134
+ safe_pos = io.tell
135
+ end
136
+ rescue Block::BrokenError
137
+ io.seek(safe_pos)
138
+ raise
139
+ end
140
+ self
141
+ end
142
+
143
+ def each_log(path)
144
+ File.open(path, 'r') {|f|
145
+ f.binmode
146
+ scan_log(f) {|log|
147
+ yield(log)
148
+ }
149
+ }
150
+ nil
151
+ end
152
+ end
153
+ end
154
+ end
155
+
156
+ # Local Variables:
157
+ # mode: Ruby
158
+ # indent-tabs-mode: nil
159
+ # End:
data/lib/higgs/lock.rb ADDED
@@ -0,0 +1,189 @@
1
+ # = multi-thread lock manager
2
+ #
3
+ # Author:: $Author: toki $
4
+ # Date:: $Date: 2007-09-26 00:20:20 +0900 (Wed, 26 Sep 2007) $
5
+ # Revision:: $Revision: 559 $
6
+ #
7
+ # == license
8
+ # :include:LICENSE
9
+ #
10
+
11
+ require 'forwardable'
12
+ require 'higgs/cache'
13
+ require 'higgs/exceptions'
14
+ require 'singleton'
15
+ require 'thread'
16
+
17
+ module Higgs
18
+ # = multi-thread lock manager
19
+ class LockManager
20
+ # for ident(1)
21
+ CVS_ID = '$Id: lock.rb 559 2007-09-25 15:20:20Z toki $'
22
+
23
+ include Exceptions
24
+
25
+ class Error < HiggsError
26
+ end
27
+
28
+ class TryLockTimeoutError < Error
29
+ end
30
+
31
+ SPIN_LOCK_COUNT = 100
32
+ TRY_LOCK_LIMIT = 10
33
+ TRY_LOCK_INTERVAL = 0.1
34
+
35
+ RAND_GEN = proc{|seed|
36
+ n = seed
37
+ cycle = 0xFFFF
38
+ proc{
39
+ n = (n * 37549 + 12345) % cycle
40
+ n.to_f / cycle
41
+ }
42
+ }
43
+
44
+ def initialize(options={})
45
+ @spin_lock_count = options[:spin_lock_count] || SPIN_LOCK_COUNT
46
+ @try_lock_limit = options[:try_lock_limit] || TRY_LOCK_LIMIT
47
+ @try_lock_interval = options[:try_lock_interval] || TRY_LOCK_INTERVAL
48
+ @rand_gen = options[:random_number_generator] || RAND_GEN
49
+ end
50
+
51
+ attr_reader :spin_lock_count
52
+ attr_reader :try_lock_limit
53
+ attr_reader :try_lock_interval
54
+
55
+ def new_rand(seed)
56
+ @rand_gen.call(seed)
57
+ end
58
+
59
+ def self.try_lock(lock, attrs)
60
+ t0 = Time.now
61
+ c = attrs.spin_lock_count
62
+ while (c > 0)
63
+ if (lock.try_lock) then
64
+ return
65
+ end
66
+ c -= 1
67
+ end
68
+
69
+ if (attrs.try_lock_limit > 0) then
70
+ rand = attrs.new_rand(::Thread.current.object_id ^ t0.to_i)
71
+ while (Time.now - t0 < attrs.try_lock_limit)
72
+ if (lock.try_lock) then
73
+ return
74
+ end
75
+ sleep(attrs.try_lock_interval * rand.call)
76
+ end
77
+ raise TryLockTimeoutError, 'expired'
78
+ else
79
+ # brave man who doesn't fear deadlock.
80
+ lock.lock
81
+ end
82
+ end
83
+ end
84
+
85
+ class GiantLockManager < LockManager
86
+ # for ident(1)
87
+ CVS_ID = '$Id: lock.rb 559 2007-09-25 15:20:20Z toki $'
88
+
89
+ def initialize(*args)
90
+ super
91
+ @rw_lock = ReadWriteLock.new
92
+ end
93
+
94
+ class NoWorkLockHandler
95
+ include Singleton
96
+
97
+ def lock(key)
98
+ self
99
+ end
100
+
101
+ def unlock(key)
102
+ self
103
+ end
104
+ end
105
+
106
+ def transaction(read_only=false)
107
+ if (read_only) then
108
+ lock = @rw_lock.read_lock
109
+ else
110
+ lock = @rw_lock.write_lock
111
+ end
112
+ r = nil
113
+ lock.synchronize{
114
+ r = yield(NoWorkLockHandler.instance)
115
+ }
116
+ r
117
+ end
118
+ end
119
+
120
+ class FineGrainLockManager < LockManager
121
+ # for ident(1)
122
+ CVS_ID = '$Id: lock.rb 559 2007-09-25 15:20:20Z toki $'
123
+
124
+ def initialize(*args)
125
+ super
126
+ @cache = SharedWorkCache.new{|key| ReadWriteLock.new }
127
+ end
128
+
129
+ class LockHandler
130
+ def initialize(attrs, cache)
131
+ @attrs = attrs
132
+ @cache = cache
133
+ @lock_map = {}
134
+ end
135
+
136
+ def lock_list
137
+ @lock_map.values
138
+ end
139
+
140
+ def unlock(key)
141
+ if (lock = @lock_map.delete(key)) then
142
+ lock.unlock
143
+ else
144
+ raise "not locked key: #{key}"
145
+ end
146
+ self
147
+ end
148
+ end
149
+
150
+ class ReadOnlyLockHandler < LockHandler
151
+ def lock(key)
152
+ r_lock = @cache[key].read_lock
153
+ LockManager.try_lock(r_lock, @attrs)
154
+ @lock_map[key] = r_lock
155
+ self
156
+ end
157
+ end
158
+
159
+ class ReadWriteLockHandler < LockHandler
160
+ def lock(key)
161
+ w_lock = @cache[key].write_lock
162
+ LockManager.try_lock(w_lock, @attrs)
163
+ @lock_map[key] = w_lock
164
+ self
165
+ end
166
+ end
167
+
168
+ def transaction(read_only=false)
169
+ if (read_only) then
170
+ lock_handler = ReadOnlyLockHandler.new(self, @cache)
171
+ else
172
+ lock_handler = ReadWriteLockHandler.new(self, @cache)
173
+ end
174
+ begin
175
+ r = yield(lock_handler)
176
+ ensure
177
+ for lock in lock_handler.lock_list
178
+ lock.unlock
179
+ end
180
+ end
181
+ r
182
+ end
183
+ end
184
+ end
185
+
186
+ # Local Variables:
187
+ # mode: Ruby
188
+ # indent-tabs-mode: nil
189
+ # End: