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
@@ -0,0 +1,73 @@
1
+ require 'sqlite3'
2
+ require 'roma/storage/basic_storage'
3
+
4
+ module Roma
5
+ module Storage
6
+
7
+ module SQLite3_Ext
8
+ def put(k,v)
9
+ if self.execute("select count(*) from t_roma where key=?",k)[0][0].to_i==0
10
+ self.execute("insert into t_roma values (?,?)",k,SQLite3::Blob.new(v))
11
+ else
12
+ self.execute("update t_roma set val=? where key=?",SQLite3::Blob.new(v),k)
13
+ end
14
+ end
15
+
16
+ def get(k)
17
+ r = self.execute("select * from t_roma where key=?",k)
18
+ return nil if r.length==0
19
+ r[0][1]
20
+ end
21
+
22
+ def out(k)
23
+ return nil if get(k) == nil
24
+ self.execute("delete from t_roma where key=?",k)
25
+ end
26
+
27
+ def rnum
28
+ self.execute("select count(*) from t_roma")[0][0].to_i
29
+ end
30
+
31
+ def each
32
+ self.execute("select * from t_roma"){ |r|
33
+ yield r[0],r[1]
34
+ }
35
+ end
36
+
37
+ def create_table
38
+ sql = "create table t_roma ( " +
39
+ "key TEXT PRIMARY KEY," +
40
+ "val BLOB);"
41
+ self.execute( sql )
42
+ end
43
+
44
+ def tables
45
+ sql = "SELECT name FROM " +
46
+ "sqlite_master WHERE type='table' UNION ALL SELECT name FROM sqlite_temp_master " +
47
+ "WHERE type='table' ORDER BY name;"
48
+ self.execute( sql ).flatten
49
+ end
50
+ end
51
+
52
+ class SQLite3Storage < BasicStorage
53
+
54
+ def initialize
55
+ super
56
+ @ext_name = 'sql3'
57
+ end
58
+
59
+ private
60
+
61
+ def open_db(fname)
62
+ hdb = SQLite3::Database.new(fname)
63
+ hdb.extend(Roma::Storage::SQLite3_Ext)
64
+ hdb.create_table if hdb.tables.length == 0
65
+ hdb
66
+ end
67
+
68
+ def close_db(hdb); hdb.close; end
69
+
70
+ end # class SQLite3Storage
71
+
72
+ end # module Storage
73
+ end # module Roma
@@ -0,0 +1,133 @@
1
+ require 'tokyocabinet'
2
+ require 'roma/storage/basic_storage'
3
+
4
+ module Roma
5
+ module Storage
6
+
7
+ class TCStorage < BasicStorage
8
+ include TokyoCabinet
9
+
10
+ def initialize
11
+ super
12
+ @ext_name = 'tc'
13
+ end
14
+
15
+ def get_stat
16
+ ret = super
17
+ @hdb.each_with_index{|hdb,idx|
18
+ ret["storage[#{idx}].path"] = File.expand_path(hdb.path)
19
+ ret["storage[#{idx}].rnum"] = hdb.rnum
20
+ ret["storage[#{idx}].fsiz"] = hdb.fsiz
21
+ }
22
+ ret
23
+ end
24
+
25
+ protected
26
+
27
+ def set_options(hdb)
28
+ prop = parse_options
29
+
30
+ prop.each_key{|k|
31
+ unless /^(bnum|apow|fpow|opts|xmsiz|rcnum|dfunit)$/ =~ k
32
+ raise RuntimeError.new("Syntax error, unexpected option #{k}")
33
+ end
34
+ }
35
+
36
+ opts = 0
37
+ if prop.key?('opts')
38
+ opts |= HDB::TLARGE if prop['opts'].include?('l')
39
+ opts |= HDB::TDEFLATE if prop['opts'].include?('d')
40
+ opts |= HDB::TBZIP if prop['opts'].include?('b')
41
+ opts |= HDB::TTCBS if prop['opts'].include?('t')
42
+ end
43
+
44
+ hdb.tune(prop['bnum'].to_i,prop['apow'].to_i,prop['fpow'].to_i,opts)
45
+
46
+ hdb.setxmsiz(prop['xmsiz'].to_i) if prop.key?('xmsiz')
47
+ hdb.setcache(prop['rcnum'].to_i) if prop.key?('rcnum')
48
+ hdb.setdfunit(prop['dfunit'].to_i) if prop.key?('dfunit')
49
+ end
50
+
51
+ private
52
+
53
+ def parse_options
54
+ return Hash.new(-1) unless @option
55
+ buf = @option.split('#')
56
+ prop = Hash.new(-1)
57
+ buf.each{|equ|
58
+ if /(\S+)\s*=\s*(\S+)/ =~ equ
59
+ prop[$1] = $2
60
+ else
61
+ raise RuntimeError.new("Option string parse error.")
62
+ end
63
+ }
64
+ prop
65
+ end
66
+
67
+ def open_db(fname)
68
+ hdb = HDB::new
69
+
70
+ set_options(hdb)
71
+
72
+ if !hdb.open(fname, HDB::OWRITER | HDB::OCREAT | HDB::ONOLCK)
73
+ ecode = hdb.ecode
74
+ raise RuntimeError.new("tcdb open error #{hdb.errmsg(ecode)}")
75
+ end
76
+ hdb
77
+ end
78
+
79
+ def close_db(hdb)
80
+ if !hdb.close
81
+ ecode = hdb.ecode
82
+ raise RuntimeError.new("tcdb close error #{hdb.errmsg(ecode)}")
83
+ end
84
+ end
85
+
86
+ end # class TCStorage
87
+
88
+ class TCAsyncStorage < TCStorage
89
+ private
90
+
91
+ def open_db(fname)
92
+ hdb = HDB::new
93
+
94
+ set_options(hdb)
95
+
96
+ hdb.instance_eval{
97
+ alias put putasync
98
+ }
99
+
100
+ if !hdb.open(fname, HDB::OWRITER | HDB::OCREAT)
101
+ ecode = hdb.ecode
102
+ raise RuntimeError.new("tcdb open error #{hdb.errmsg(ecode)}")
103
+ end
104
+
105
+ Thread.new {
106
+ loop{
107
+ sleep 10
108
+ hdb.sync
109
+ }
110
+ }
111
+
112
+ hdb
113
+ end
114
+ end # class TCAsyncStorage
115
+
116
+
117
+ class TCMemStorage < BasicStorage
118
+ include TokyoCabinet
119
+
120
+ private
121
+
122
+ def open_db(fname)
123
+ hdb = ADB::new
124
+ hdb.open("*")
125
+ hdb
126
+ end
127
+
128
+ def close_db(hdb); end
129
+
130
+ end # class TCMemStorage
131
+
132
+ end # module Storage
133
+ end # module Roma
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # usage:mkrecent dgst-bits div-bits divnum storage-path1 storage-path2 recent-storage-path
5
+ #
6
+ require 'roma/routing/routing_data'
7
+
8
+ module Roma
9
+ module Storage
10
+ end
11
+ Storage::autoload(:TCStorage,'roma/storage/tc_storage')
12
+ Storage::autoload(:DbmStorage,'roma/storage/dbm_storage')
13
+ Storage::autoload(:SQLite3Storage,'roma/storage/sqlite3_storage')
14
+
15
+ class MakeRecentData
16
+
17
+ def initialize(argv = nil)
18
+ if argv.length != 6
19
+ STDERR.puts "usage:mkrecent dgst-bits div-bits divnum storage-path1 storage-path2 recent-storage-path"
20
+ exit
21
+ end
22
+
23
+ dgst_bits = argv[0].to_i
24
+ div_bits = argv[1].to_i
25
+ @divnum = argv[2].to_i
26
+ @strgpath1 = argv[3]
27
+ @strgpath2 = argv[4]
28
+ @recentpath = argv[5]
29
+
30
+ @vnodes = []
31
+ (2**div_bits).times{|i|
32
+ @vnodes << ( i<<(dgst_bits-div_bits) )
33
+ }
34
+ end
35
+
36
+ def suite
37
+ if File::directory?(@recentpath)
38
+ STDERR.puts "#{@recentpath} exists."
39
+ exit
40
+ end
41
+
42
+ Dir::mkdir(@recentpath)
43
+
44
+ Dir::glob("#{@strgpath1}/*").each{|dir|
45
+ next unless File::directory?(dir)
46
+ hname = dir[dir.rindex('/')+1..-1]
47
+ open_storage(dir,
48
+ "#{@strgpath2}/#{hname}",
49
+ "#{@recentpath}/#{hname}")
50
+ exec(hname)
51
+
52
+ close_storage
53
+ }
54
+ end
55
+
56
+ def open_storage(p1,p2,rp)
57
+ puts "Open #{p1}"
58
+ @st1 = ropen(p1)
59
+ @st1.each_vn_dump_sleep = 0
60
+ exit unless @st1
61
+ puts "Open #{p2}"
62
+ @st2 = ropen(p2)
63
+ @st2.each_vn_dump_sleep = 0
64
+ unless @st2
65
+ STDERR.puts ""
66
+ @st1.closedb
67
+ exit
68
+ end
69
+
70
+ if @st1.class != @st2.class
71
+ STDERR.puts "#{p1} and #{p2} that file type is different."
72
+ @st1.closedb
73
+ @st2.closedb
74
+ exit
75
+ end
76
+
77
+ puts "Open #{rp}"
78
+ @rst = @st1.class.new
79
+ @rst.divnum = @divnum
80
+ @rst.vn_list = @vnodes
81
+ @rst.storage_path = rp
82
+ @rst.opendb
83
+ end
84
+
85
+ def close_storage
86
+ @st1.closedb
87
+ @st2.closedb
88
+ @rst.closedb
89
+ end
90
+
91
+ def exec(hname)
92
+ n = 0
93
+ @vnodes.each{|vn|
94
+ printf "#{hname}:#{n}/#{@vnodes.length}\r"
95
+ n+=1
96
+ buf = @st1.dump(vn)
97
+ @rst.load( buf ) if buf
98
+ buf = @st2.dump(vn)
99
+ @rst.load( buf ) if buf
100
+ }
101
+ end
102
+
103
+ private
104
+
105
+ def ropen(path)
106
+ unless File::directory?(path)
107
+ STDERR.puts "#{path} dose not found."
108
+ return nil
109
+ end
110
+
111
+ ext = File::extname(Dir::glob("#{path}/0.*")[0])[1..-1]
112
+
113
+ storage = new_storage(ext)
114
+ storage.divnum = @divnum
115
+ storage.vn_list = @vnodes
116
+ storage.storage_path = path
117
+ storage.opendb
118
+ storage
119
+ end
120
+
121
+ def new_storage(ext)
122
+ case(ext)
123
+ when 'tc'
124
+ return ::Roma::Storage::TCStorage.new
125
+ when 'dbm'
126
+ return Roma::Storage::DbmStorage.new
127
+ when 'sql3'
128
+ return Roma::Storage::SQLite3Storage.new
129
+ else
130
+ return nil
131
+ end
132
+ end
133
+
134
+ end # MakeRecentData
135
+ end # module Roma
136
+
137
+ Roma::MakeRecentData.new(ARGV).suite
138
+ puts "Make recent data process has succeed."
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'optparse'
4
+ require 'roma/routing/routing_data'
5
+
6
+ # ダイジェストのビット数
7
+ dgst_bits=32
8
+ # 分割ビット数 (dgst_bits >= div_bits)
9
+ div_bits=9
10
+ # 冗長度 (nodes.length >= rn)
11
+ rn=2
12
+ # ホスト名の重複許可
13
+ repeathost=false
14
+
15
+ opts = OptionParser.new
16
+ opts.banner = "usage:#{File.basename($0)} [options] node-id..."
17
+ opts.on("-h","--hash [bits]","(default=32)"){|v| dgst_bits = v.to_i }
18
+ opts.on("-d","--divide [bits]","(default=9)"){|v| div_bits = v.to_i }
19
+ opts.on("-r","--redundant [num]","(default=2)"){|v| rn = v.to_i }
20
+ opts.on(nil,"--enabled_repeathost"){|v| repeathost=true }
21
+ opts.parse!(ARGV)
22
+
23
+ nodes = ARGV
24
+ nodes.map!{|n| n.sub(':','_')}
25
+
26
+ if nodes.length == 0
27
+ STDERR.puts opts.help
28
+ exit!
29
+ end
30
+
31
+ if dgst_bits < div_bits
32
+ STDERR.puts "The hash bits should be divide bits or more."
33
+ exit!
34
+ end
35
+
36
+ if div_bits > 32
37
+ STDERR.puts "The upper bound of divide bits is 32."
38
+ exit!
39
+ end
40
+
41
+ if nodes.length < rn
42
+ STDERR.puts "The node-id number should be redundant number or more."
43
+ exit!
44
+ end
45
+
46
+ rt = Roma::Routing::RoutingData::create(dgst_bits,div_bits,rn,nodes,repeathost)
47
+
48
+ nodes.each{|nid|
49
+ rt.save("#{nid}.route")
50
+ }
51
+ puts "nodes => #{nodes}"
52
+ puts "Routing table has created."
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # usage:recoverlost address port storage-path [yyyymmddhhmmss]
5
+ #
6
+ require 'roma/tools/recoverlost_lib'
7
+
8
+ Roma::RecoverLost.new('recoverlost', 'spushv', ARGV).suite
9
+ puts "Recover process has succeed."
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # usage:recoverlost_alist address port storage-path [yyyymmddhhmmss]
5
+ #
6
+ require 'roma/tools/recoverlost_lib'
7
+
8
+ Roma::RecoverLost.new('recoverlost_alist', 'alist_spushv', ARGV).suite
9
+ puts "Recover process has succeed."
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # usage:recoverlost address port storage-path [yyyymmddhhmmss]
5
+ #
6
+ require 'roma/client/sender'
7
+ require 'roma/messaging/con_pool'
8
+ require 'roma/routing/routing_data'
9
+
10
+ module Roma
11
+ module Storage
12
+ end
13
+ Storage::autoload(:TCStorage,'roma/storage/tc_storage')
14
+ Storage::autoload(:DbmStorage,'roma/storage/dbm_storage')
15
+ Storage::autoload(:SQLite3Storage,'roma/storage/sqlite3_storage')
16
+
17
+ class RecoverLost
18
+
19
+ def initialize(pname, pushv_cmd, argv)
20
+ if argv.length < 3
21
+ puts "usage:#{pname} address port storage-path [yyyymmddhhmmss]"
22
+ exit
23
+ end
24
+
25
+ @addr = argv[0]
26
+ @port = argv[1]
27
+ @strgpath = argv[2]
28
+ @ymdhms = argv[3]
29
+
30
+ if @port =~ /\D/
31
+ STDERR.puts "port was not numeric."
32
+ exit
33
+ end
34
+
35
+ if @ymdhms && (@ymdhms.length != 14 || @ymdhms =~ /\D/)
36
+ STDERR.puts "yyyymmddhhmmss format mismatch."
37
+ exit
38
+ end
39
+ @pushv_cmd = pushv_cmd
40
+ @nodeid = "#{@addr}_#{@port}"
41
+ @stream_copy_wait_param = 0.0001
42
+ end
43
+
44
+ def suite
45
+ @rd = get_routing_data(@nodeid)
46
+ @lost_vnodes = get_lost_vnodes(@rd,@ymdhms)
47
+ puts "#{@lost_vnodes.length} vnodes where data was lost."
48
+
49
+ exit if @lost_vnodes.length == 0
50
+
51
+ each_hash(@strgpath){|hname,dir|
52
+ puts "#{hname} #{dir}"
53
+ @storage = open_storage(dir,@lost_vnodes)
54
+ start_recover(hname)
55
+ @storage.closedb
56
+ }
57
+ end
58
+
59
+ def each_hash(path)
60
+ Dir::glob("#{path}/*").each{|dir|
61
+ next unless File::directory?(dir)
62
+ hname = dir[dir.rindex('/')+1..-1]
63
+ yield hname,dir
64
+ }
65
+ end
66
+
67
+ def get_routing_data(nid)
68
+ sender = Roma::Client::Sender.new
69
+ sender.send_routedump_command(nid)
70
+ end
71
+
72
+ def get_lost_vnodes(rd,ymdhms)
73
+ ret = rd.get_lost_vnodes
74
+ if ymdhms
75
+ ret |= get_history_of_lost(rd.nodes[0],ymdhms)
76
+ end
77
+ ret
78
+ end
79
+
80
+ def get_history_of_lost(nid,ymdhms)
81
+ ret = []
82
+ con = Roma::Messaging::ConPool.instance.get_connection(nid)
83
+ con.write("history_of_lost #{ymdhms}\r\n")
84
+ while((buf = con.gets) != "END\r\n")
85
+ ret << buf.chomp.to_i
86
+ end
87
+ Roma::Messaging::ConPool.instance.return_connection(nid, con)
88
+ ret
89
+ end
90
+
91
+ def open_storage(path,vn_list)
92
+ unless File::directory?(path)
93
+ STDERR.puts "#{path} dose not found."
94
+ return nil
95
+ end
96
+
97
+ # get a file extension
98
+ ext = File::extname(Dir::glob("#{path}/0.*")[0])[1..-1]
99
+ # count a number of divided files
100
+ divnum = Dir::glob("#{path}/*.#{ext}").length
101
+
102
+ st = new_storage(ext)
103
+ st.divnum = divnum
104
+ st.vn_list = vn_list
105
+ st.storage_path = path
106
+ st.opendb
107
+ st
108
+ end
109
+
110
+ def new_storage(ext)
111
+ case(ext)
112
+ when 'tc'
113
+ return ::Roma::Storage::TCStorage.new
114
+ when 'dbm'
115
+ return Roma::Storage::DbmStorage.new
116
+ when 'sql3'
117
+ return Roma::Storage::SQLite3Storage.new
118
+ else
119
+ return nil
120
+ end
121
+ end
122
+
123
+ def start_recover(hname)
124
+ @lost_vnodes.each{|vn|
125
+ nodes = @rd.v_idx[vn]
126
+ if nodes == nil || nodes.length == 0
127
+ nid = @rd.nodes[rand(@rd.nodes.length)]
128
+ puts "#{vn} assign to #{nid}"
129
+ else
130
+ nid = nodes[0]
131
+ puts "#{vn} was auto assirned at #{nid}"
132
+ end
133
+
134
+ if push_a_vnode_stream(hname, vn, nid)!="STORED"
135
+ STDERR.puts "push_a_vnode_stream aborted in #{vn}"
136
+ exit
137
+ end
138
+
139
+ if nodes == nil || nodes.length == 0
140
+ cmd = "setroute #{vn} #{@rd.v_clk[vn]} #{nid}\r\n"
141
+ exit unless send_cmd(nid ,cmd)
142
+ broadcast_cmd(cmd, nid)
143
+ end
144
+ }
145
+ end
146
+
147
+ def push_a_vnode(hname, vn, nid)
148
+ dmp = @storage.dump(vn)
149
+ return true unless dmp
150
+ con = Roma::Messaging::ConPool.instance.get_connection(nid) unless con
151
+ con.write("pushv #{hname} #{vn}\r\n")
152
+ res = con.gets
153
+ con.write("#{dmp.length}\r\n#{dmp}\r\nEND\r\n")
154
+ res = con.gets
155
+ con.close
156
+ res.chomp! if res
157
+ res
158
+ rescue =>e
159
+ STDERR.puts "#{e}\n#{$@}"
160
+ nil
161
+ end
162
+
163
+ def push_a_vnode_stream(hname, vn, nid)
164
+ con = Roma::Messaging::ConPool.instance.get_connection(nid)
165
+
166
+ # con.write("spushv #{hname} #{vn}\r\n")
167
+ con.write("#{@pushv_cmd} #{hname} #{vn}\r\n")
168
+
169
+ res = con.gets # READY\r\n or error string
170
+ if res != "READY\r\n"
171
+ con.close
172
+ return res.chomp
173
+ end
174
+
175
+ @storage.each_vn_dump(vn){|data|
176
+ con.write(data)
177
+ sleep @stream_copy_wait_param
178
+ }
179
+ con.write("\0"*20) # end of steram
180
+
181
+ res = con.gets # STORED\r\n or error string
182
+ Roma::Messaging::ConPool.instance.return_connection(nid,con)
183
+ res.chomp! if res
184
+ res
185
+ rescue =>e
186
+ STDERR.puts "#{e}\n#{$@}"
187
+ nil
188
+ end
189
+
190
+ def broadcast_cmd(cmd,without_nids=nil)
191
+ without_nids=[] unless without_nids
192
+ res = {}
193
+ @rd.nodes.each{ |nid|
194
+ res[nid] = send_cmd(nid,cmd) unless without_nids.include?(nid)
195
+ }
196
+ res
197
+ rescue => e
198
+ STDERR.puts("#{e}\n#{$@}")
199
+ nil
200
+ end
201
+
202
+ def send_cmd(nid, cmd)
203
+ con = Roma::Messaging::ConPool.instance.get_connection(nid)
204
+ con.write(cmd)
205
+ res = con.gets
206
+ Roma::Messaging::ConPool.instance.return_connection(nid, con)
207
+ if res
208
+ res.chomp!
209
+ end
210
+ res
211
+ rescue => e
212
+ STDERR.puts("#{__FILE__}:#{__LINE__}:Send command failed that node-id is #{nid},command is #{cmd}.")
213
+ nil
214
+ end
215
+
216
+ end # class RecoverLost
217
+ end # module Roma
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'roma/commons'
4
+ require 'roma/client/sender'
5
+
6
+ module Roma
7
+
8
+ class Watcher
9
+
10
+ def initialize
11
+ @sender = Roma::Client::Sender.new
12
+ end
13
+
14
+ def get_node_list(nid)
15
+ @sender.send_command(nid, "nodelist").split(' ')
16
+ end
17
+
18
+ end # class Watcher
19
+
20
+ end # module Roma
21
+
22
+
23
+ w = Roma::Watcher.new
24
+
25
+ # 監視ノードの定義
26
+ nodes = ['roma0:11211','roma0:11212','roma0:11213','roma0:11214']
27
+
28
+ nodes.each{|nid|
29
+ begin
30
+ if w.get_node_list(nid).length != nodes.length
31
+ STDERR.puts "fail over occurred in #{nid}."
32
+ end
33
+ rescue
34
+ STDERR.puts "command error in #{nid}."
35
+ end
36
+ }
37
+
38
+ puts "#{Time.now} ROMA watcher has done."
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'roma/commons'
4
+ require 'roma/client/sender'
5
+
6
+ module Roma
7
+
8
+ class Watcher
9
+
10
+ def initialize
11
+ @sender = Roma::Client::Sender.new
12
+ end
13
+
14
+ def watch(nid, command)
15
+ ret = @sender.send_command(nid, command, value = nil, :multiplelines_receiver)
16
+ end
17
+ end # class Watcher
18
+
19
+ end # module Roma
20
+
21
+ w = Roma::Watcher.new
22
+
23
+ # the definition of all nodes
24
+ nodes = ['roma0:11211','roma0:11212']
25
+
26
+ nodes.each{|nid|
27
+ begin
28
+ ret = w.watch(nid, "stat #{ARGV[0]}")
29
+ puts "/********** #{nid} **********/"
30
+ ret.each{|l|
31
+ puts l
32
+ }
33
+ rescue
34
+ STDERR.puts "command error in #{nid}."
35
+ end
36
+ }
37
+
38
+ puts "#{Time.now} ROMA watcher2 has done."