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.
- 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."
|