roma 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. data/LICENSE.rdoc +675 -0
  2. data/README.rdoc +0 -0
  3. data/Rakefile +70 -0
  4. data/bin/mkrecent +7 -0
  5. data/bin/mkroute +7 -0
  6. data/bin/recoverlost +8 -0
  7. data/bin/recoverlost_alist +8 -0
  8. data/bin/romad +7 -0
  9. data/bin/sample_watcher +8 -0
  10. data/bin/sample_watcher2 +8 -0
  11. data/bin/simple_bench +8 -0
  12. data/bin/ssroute +7 -0
  13. data/bin/tribunus +7 -0
  14. data/lib/roma/async_process.rb +696 -0
  15. data/lib/roma/command/bg_command_receiver.rb +188 -0
  16. data/lib/roma/command/mh_command_receiver.rb +117 -0
  17. data/lib/roma/command/receiver.rb +287 -0
  18. data/lib/roma/command/rt_command_receiver.rb +147 -0
  19. data/lib/roma/command/st_command_receiver.rb +564 -0
  20. data/lib/roma/command/util_command_receiver.rb +67 -0
  21. data/lib/roma/command/vn_command_receiver.rb +143 -0
  22. data/lib/roma/command_plugin.rb +11 -0
  23. data/lib/roma/config.rb +64 -0
  24. data/lib/roma/event/con_pool.rb +140 -0
  25. data/lib/roma/event/handler.rb +159 -0
  26. data/lib/roma/plugin/plugin_alist.rb +1572 -0
  27. data/lib/roma/plugin/plugin_debug.rb +19 -0
  28. data/lib/roma/plugin/plugin_test.rb +14 -0
  29. data/lib/roma/romad.rb +582 -0
  30. data/lib/roma/routing/cb_rttable.rb +326 -0
  31. data/lib/roma/routing/merkle_tree.rb +54 -0
  32. data/lib/roma/routing/rttable.rb +148 -0
  33. data/lib/roma/stats.rb +112 -0
  34. data/lib/roma/storage/basic_storage.rb +510 -0
  35. data/lib/roma/storage/dbm_storage.rb +80 -0
  36. data/lib/roma/storage/dummy_storage.rb +44 -0
  37. data/lib/roma/storage/rh_storage.rb +35 -0
  38. data/lib/roma/storage/sqlite3_storage.rb +73 -0
  39. data/lib/roma/storage/tc_storage.rb +133 -0
  40. data/lib/roma/tools/mkrecent.rb +138 -0
  41. data/lib/roma/tools/mkroute.rb +52 -0
  42. data/lib/roma/tools/recoverlost.rb +9 -0
  43. data/lib/roma/tools/recoverlost_alist.rb +9 -0
  44. data/lib/roma/tools/recoverlost_lib.rb +217 -0
  45. data/lib/roma/tools/sample_watcher.rb +38 -0
  46. data/lib/roma/tools/sample_watcher2.rb +38 -0
  47. data/lib/roma/tools/simple_bench.rb +57 -0
  48. data/lib/roma/tools/ssroute.rb +23 -0
  49. data/lib/roma/tools/tribunus.rb +299 -0
  50. data/lib/roma/version.rb +4 -0
  51. data/lib/roma/write_behind.rb +179 -0
  52. data/test/rcirb.rb +16 -0
  53. data/test/roma-test-utils.rb +65 -0
  54. data/test/run-test.rb +16 -0
  55. data/test/t_cpdata.rb +277 -0
  56. data/test/t_listplugin.rb +592 -0
  57. data/test/t_rclient.rb +318 -0
  58. data/test/t_routing_data.rb +100 -0
  59. data/test/t_storage.rb +644 -0
  60. data/test/t_writebehind.rb +200 -0
  61. metadata +134 -0
