roma 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.rdoc +675 -0
- data/README.rdoc +0 -0
- data/Rakefile +70 -0
- data/bin/mkrecent +7 -0
- data/bin/mkroute +7 -0
- data/bin/recoverlost +8 -0
- data/bin/recoverlost_alist +8 -0
- data/bin/romad +7 -0
- data/bin/sample_watcher +8 -0
- data/bin/sample_watcher2 +8 -0
- data/bin/simple_bench +8 -0
- data/bin/ssroute +7 -0
- data/bin/tribunus +7 -0
- data/lib/roma/async_process.rb +696 -0
- data/lib/roma/command/bg_command_receiver.rb +188 -0
- data/lib/roma/command/mh_command_receiver.rb +117 -0
- data/lib/roma/command/receiver.rb +287 -0
- data/lib/roma/command/rt_command_receiver.rb +147 -0
- data/lib/roma/command/st_command_receiver.rb +564 -0
- data/lib/roma/command/util_command_receiver.rb +67 -0
- data/lib/roma/command/vn_command_receiver.rb +143 -0
- data/lib/roma/command_plugin.rb +11 -0
- data/lib/roma/config.rb +64 -0
- data/lib/roma/event/con_pool.rb +140 -0
- data/lib/roma/event/handler.rb +159 -0
- data/lib/roma/plugin/plugin_alist.rb +1572 -0
- data/lib/roma/plugin/plugin_debug.rb +19 -0
- data/lib/roma/plugin/plugin_test.rb +14 -0
- data/lib/roma/romad.rb +582 -0
- data/lib/roma/routing/cb_rttable.rb +326 -0
- data/lib/roma/routing/merkle_tree.rb +54 -0
- data/lib/roma/routing/rttable.rb +148 -0
- data/lib/roma/stats.rb +112 -0
- data/lib/roma/storage/basic_storage.rb +510 -0
- data/lib/roma/storage/dbm_storage.rb +80 -0
- data/lib/roma/storage/dummy_storage.rb +44 -0
- data/lib/roma/storage/rh_storage.rb +35 -0
- data/lib/roma/storage/sqlite3_storage.rb +73 -0
- data/lib/roma/storage/tc_storage.rb +133 -0
- data/lib/roma/tools/mkrecent.rb +138 -0
- data/lib/roma/tools/mkroute.rb +52 -0
- data/lib/roma/tools/recoverlost.rb +9 -0
- data/lib/roma/tools/recoverlost_alist.rb +9 -0
- data/lib/roma/tools/recoverlost_lib.rb +217 -0
- data/lib/roma/tools/sample_watcher.rb +38 -0
- data/lib/roma/tools/sample_watcher2.rb +38 -0
- data/lib/roma/tools/simple_bench.rb +57 -0
- data/lib/roma/tools/ssroute.rb +23 -0
- data/lib/roma/tools/tribunus.rb +299 -0
- data/lib/roma/version.rb +4 -0
- data/lib/roma/write_behind.rb +179 -0
- data/test/rcirb.rb +16 -0
- data/test/roma-test-utils.rb +65 -0
- data/test/run-test.rb +16 -0
- data/test/t_cpdata.rb +277 -0
- data/test/t_listplugin.rb +592 -0
- data/test/t_rclient.rb +318 -0
- data/test/t_routing_data.rb +100 -0
- data/test/t_storage.rb +644 -0
- data/test/t_writebehind.rb +200 -0
- 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_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."
|