roma 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
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."