roma 0.8.13 → 0.8.14
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.
- checksums.yaml +7 -0
- data/CHANGELOG +20 -0
- data/Gemfile +17 -0
- data/Rakefile +2 -2
- data/ruby/server/bin/cpdb +6 -0
- data/ruby/server/bin/safecopy_integration_test +10 -0
- data/ruby/server/bin/safecopy_test +10 -0
- data/ruby/server/lib/roma/async_process.rb +87 -3
- data/ruby/server/lib/roma/command/sys_command_receiver.rb +181 -5
- data/ruby/server/lib/roma/command/vn_command_receiver.rb +9 -3
- data/ruby/server/lib/roma/event/con_pool.rb +1 -1
- data/ruby/server/lib/roma/event/handler.rb +11 -5
- data/ruby/server/lib/roma/messaging/con_pool.rb +1 -1
- data/ruby/server/lib/roma/romad.rb +3 -1
- data/ruby/server/lib/roma/stats.rb +19 -1
- data/ruby/server/lib/roma/storage/basic_storage.rb +342 -82
- data/ruby/server/lib/roma/storage/dummy_storage.rb +0 -2
- data/ruby/server/lib/roma/storage/rh_storage.rb +13 -12
- data/ruby/server/lib/roma/storage/sqlite3_storage.rb +4 -0
- data/ruby/server/lib/roma/storage/tc_storage.rb +6 -20
- data/ruby/server/lib/roma/tools/cpdb.rb +103 -0
- data/ruby/server/lib/roma/tools/safecopy_integration_test.rb +247 -0
- data/ruby/server/lib/roma/tools/safecopy_test.rb +184 -0
- data/ruby/server/lib/roma/tools/simple_bench.rb +16 -16
- data/ruby/server/lib/roma/version.rb +1 -1
- data/ruby/server/test/t_storage.rb +223 -41
- metadata +25 -20
@@ -8,15 +8,18 @@ module Roma
|
|
8
8
|
def get(k); self[k]; end
|
9
9
|
def out(k); delete(k); end
|
10
10
|
def rnum; length; end
|
11
|
+
def sync; true; end
|
11
12
|
end
|
12
13
|
|
13
14
|
class RubyHashStorage < BasicStorage
|
14
15
|
|
15
16
|
def opendb
|
16
17
|
create_div_hash
|
17
|
-
@divnum.times
|
18
|
+
@divnum.times do |i|
|
18
19
|
@hdb[i] = open_db(nil)
|
19
|
-
|
20
|
+
@hdbc[i] = nil
|
21
|
+
@dbs[i] = :normal
|
22
|
+
end
|
20
23
|
end
|
21
24
|
|
22
25
|
if RUBY_VERSION >= '1.9.2'
|
@@ -42,25 +45,23 @@ module Roma
|
|
42
45
|
}
|
43
46
|
end
|
44
47
|
|
45
|
-
def
|
48
|
+
def each_unpacked_db(target_vn, db)
|
46
49
|
count = 0
|
47
50
|
tn = Time.now.to_i
|
48
|
-
keys =
|
49
|
-
keys.each
|
50
|
-
v =
|
51
|
+
keys = db[@hdiv[target_vn]].keys
|
52
|
+
keys.each do |k|
|
53
|
+
v = db[@hdiv[target_vn]][k]
|
51
54
|
vn, last, clk, expt, val = unpack_data(v)
|
52
55
|
if vn != target_vn || (expt != 0 && tn > expt)
|
53
56
|
count += 1
|
54
57
|
sleep @each_vn_dump_sleep if count % @each_vn_dump_sleep_count == 0
|
55
58
|
next
|
56
59
|
end
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
yield [vn, last, clk, expt, k.length, k, 0].pack("NNNNNa#{k.length}N")
|
61
|
-
end
|
62
|
-
}
|
60
|
+
yield vn, last, clk, expt, k, val
|
61
|
+
end
|
63
62
|
end
|
63
|
+
private :each_unpacked_db
|
64
|
+
|
64
65
|
|
65
66
|
def each_hdb_dump(i,except_vnh = nil)
|
66
67
|
count = 0
|
@@ -32,7 +32,7 @@ module Roma
|
|
32
32
|
end
|
33
33
|
ret
|
34
34
|
end
|
35
|
-
end
|
35
|
+
end # class TokyoCabinet::HDB
|
36
36
|
|
37
37
|
def initialize
|
38
38
|
super
|
@@ -51,33 +51,18 @@ module Roma
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def opendb
|
54
|
-
create_div_hash
|
55
|
-
path = ''
|
56
|
-
@storage_path.split('/').each{|p|
|
57
|
-
if p.length==0
|
58
|
-
path = '/'
|
59
|
-
next
|
60
|
-
end
|
61
|
-
path << p
|
62
|
-
Dir::mkdir(path) unless File.exist?(path)
|
63
|
-
path << '/'
|
64
|
-
}
|
65
|
-
|
66
54
|
@fname_lock = "#{@storage_path}/lock"
|
67
55
|
if File.exist?(@fname_lock)
|
68
56
|
raise RuntimeError.new("Lock file already exists.")
|
69
57
|
end
|
70
|
-
open(@fname_lock,"w"){}
|
71
58
|
|
72
|
-
|
73
|
-
|
74
|
-
}
|
59
|
+
super
|
60
|
+
|
61
|
+
open(@fname_lock,"w"){}
|
75
62
|
end
|
76
63
|
|
77
64
|
def closedb
|
78
|
-
|
79
|
-
buf = @hdb; @hdb = []
|
80
|
-
buf.each{ |hdb| close_db(hdb) }
|
65
|
+
super
|
81
66
|
|
82
67
|
File.unlink(@fname_lock) if @fname_lock
|
83
68
|
@fname_lock = nil
|
@@ -202,6 +187,7 @@ module Roma
|
|
202
187
|
opts += "#bnum=#{prop['bnum']}" if prop.key?('bnum')
|
203
188
|
opts += "#capnum=#{prop['capnum']}" if prop.key?('capnum')
|
204
189
|
opts += "#capsiz=#{prop['capsiz']}" if prop.key?('capsiz')
|
190
|
+
|
205
191
|
opts = nil unless opts.length > 0
|
206
192
|
opts
|
207
193
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module Roma
|
6
|
+
class SafeCopy
|
7
|
+
|
8
|
+
attr_reader :storages
|
9
|
+
|
10
|
+
def initialize(addr, port)
|
11
|
+
@con = TCPSocket.open(addr, port)
|
12
|
+
get_storage_info
|
13
|
+
end
|
14
|
+
|
15
|
+
def backup_all
|
16
|
+
@storages.keys.each do |k|
|
17
|
+
backup(k)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def backup(hname)
|
22
|
+
stat = get_safecopy_stats(hname)
|
23
|
+
if stat.uniq != [:normal]
|
24
|
+
puts "storages[#{hname}].storage.safecopy_stats #{stat.to_s}"
|
25
|
+
puts "ERROR: Status except the :normal exists."
|
26
|
+
return
|
27
|
+
end
|
28
|
+
@storages[hname].each_with_index do |fname, num|
|
29
|
+
ret = set_storage_status(hname, num, "safecopy")
|
30
|
+
if ret != "PUSHED\r\n"
|
31
|
+
puts ret
|
32
|
+
puts "ERROR: Can't change storage status to safecopy."
|
33
|
+
return
|
34
|
+
end
|
35
|
+
wait(hname, num, :safecopy_flushed)
|
36
|
+
puts "copy file : #{fname}"
|
37
|
+
# file copy
|
38
|
+
`cp #{fname} #{fname}.#{Time.now.strftime("%Y%m%d%H%M%S")}`
|
39
|
+
ret = set_storage_status(hname, num, "normal")
|
40
|
+
if ret != "PUSHED\r\n"
|
41
|
+
puts ret
|
42
|
+
puts "ERROR: Can't change storage status to normal."
|
43
|
+
return
|
44
|
+
end
|
45
|
+
wait(hname, num, :normal)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def wait(hname, num, stat)
|
50
|
+
print "waiting for storages[#{hname}][#{num}] == #{stat} "
|
51
|
+
while get_safecopy_stats(hname)[num] != stat
|
52
|
+
print "."
|
53
|
+
sleep 5
|
54
|
+
end
|
55
|
+
puts
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_storage_info
|
59
|
+
@storages = {}
|
60
|
+
stats do |line|
|
61
|
+
if /^storages\[(.+)\]\.storage\[(\d+)\]\.path\s(.+)/ =~ line
|
62
|
+
@storages[$1] = [] unless @storages.key? $1
|
63
|
+
@storages[$1][$2.to_i] = $3.chomp
|
64
|
+
# puts "#{$1} #{$2} #{$3}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_safecopy_stats(hname)
|
70
|
+
ret = nil
|
71
|
+
stats do |line|
|
72
|
+
if /^storages\[#{hname}\]\.storage\.safecopy_stats\s(.+)/ =~ line
|
73
|
+
ret = $1.chomp
|
74
|
+
end
|
75
|
+
end
|
76
|
+
eval ret
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_storage_status(hname, num, stat)
|
80
|
+
@con.puts "set_storage_status #{num} #{stat} #{hname}\r\n"
|
81
|
+
@con.gets
|
82
|
+
end
|
83
|
+
|
84
|
+
def stats
|
85
|
+
@con.puts "stat storage\r\n"
|
86
|
+
yield $_ while @con.gets != "END\r\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
def close
|
90
|
+
@con.close if @con
|
91
|
+
end
|
92
|
+
|
93
|
+
end # SafeCopy
|
94
|
+
end # Roma
|
95
|
+
|
96
|
+
if ARGV.length < 1
|
97
|
+
puts File.basename(__FILE__) + " [port]"
|
98
|
+
exit
|
99
|
+
end
|
100
|
+
|
101
|
+
sc = Roma::SafeCopy.new("localhost", ARGV[0].to_i)
|
102
|
+
sc.backup_all
|
103
|
+
sc.close
|
@@ -0,0 +1,247 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'date'
|
4
|
+
require 'roma/client/rclient'
|
5
|
+
|
6
|
+
@cnt = 0
|
7
|
+
@tmax = 0
|
8
|
+
@tmin = 100
|
9
|
+
|
10
|
+
@m = Mutex.new
|
11
|
+
|
12
|
+
Thread.new do
|
13
|
+
sleep_time=10
|
14
|
+
while(true)
|
15
|
+
sleep sleep_time
|
16
|
+
printf("\s\sqps=%d max=%f min=%f ave=%f\n",@cnt/sleep_time,@tmax,@tmin,sleep_time/@cnt.to_f)
|
17
|
+
@cnt=0
|
18
|
+
@tmax=0
|
19
|
+
@tmin=100
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def random_rquest_sender(ini_nodes, n)
|
24
|
+
puts __method__
|
25
|
+
rc=Roma::Client::RomaClient.new(ini_nodes)
|
26
|
+
|
27
|
+
loop do
|
28
|
+
i=rand(n)
|
29
|
+
ts = DateTime.now
|
30
|
+
case rand(3)
|
31
|
+
when 0
|
32
|
+
res=rc.set(i.to_s,'hoge'+i.to_s)
|
33
|
+
puts "set k=#{i} #{res}" if res==nil || res.chomp != 'STORED'
|
34
|
+
when 1
|
35
|
+
res=rc.get(i.to_s)
|
36
|
+
puts "get k=#{i} #{res}" if res == :error
|
37
|
+
when 2
|
38
|
+
res=rc.delete(i.to_s)
|
39
|
+
puts "del k=#{i} #{res}" if res != 'DELETED' && res != 'NOT_FOUND'
|
40
|
+
end
|
41
|
+
t=(DateTime.now - ts).to_f * 86400.0
|
42
|
+
@tmax=t if t > @tmax
|
43
|
+
@tmin=t if t < @tmin
|
44
|
+
@cnt+=1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def set_counts(ini_nodes, range, key_prefix, value)
|
49
|
+
puts "\s\s#{__method__} #{range} #{value}"
|
50
|
+
rc=Roma::Client::RomaClient.new(ini_nodes)
|
51
|
+
@range_cnt = 0
|
52
|
+
|
53
|
+
range.each do |i|
|
54
|
+
ts = DateTime.now
|
55
|
+
@range_cnt = i
|
56
|
+
res=rc.set("#{key_prefix}_#{i}","#{value}")
|
57
|
+
puts "set #{key_prefix}_#{i}=#{value} #{res}" if res==nil || res.chomp != 'STORED'
|
58
|
+
t=(DateTime.now - ts).to_f * 86400.0
|
59
|
+
@tmax=t if t > @tmax
|
60
|
+
@tmin=t if t < @tmin
|
61
|
+
@cnt+=1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_count(ini_nodes, range, key_prefix, value)
|
66
|
+
puts "\s\s#{__method__} #{range} #{value}"
|
67
|
+
rc=Roma::Client::RomaClient.new(ini_nodes)
|
68
|
+
|
69
|
+
range.each do |i|
|
70
|
+
ts = DateTime.now
|
71
|
+
res = rc.get("#{key_prefix}_#{i}")
|
72
|
+
if res != value.to_s
|
73
|
+
puts "error k=#{key_prefix}_#{i} #{res}"
|
74
|
+
end
|
75
|
+
|
76
|
+
t=(DateTime.now - ts).to_f * 86400.0
|
77
|
+
@tmax=t if t > @tmax
|
78
|
+
@tmin=t if t < @tmin
|
79
|
+
@cnt+=1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def send_cmd(nid, cmd)
|
84
|
+
conn = Roma::Client::ConPool.instance.get_connection(nid)
|
85
|
+
conn.write "#{cmd}\r\n"
|
86
|
+
ret = conn.gets
|
87
|
+
Roma::Client::ConPool.instance.return_connection(nid, conn)
|
88
|
+
ret
|
89
|
+
rescue =>e
|
90
|
+
STDERR.puts "#{nid} #{cmd} #{e.inspect}"
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
|
94
|
+
def stats(nid, regexp=nil)
|
95
|
+
conn = Roma::Client::ConPool.instance.get_connection(nid)
|
96
|
+
if regexp
|
97
|
+
conn.write "stats #{regexp}\r\n"
|
98
|
+
else
|
99
|
+
conn.write "stats\r\n"
|
100
|
+
end
|
101
|
+
ret = ""
|
102
|
+
while(conn.gets != "END\r\n")
|
103
|
+
ret << $_
|
104
|
+
end
|
105
|
+
Roma::Client::ConPool.instance.return_connection(nid, conn)
|
106
|
+
ret
|
107
|
+
rescue =>e
|
108
|
+
STDERR.puts "#{nid} #{e.inspect}"
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
112
|
+
def safecopy_stats(nid)
|
113
|
+
ret = stats(nid, 'storage.safecopy_stats')
|
114
|
+
return eval $1 if ret =~ /^.+\s(\[.+\])/
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
|
118
|
+
def set_storage_status(nid, fno, stat)
|
119
|
+
send_cmd(ARGV[0], "set_storage_status #{fno} #{stat}")
|
120
|
+
end
|
121
|
+
|
122
|
+
def wait_status(nid, fno, stat)
|
123
|
+
while safecopy_stats(nid)[fno] != stat
|
124
|
+
sleep 5
|
125
|
+
end
|
126
|
+
stat
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_change_status
|
130
|
+
|
131
|
+
puts "write (0...10000) = 0"
|
132
|
+
set_counts(ARGV, 0...10000, "default_key",0)
|
133
|
+
Thread.new { random_rquest_sender(ARGV, 10000) }
|
134
|
+
|
135
|
+
set_counts(ARGV, 0...1000, "flushing_key", 0)
|
136
|
+
set_counts(ARGV, 0...1000, "caching_key", 0)
|
137
|
+
|
138
|
+
nid = ARGV[0]
|
139
|
+
|
140
|
+
sleep(5)
|
141
|
+
|
142
|
+
10.times do |n|
|
143
|
+
puts "\n#{n+1}th loop(#{n}.tc)****************************************************************** "
|
144
|
+
|
145
|
+
#========================================================================================
|
146
|
+
#flushing(normal => safecopy_flushed)
|
147
|
+
flush_loop_count = 0
|
148
|
+
@range_cnt = 0
|
149
|
+
@flag = false
|
150
|
+
|
151
|
+
t = Thread.new {
|
152
|
+
loop{
|
153
|
+
flush_loop_count += 1
|
154
|
+
set_counts(ARGV, 0...1000, "flushing_key", flush_loop_count)
|
155
|
+
@flag = true
|
156
|
+
}
|
157
|
+
}
|
158
|
+
while !@flag do
|
159
|
+
puts "\s\s[debug]sleep flushing start"
|
160
|
+
sleep(1)
|
161
|
+
puts "\s\s[debug]sleep flushing end"
|
162
|
+
end
|
163
|
+
puts "\s\s#{set_storage_status(nid, n, 'safecopy')}"
|
164
|
+
puts "#{wait_status(nid, n, :safecopy_flushed)}"
|
165
|
+
|
166
|
+
#sleep(5)
|
167
|
+
t.kill
|
168
|
+
|
169
|
+
flushing_range_cnt = @range_cnt
|
170
|
+
puts "\s\s#{safecopy_stats(nid)}\n\n"
|
171
|
+
|
172
|
+
#========================================================================================
|
173
|
+
#Caching(safecopy_flushed => normal)
|
174
|
+
#sleep(30)
|
175
|
+
cache_loop_count = 0
|
176
|
+
@range_cnt = 0
|
177
|
+
@flag = false
|
178
|
+
t = Thread.new {
|
179
|
+
loop{
|
180
|
+
cache_loop_count += 1
|
181
|
+
set_counts(ARGV, 0...1000, "caching_key", cache_loop_count)
|
182
|
+
@flag = true
|
183
|
+
}
|
184
|
+
}
|
185
|
+
while !@flag do
|
186
|
+
puts "\s\s[debug]sleep caching start"
|
187
|
+
sleep(1)
|
188
|
+
puts "\s\s[debug]sleep caching end"
|
189
|
+
end
|
190
|
+
|
191
|
+
puts "\s\s#{set_storage_status(nid, n, 'normal')}"
|
192
|
+
puts "#{wait_status(nid, n, :normal)}"
|
193
|
+
|
194
|
+
#sleep(5)
|
195
|
+
t.kill
|
196
|
+
|
197
|
+
caching_range_cnt = @range_cnt
|
198
|
+
puts "\s\s#{safecopy_stats(nid)}"
|
199
|
+
|
200
|
+
#========================================================================================
|
201
|
+
#check
|
202
|
+
puts "\n[Check]"
|
203
|
+
puts "\s\sflushing key"
|
204
|
+
check_count(ARGV, 0..flushing_range_cnt, "flushing_key", flush_loop_count)
|
205
|
+
check_count(ARGV, flushing_range_cnt+1...1000, "flushing_key", flush_loop_count-1)
|
206
|
+
|
207
|
+
puts "\n\s\scaching key"
|
208
|
+
check_count(ARGV, 0..caching_range_cnt, "caching_key", cache_loop_count)
|
209
|
+
check_count(ARGV, caching_range_cnt+1...1000, "caching_key", cache_loop_count-1) if cache_loop_count != 1
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_round
|
214
|
+
n = 0
|
215
|
+
1000.times do |i|
|
216
|
+
set_counts(ARGV, 0...10000, i)
|
217
|
+
check_count(ARGV, 0...10000, i)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
param = { :num=>10000, :th=>1 }
|
222
|
+
|
223
|
+
opts = OptionParser.new
|
224
|
+
|
225
|
+
opts.on("-r", "--round", "round request"){|v| param[:round] = v }
|
226
|
+
opts.on("-c", "--count [x]", "counts of the test times"){|v| param[:count] = v.to_i }
|
227
|
+
|
228
|
+
opts.banner = "usage:#{File.basename($0)} [options] addr:port"
|
229
|
+
opts.parse!(ARGV)
|
230
|
+
|
231
|
+
if ARGV.length == 0
|
232
|
+
STDERR.puts opts.help
|
233
|
+
exit
|
234
|
+
end
|
235
|
+
|
236
|
+
if param.key?(:round)
|
237
|
+
test_round
|
238
|
+
else
|
239
|
+
param[:count] = 1 if !param.key?(:count)
|
240
|
+
|
241
|
+
param[:count].times do |count|
|
242
|
+
puts "#{count+1}th test========================================================================================="
|
243
|
+
test_change_status
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
puts "#{File.basename($0)} has done."
|