data/test/t_rclient.rb ADDED
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'roma/client/rclient'
5
+
6
+ Roma::Client::RomaClient.class_eval{
7
+ def init_sync_routing_proc
8
+ end
9
+ }
10
+
11
+ class RClientTest < Test::Unit::TestCase
12
+ include RomaTestUtils
13
+
14
+ def setup
15
+ start_roma
16
+ @rc=Roma::Client::RomaClient.new(["localhost_11211","localhost_11212"])
17
+ end
18
+
19
+ def teardown
20
+ stop_roma
21
+ Roma::Messaging::ConPool::instance.close_all
22
+ end
23
+
24
+ def test_set_get_delete
25
+ @rc.delete("abc")
26
+ assert_nil( @rc.get("abc") )
27
+ assert_equal("STORED", @rc.set("abc","value abc"))
28
+ assert_equal("value abc", @rc.get("abc"))
29
+ assert_equal("STORED", @rc.set("abc","value abc")) # 上書きは成功する
30
+ assert_equal("DELETED", @rc.delete("abc"))
31
+ assert_nil( @rc.get("abc"))
32
+ assert_equal("NOT_FOUND", @rc.delete("abc"))
33
+ end
34
+
35
+ def test_set_get
36
+ 10.times{|i|
37
+ s = i.to_s * 1024000
38
+ assert_equal("STORED", @rc.set("abc", s))
39
+ assert(s == @rc.get("abc"))
40
+ }
41
+ end
42
+
43
+ def test_set_gets
44
+ keys = []
45
+ assert_equal(@rc.gets(["key-1","key-2"]).length,0)
46
+ 10.times{|i|
47
+ assert_equal("STORED", @rc.set("key-#{i}", "value-#{i}"))
48
+ keys << "key-#{i}"
49
+ }
50
+ ret = @rc.gets(keys)
51
+ assert_equal(ret.length,10)
52
+ ret.each_pair{|k,v|
53
+ assert_equal(k[-1],v[-1])
54
+ assert_equal(k[0..3],"key-")
55
+ assert_equal(v[0..5],"value-")
56
+ }
57
+ keys << "key-99"
58
+ ret = @rc.gets(keys)
59
+ assert_equal(ret.length,10)
60
+
61
+ assert_equal("DELETED", @rc.delete("key-5"))
62
+ ret = @rc.gets(keys)
63
+ assert_equal(ret.length,9)
64
+ end
65
+
66
+ def test_out
67
+ # 本当に消す
68
+ @rc.out("key-out")
69
+ # 本当にない場合は NOT_DELETED
70
+ assert_equal("NOT_DELETED", @rc.out("key-out"))
71
+ assert_equal("STORED", @rc.set("key-out","value out"))
72
+ assert_equal("DELETED", @rc.out("key-out"))
73
+ assert_equal("STORED", @rc.set("key-out","value out"))
74
+ # 削除マークをつける
75
+ assert_equal("DELETED", @rc.delete("key-out"))
76
+ # delete してもマークを消すので DELETED
77
+ assert_equal("DELETED", @rc.out("key-out"))
78
+ end
79
+
80
+ def test_add
81
+ assert_nil( @rc.get("add") )
82
+ assert_equal("STORED", @rc.add("add","value add"))
83
+ assert_equal("NOT_STORED", @rc.add("add","value add")) # 上書きは失敗する
84
+ assert_equal("DELETED", @rc.delete("add"))
85
+ assert_equal("STORED", @rc.add("add","value add")) # delete 後の add の成功を確認
86
+ assert_equal("DELETED", @rc.delete("add"))
87
+ end
88
+
89
+ def test_replace
90
+ assert_nil( @rc.get("replace") )
91
+ assert_equal("NOT_STORED", @rc.replace("replace","value replace"))
92
+ assert_nil( @rc.get("replace") )
93
+ assert_equal("STORED", @rc.add("replace","value add"))
94
+ assert_equal("STORED", @rc.replace("replace","value replace"))
95
+ assert_equal("DELETED", @rc.delete("replace"))
96
+ end
97
+
98
+ def test_append
99
+ assert_nil( @rc.get("append") )
100
+ assert_equal("NOT_STORED", @rc.append("append","append"))
101
+ assert_equal("STORED", @rc.set("append","set"))
102
+ assert_equal("set", @rc.get("append"))
103
+ assert_equal("STORED", @rc.append("append","append"))
104
+ assert_equal("setappend", @rc.get("append"))
105
+ assert_equal("DELETED", @rc.delete("append"))
106
+ end
107
+
108
+ def test_prepend
109
+ assert_nil( @rc.get("prepend"))
110
+ assert_equal("NOT_STORED", @rc.prepend("prepend","prepend"))
111
+ assert_equal("STORED", @rc.set("prepend","set"))
112
+ assert_equal("set", @rc.get("prepend"))
113
+ assert_equal("STORED", @rc.prepend("prepend","prepend"))
114
+ assert_equal("prependset", @rc.get("prepend"))
115
+ assert_equal("DELETED", @rc.delete("prepend"))
116
+ end
117
+
118
+ def test_incr
119
+ assert_nil( @rc.get("incr"))
120
+ assert_equal("NOT_FOUND", @rc.incr("incr"))
121
+ assert_equal("STORED", @rc.set("incr","100"))
122
+ assert_equal(101, @rc.incr("incr"))
123
+ assert_equal(102, @rc.incr("incr"))
124
+ assert_equal("DELETED", @rc.delete("incr"))
125
+ end
126
+
127
+ def test_decr
128
+ assert_nil( @rc.get("decr") )
129
+ assert_equal("NOT_FOUND", @rc.decr("decr"))
130
+ assert_equal("STORED", @rc.set("decr","100"))
131
+ assert_equal(99, @rc.decr("decr"))
132
+ assert_equal(98, @rc.decr("decr"))
133
+ assert_equal("DELETED", @rc.delete("decr"))
134
+ end
135
+
136
+ def test_createhash
137
+ con = Roma::Messaging::ConPool.instance.get_connection("localhost_11211")
138
+ con.write("hashlist\r\n")
139
+ ret = con.gets
140
+ assert_equal("roma", ret.chomp )
141
+
142
+ con.write("createhash test\r\n")
143
+ ret = con.gets
144
+ assert_equal("{\"localhost_11212\"=>\"CREATED\", \"localhost_11211\"=>\"CREATED\"}", ret.chomp )
145
+
146
+ con.write("hashlist\r\n")
147
+ ret = con.gets
148
+ assert_equal("roma test", ret.chomp )
149
+
150
+ assert_equal("STORED", @rc.set("roma","hname=roma"))
151
+ assert_equal("hname=roma", @rc.get("roma"))
152
+ @rc.default_hash_name='test'
153
+ assert_nil( @rc.get("roma") )
154
+ assert_equal("STORED", @rc.set("roma","hname=test"))
155
+ assert_equal("hname=test", @rc.get("roma"))
156
+ @rc.default_hash_name='roma'
157
+ assert_equal("hname=roma", @rc.get("roma"))
158
+ assert_equal("DELETED", @rc.delete("roma"))
159
+
160
+ @rc.default_hash_name='not_exist_hash' # 存在しないハッシュへのアクセス
161
+ begin
162
+ @rc.get("roma")
163
+ assert(false)
164
+ rescue =>e
165
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
166
+ end
167
+
168
+ begin
169
+ @rc.set("roma","hname=roma")
170
+ assert(false)
171
+ rescue =>e
172
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
173
+ end
174
+
175
+ begin
176
+ @rc.delete("roma")
177
+ assert(false)
178
+ rescue =>e
179
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
180
+ end
181
+
182
+ begin
183
+ @rc.add("add","value add")
184
+ assert(false)
185
+ rescue =>e
186
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
187
+ end
188
+
189
+ begin
190
+ @rc.replace("replace","value replace")
191
+ assert(false)
192
+ rescue =>e
193
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
194
+ end
195
+
196
+ begin
197
+ @rc.append("append","append")
198
+ assert(false)
199
+ rescue =>e
200
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.', e.message)
201
+ end
202
+
203
+ begin
204
+ @rc.prepend("prepend","prepend")
205
+ assert(false)
206
+ rescue =>e
207
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
208
+ end
209
+
210
+ begin
211
+ @rc.incr("incr")
212
+ assert(false)
213
+ rescue =>e
214
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
215
+ end
216
+
217
+ begin
218
+ @rc.decr("decr")
219
+ assert(false)
220
+ rescue =>e
221
+ assert_equal('SERVER_ERROR not_exist_hash dose not exists.',e.message)
222
+ end
223
+
224
+ con.write("deletehash test\r\n")
225
+ ret = con.gets
226
+ assert_equal( "{\"localhost_11212\"=>\"DELETED\", \"localhost_11211\"=>\"DELETED\"}", ret.chomp )
227
+
228
+ con.close
229
+ end
230
+
231
+ def test_createhash2
232
+ # test ハッシュを追加し終了する
233
+ con = Roma::Messaging::ConPool.instance.get_connection("localhost_11211")
234
+ con.write("hashlist\r\n")
235
+ ret = con.gets
236
+ assert_equal("roma", ret.chomp)
237
+
238
+ con.write("createhash test\r\n")
239
+ ret = con.gets
240
+ assert_equal("{\"localhost_11212\"=>\"CREATED\", \"localhost_11211\"=>\"CREATED\"}", ret.chomp )
241
+
242
+ assert_equal("STORED", @rc.set("roma","hname=roma"))
243
+ assert_equal("hname=roma", @rc.get("roma"))
244
+ @rc.default_hash_name='test'
245
+ assert_equal("STORED", @rc.set("roma","hname=test"))
246
+ assert_equal("hname=test", @rc.get("roma"))
247
+ con.write("balse\r\n")
248
+ con.gets
249
+ con.write "yes\r\n"
250
+ ret = con.gets
251
+ con.close
252
+
253
+
254
+ # 再起動
255
+ ruby_path = File.join(RbConfig::CONFIG["bindir"],
256
+ RbConfig::CONFIG["ruby_install_name"])
257
+ path = File.dirname(File.expand_path($PROGRAM_NAME))
258
+ sh = Shell.new
259
+ sh.system(ruby_path,"#{path}/../bin/romad","localhost","-p","11211","-d","--verbose")
260
+ sh.system(ruby_path,"#{path}/../bin/romad","localhost","-p","11212","-d","--verbose")
261
+ sleep 2
262
+ Roma::Messaging::ConPool.instance.close_all
263
+
264
+ @rc=Roma::Client::RomaClient.new(["localhost_11211","localhost_11212"])
265
+ @rc.default_hash_name='test'
266
+ con = Roma::Messaging::ConPool.instance.get_connection("localhost_11211")
267
+ con.write("hashlist\r\n")
268
+ ret = con.gets
269
+
270
+ #
271
+ # for file storage
272
+ #
273
+
274
+ # 停止前のデータが残っていることを確認
275
+ #assert_equal("hname=test", @rc.get("roma"))
276
+
277
+ # test ハッシュを削除
278
+ #con.write("deletehash test\r\n")
279
+ #ret = con.gets
280
+ #assert_equal("{\"localhost_11212\"=>\"DELETED\", \"localhost_11211\"=>\"DELETED\"}", ret.chomp )
281
+
282
+ # デフォルトハッシュに残ったテストデータを削除
283
+ #@rc.default_hash_name='roma'
284
+ #assert_equal('DELETED', @rc.delete("roma"))
285
+
286
+ end
287
+
288
+ def test_createhash3
289
+ con = Roma::Messaging::ConPool.instance.get_connection("localhost_11211")
290
+
291
+ # 存在しないハッシュを削除
292
+ con.write("deletehash test\r\n")
293
+ ret = con.gets
294
+ assert_equal("{\"localhost_11212\"=>\"SERVER_ERROR test dose not exists.\", \"localhost_11211\"=>\"SERVER_ERROR test dose not exists.\"}", ret.chomp )
295
+
296
+ # デフォルトハッシュを削除
297
+ con.write("deletehash roma\r\n")
298
+ ret = con.gets
299
+ assert_equal("{\"localhost_11212\"=>\"SERVER_ERROR the hash name of 'roma' can't delete.\", \"localhost_11211\"=>\"SERVER_ERROR the hash name of 'roma' can't delete.\"}", ret.chomp )
300
+ end
301
+ end
302
+
303
+ class RClientTestForceForward < RClientTest
304
+ def setup
305
+ super
306
+ @rc.rttable.instance_eval{
307
+ undef search_node
308
+
309
+ def search_node(key); search_node2(key); end
310
+
311
+ def search_node2(key)
312
+ d = Digest::SHA1.hexdigest(key).hex % @hbits
313
+ @rd.v_idx[d & @search_mask][1]
314
+ end
315
+ }
316
+ end
317
+
318
+ end
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'roma/routing/routing_data'
5
+ require 'yaml'
6
+
7
+ class RoutingDataTest < Test::Unit::TestCase
8
+ def setup
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def cnt_obj
15
+ GC.start
16
+ n=0
17
+ ObjectSpace.each_object{|o| n+=1 }
18
+ n
19
+ end
20
+
21
+ def test_object_count
22
+ c1=cnt_obj
23
+ rd=Roma::Routing::RoutingData.create(32,9,2,['roma0_11211','roma0_11212'])
24
+ c2=cnt_obj
25
+ puts
26
+ puts "RoutingData.create #{c2-c1} objects"
27
+ c1=c2
28
+ rd.save("routing_data.test.route")
29
+ rd2=Roma::Routing::RoutingData.load("routing_data.test.route")
30
+ c2=cnt_obj
31
+ puts "RoutingData.load #{c2-c1} objects"
32
+ File::unlink("routing_data.test.route")
33
+ end
34
+
35
+ def test_save_load
36
+ rd=Roma::Routing::RoutingData.create(32,8,1,['roma0_3300'])
37
+ rd.save("routing_data.test.route")
38
+ rd2=Roma::Routing::RoutingData.load("routing_data.test.route")
39
+ assert( YAML.dump(rd) == YAML.dump(rd2) )
40
+ File::unlink("routing_data.test.route")
41
+ end
42
+
43
+ def test_next_vnode
44
+ rd=Roma::Routing::RoutingData.create(32,8,1,['roma0_3300'])
45
+ assert( 0x01000000 == rd.next_vnode(0x00000000) )
46
+ assert( 0x00000000 == rd.next_vnode(0xff000000) )
47
+ assert( 0x56000000 == rd.next_vnode(0x55000000) )
48
+ end
49
+
50
+ def test_create_nodes_from_v_idx
51
+ rd=Roma::Routing::RoutingData.create(32,8,1,['roma0','roma1','roma2'])
52
+ rd.nodes.clear
53
+ rd.create_nodes_from_v_idx
54
+ assert( rd.nodes == ['roma0','roma1','roma2'] )
55
+ end
56
+
57
+ def test_create
58
+ # ダイジェストの総ビット数 32
59
+ # バーチャルノードのビット数 8
60
+ # 冗長度 1
61
+ # ノードIDの配列 [roma0_3300]
62
+ rd=Roma::Routing::RoutingData.create(32,8,1,['roma0_3300'])
63
+
64
+ assert( rd.v_idx.length==256 )
65
+ assert( rd.nodes.length==1 )
66
+ assert( rd.search_mask==0xff000000 )
67
+ assert( rd.dgst_bits==32 )
68
+ assert( rd.div_bits==8 )
69
+ assert( rd.rn==1 )
70
+
71
+ # ダイジェストの総ビット数 32
72
+ # バーチャルノードのビット数 16
73
+ # 冗長度 2
74
+ # ノードIDの配列 ['roma0_3300','roma1_3300','roma2_3300']
75
+ rd=Roma::Routing::RoutingData.create(32,16,2,['roma0_3300','roma1_3300','roma2_3300'])
76
+
77
+ assert( rd.v_idx.length==65536 )
78
+ assert( rd.nodes.length==3 )
79
+ assert( rd.search_mask==0xffff0000 )
80
+ assert( rd.dgst_bits==32 )
81
+ assert( rd.div_bits==16 )
82
+ assert( rd.rn==2 )
83
+
84
+ c0=c1=c2=0
85
+ rd.v_idx.each_value{|v|
86
+ case v[0]
87
+ when 'roma0_3300'
88
+ c0+=1
89
+ when 'roma1_3300'
90
+ c1+=1
91
+ when 'roma2_3300'
92
+ c2+=1
93
+ end
94
+ }
95
+ # バラつきは10%より小さいでしょ
96
+ assert( (c0-c1).abs < rd.v_idx.length/10 )
97
+ assert( (c1-c2).abs < rd.v_idx.length/10 )
98
+ end
99
+
100
+ end