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
@@ -90,7 +90,7 @@ module Roma
|
|
90
90
|
|
91
91
|
def get_connection(ap)
|
92
92
|
ret = @pool[ap].shift if @pool.key?(ap) && @pool[ap].length > 0
|
93
|
-
if ret && ret.last_access < Time.now - @expire_time
|
93
|
+
if ret && @expire_time != 0 && ret.last_access < Time.now - @expire_time
|
94
94
|
ret.close_connection if ret.connected
|
95
95
|
ret = nil
|
96
96
|
Logging::RLogger.instance.info("EM connection expired at #{ap},remains #{@pool[ap].length}")
|
@@ -50,7 +50,15 @@ module Roma
|
|
50
50
|
@@connection_expire_time
|
51
51
|
end
|
52
52
|
|
53
|
-
|
53
|
+
@@timeout = 10
|
54
|
+
def self.timeout=(n)
|
55
|
+
@@timeout = n
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.timeout
|
59
|
+
@@timeout
|
60
|
+
end
|
61
|
+
|
54
62
|
attr_reader :connected
|
55
63
|
attr_reader :lastcmd
|
56
64
|
attr_reader :last_access
|
@@ -71,7 +79,6 @@ module Roma
|
|
71
79
|
|
72
80
|
@storages = storages
|
73
81
|
@rttable = rttable
|
74
|
-
@timeout = 10
|
75
82
|
@log = Roma::Logging::RLogger.instance
|
76
83
|
@last_access = Time.now
|
77
84
|
end
|
@@ -96,7 +103,6 @@ module Roma
|
|
96
103
|
end
|
97
104
|
|
98
105
|
def unbind
|
99
|
-
@log.debug("Roma::Event::Handler.unbind called")
|
100
106
|
@connected=false
|
101
107
|
begin
|
102
108
|
@fiber.resume
|
@@ -144,7 +150,7 @@ module Roma
|
|
144
150
|
|
145
151
|
def dispatcher
|
146
152
|
@stats = Roma::Stats.instance
|
147
|
-
|
153
|
+
#@log.debug("Roma::Event::Handler.dipatcher called")
|
148
154
|
while(@connected) do
|
149
155
|
@enter_time = nil
|
150
156
|
next unless s=gets
|
@@ -224,7 +230,7 @@ module Roma
|
|
224
230
|
else
|
225
231
|
remain = size - @rbuf.size
|
226
232
|
Fiber.yield(remain)
|
227
|
-
if Time.now.to_i - t >
|
233
|
+
if Time.now.to_i - t > @@timeout * mult
|
228
234
|
@log.warn("#{__FILE__}:#{__LINE__}:#{@addr}:#{@port} read_bytes time out");
|
229
235
|
close_connection
|
230
236
|
return nil
|
@@ -21,7 +21,7 @@ module Roma
|
|
21
21
|
|
22
22
|
def get_connection(ap)
|
23
23
|
ret,last = @pool[ap].shift if @pool.key?(ap) && @pool[ap].length > 0
|
24
|
-
if ret && last < Time.now - @expire_time
|
24
|
+
if ret && @expire_time != 0 && last < Time.now - @expire_time
|
25
25
|
ret.close
|
26
26
|
ret = nil
|
27
27
|
Logging::RLogger.instance.info("connection expired at #{ap},remains #{@pool[ap].length}")
|
@@ -521,6 +521,8 @@ module Roma
|
|
521
521
|
@stats.run_storage_clean_up
|
522
522
|
stop_clean_up
|
523
523
|
end
|
524
|
+
rescue Exception =>e
|
525
|
+
@log.error("#{e}\n#{$@}")
|
524
526
|
end
|
525
527
|
|
526
528
|
def timer_event_10sec
|
@@ -539,7 +541,7 @@ module Roma
|
|
539
541
|
@log.warn("failover disable now!!")
|
540
542
|
else
|
541
543
|
version_check
|
542
|
-
@rttable.delete_old_trans
|
544
|
+
@rttable.delete_old_trans(@stats.routing_trans_timeout)
|
543
545
|
start_sync_routing_process
|
544
546
|
end
|
545
547
|
|
@@ -63,6 +63,14 @@ module Roma
|
|
63
63
|
attr_accessor :latency_data
|
64
64
|
#attr_accessor :latency_denominator
|
65
65
|
|
66
|
+
# for vnode copy parameter
|
67
|
+
attr_accessor :spushv_klength_warn
|
68
|
+
attr_accessor :spushv_vlength_warn
|
69
|
+
attr_accessor :spushv_read_timeout
|
70
|
+
attr_accessor :reqpushv_timeout_count
|
71
|
+
|
72
|
+
attr_accessor :routing_trans_timeout
|
73
|
+
|
66
74
|
def initialize
|
67
75
|
@config_path = nil
|
68
76
|
@run_recover = false
|
@@ -90,8 +98,13 @@ module Roma
|
|
90
98
|
@wb_command_map = {}
|
91
99
|
@latency_log = false
|
92
100
|
@latency_check_cmd =["get", "set", "delete"]
|
93
|
-
@latency_check_time_count =
|
101
|
+
@latency_check_time_count = false
|
94
102
|
@latency_data = Hash.new { |hash,key| hash[key] = {} } #double hash
|
103
|
+
@spushv_klength_warn = 1024 # 1kB
|
104
|
+
@spushv_vlength_warn = 1024 * 1024 # 1MB
|
105
|
+
@spushv_read_timeout = 100
|
106
|
+
@reqpushv_timeout_count = 300 # 0.1 * 300 sec
|
107
|
+
@routing_trans_timeout = 3600 * 3 # 3hr
|
95
108
|
end
|
96
109
|
|
97
110
|
def ap_str
|
@@ -132,6 +145,11 @@ module Roma
|
|
132
145
|
ret['stats.latency_log'] = @latency_log
|
133
146
|
ret['stats.latency_check_cmd'] = @latency_check_cmd
|
134
147
|
ret['stats.latency_check_time_count'] = @latency_check_time_count
|
148
|
+
ret['stats.spushv_klength_warn'] = @spushv_klength_warn
|
149
|
+
ret['stats.spushv_vlength_warn'] = @spushv_vlength_warn
|
150
|
+
ret['stats.spushv_read_timeout'] = @spushv_read_timeout
|
151
|
+
ret['stats.reqpushv_timeout_count'] = @reqpushv_timeout_count
|
152
|
+
ret['stats.routing_trans_timeout'] = @routing_trans_timeout
|
135
153
|
ret
|
136
154
|
end
|
137
155
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'digest/sha1'
|
2
|
+
require 'thread'
|
2
3
|
|
3
4
|
module Roma
|
4
5
|
module Storage
|
@@ -7,11 +8,11 @@ module Roma
|
|
7
8
|
|
8
9
|
class BasicStorage
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
attr_reader :hdb
|
12
|
+
attr_reader :hdiv
|
13
|
+
attr_reader :ext_name
|
14
14
|
attr_reader :error_message
|
15
|
+
attr_reader :dbs
|
15
16
|
|
16
17
|
attr_writer :vn_list
|
17
18
|
attr_writer :storage_path
|
@@ -23,8 +24,17 @@ module Roma
|
|
23
24
|
attr_accessor :each_clean_up_sleep
|
24
25
|
attr_accessor :logic_clock_expire
|
25
26
|
|
27
|
+
attr_accessor :do_each_vn_dump
|
28
|
+
|
26
29
|
def initialize
|
30
|
+
# database handler
|
27
31
|
@hdb = []
|
32
|
+
# database cache handler
|
33
|
+
@hdbc = []
|
34
|
+
# status of a database
|
35
|
+
@dbs = []
|
36
|
+
@log_fd = nil
|
37
|
+
|
28
38
|
@hdiv = Hash.new(0)
|
29
39
|
|
30
40
|
@ext_name = 'db'
|
@@ -35,6 +45,10 @@ module Roma
|
|
35
45
|
@each_vn_dump_sleep_count = 100
|
36
46
|
@each_clean_up_sleep = 0.01
|
37
47
|
@logic_clock_expire = 300
|
48
|
+
|
49
|
+
@each_cache_lock = Mutex::new
|
50
|
+
@each_clean_up_lock = Mutex::new
|
51
|
+
@stat_lock = Mutex::new
|
38
52
|
end
|
39
53
|
|
40
54
|
def get_stat
|
@@ -46,6 +60,7 @@ module Roma
|
|
46
60
|
ret['storage.each_vn_dump_sleep_count'] = @each_vn_dump_sleep_count
|
47
61
|
ret['storage.each_clean_up_sleep'] = @each_clean_up_sleep
|
48
62
|
ret['storage.logic_clock_expire'] = @logic_clock_expire
|
63
|
+
ret['storage.safecopy_stats'] = @dbs.inspect
|
49
64
|
ret
|
50
65
|
end
|
51
66
|
|
@@ -71,27 +86,45 @@ module Roma
|
|
71
86
|
end
|
72
87
|
protected :create_div_hash
|
73
88
|
|
74
|
-
def
|
75
|
-
create_div_hash
|
89
|
+
def mkdir_p(md_path)
|
76
90
|
path = ''
|
77
|
-
|
78
|
-
if p.length==0
|
91
|
+
md_path.split('/').each do |p|
|
92
|
+
if p.length == 0
|
79
93
|
path = '/'
|
80
94
|
next
|
81
95
|
end
|
82
96
|
path << p
|
83
97
|
Dir::mkdir(path) unless File.exist?(path)
|
84
98
|
path << '/'
|
85
|
-
|
86
|
-
|
99
|
+
end
|
100
|
+
end
|
101
|
+
protected :mkdir_p
|
102
|
+
|
103
|
+
def opendb
|
104
|
+
create_div_hash
|
105
|
+
mkdir_p(@storage_path)
|
106
|
+
@divnum.times do |i|
|
107
|
+
# open database file
|
87
108
|
@hdb[i] = open_db("#{@storage_path}/#{i}.#{@ext_name}")
|
88
|
-
|
109
|
+
# check cache file
|
110
|
+
if File.exist?(cache_file_name(i))
|
111
|
+
@hdbc[i] = open_db(cache_file_name(i))
|
112
|
+
stop_clean_up { @dbs[i] = :safecopy_flushed }
|
113
|
+
else
|
114
|
+
@dbs[i] = :normal
|
115
|
+
@hdbc[i] = nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
open_log
|
89
119
|
end
|
90
120
|
|
91
121
|
def closedb
|
92
122
|
stop_clean_up
|
93
123
|
buf = @hdb; @hdb = []
|
94
|
-
buf.each{ |
|
124
|
+
buf.each{ |h| close_db(h) if h }
|
125
|
+
buf = @hdbc; @hdbc = []
|
126
|
+
buf.each{ |h| close_db(h) if h }
|
127
|
+
close_log
|
95
128
|
end
|
96
129
|
|
97
130
|
|
@@ -117,15 +150,41 @@ module Roma
|
|
117
150
|
end
|
118
151
|
private :pack_header, :unpack_header, :pack_data, :unpack_data
|
119
152
|
|
153
|
+
def db_get(vn, k)
|
154
|
+
n = @hdiv[vn]
|
155
|
+
d = @hdb[n].get(k)
|
156
|
+
return d if @dbs[n] == :normal
|
157
|
+
|
158
|
+
c = @hdbc[n].get(k)
|
159
|
+
return d unless c # in case of out of :normal status
|
160
|
+
|
161
|
+
if @dbs[n] == :cachecleaning && d
|
162
|
+
# in case of existing value is both @hdb and @hdbc
|
163
|
+
vn, lat, clk, expt = unpack_header(d)
|
164
|
+
cvn, clat, cclk, cexpt = unpack_header(c)
|
165
|
+
return d if cmp_clk(clk, cclk) > 0 # if @hdb newer than @hdbc
|
166
|
+
end
|
167
|
+
c
|
168
|
+
end
|
169
|
+
|
170
|
+
def db_put(vn, k, v)
|
171
|
+
n = @hdiv[vn]
|
172
|
+
if @dbs[n] == :safecopy_flushing || @dbs[n] == :safecopy_flushed
|
173
|
+
ret = @hdbc[n].put(k, v)
|
174
|
+
else
|
175
|
+
ret = @hdb[n].put(k, v)
|
176
|
+
end
|
177
|
+
ret
|
178
|
+
end
|
120
179
|
|
121
180
|
def get_context(vn, k, d)
|
122
|
-
buf =
|
181
|
+
buf = db_get(vn, k)
|
123
182
|
return nil unless buf
|
124
183
|
unpack_header(buf)
|
125
184
|
end
|
126
185
|
|
127
186
|
def cas(vn, k, d, clk, expt, v)
|
128
|
-
buf =
|
187
|
+
buf = db_get(vn ,k)
|
129
188
|
return :not_found unless buf
|
130
189
|
t = Time.now.to_i
|
131
190
|
data = unpack_data(buf)
|
@@ -133,12 +192,12 @@ module Roma
|
|
133
192
|
return :exists if clk != data[2]
|
134
193
|
clk = (data[2] + 1) & 0xffffffff
|
135
194
|
ret = [vn, t, clk, expt, v]
|
136
|
-
return ret if
|
195
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
137
196
|
nil
|
138
197
|
end
|
139
198
|
|
140
199
|
def rset(vn, k, d, clk, expt, v)
|
141
|
-
buf =
|
200
|
+
buf = db_get(vn, k)
|
142
201
|
t = Time.now.to_i
|
143
202
|
if buf
|
144
203
|
data = unpack_data(buf)
|
@@ -149,13 +208,13 @@ module Roma
|
|
149
208
|
end
|
150
209
|
|
151
210
|
ret = [vn, t, clk, expt, v]
|
152
|
-
return ret if
|
211
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
153
212
|
@error_message = "error:put"
|
154
213
|
nil
|
155
214
|
end
|
156
215
|
|
157
216
|
def set(vn, k, d, expt, v)
|
158
|
-
buf =
|
217
|
+
buf = db_get(vn, k)
|
159
218
|
clk = 0
|
160
219
|
if buf
|
161
220
|
data = unpack_data(buf)
|
@@ -163,12 +222,12 @@ module Roma
|
|
163
222
|
end
|
164
223
|
|
165
224
|
ret = [vn, Time.now.to_i, clk, expt, v]
|
166
|
-
return ret if
|
225
|
+
return ret if db_put(vn , k, pack_data(*ret))
|
167
226
|
nil
|
168
227
|
end
|
169
228
|
|
170
229
|
def add(vn, k, d, expt, v)
|
171
|
-
buf =
|
230
|
+
buf = db_get(vn, k)
|
172
231
|
clk = 0
|
173
232
|
if buf
|
174
233
|
vn, t, clk, expt2, v2 = unpack_data(buf)
|
@@ -178,12 +237,12 @@ module Roma
|
|
178
237
|
|
179
238
|
# not exist
|
180
239
|
ret = [vn, Time.now.to_i, clk, expt, v]
|
181
|
-
return ret if
|
240
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
182
241
|
nil
|
183
242
|
end
|
184
243
|
|
185
244
|
def replace(vn, k, d, expt, v)
|
186
|
-
buf =
|
245
|
+
buf = db_get(vn, k)
|
187
246
|
return nil unless buf
|
188
247
|
|
189
248
|
# buf != nil
|
@@ -192,12 +251,12 @@ module Roma
|
|
192
251
|
clk = (clk + 1) & 0xffffffff
|
193
252
|
|
194
253
|
ret = [vn, Time.now.to_i, clk, expt, v]
|
195
|
-
return ret if
|
254
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
196
255
|
nil
|
197
256
|
end
|
198
257
|
|
199
258
|
def append(vn, k, d, expt, v)
|
200
|
-
buf =
|
259
|
+
buf = db_get(vn, k)
|
201
260
|
return nil unless buf
|
202
261
|
|
203
262
|
# buf != nil
|
@@ -206,12 +265,12 @@ module Roma
|
|
206
265
|
clk = (clk + 1) & 0xffffffff
|
207
266
|
|
208
267
|
ret = [vn, Time.now.to_i, clk, expt, v2 + v]
|
209
|
-
return ret if
|
268
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
210
269
|
nil
|
211
270
|
end
|
212
271
|
|
213
272
|
def prepend(vn, k, d, expt, v)
|
214
|
-
buf =
|
273
|
+
buf = db_get(vn, k)
|
215
274
|
return nil unless buf
|
216
275
|
|
217
276
|
# buf != nil
|
@@ -220,12 +279,12 @@ module Roma
|
|
220
279
|
clk = (clk + 1) & 0xffffffff
|
221
280
|
|
222
281
|
ret = [vn, Time.now.to_i, clk, expt, v + v2]
|
223
|
-
return ret if
|
282
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
224
283
|
nil
|
225
284
|
end
|
226
285
|
|
227
286
|
def get(vn, k, d)
|
228
|
-
buf =
|
287
|
+
buf = db_get(vn, k)
|
229
288
|
return nil unless buf
|
230
289
|
vn, t, clk, expt, v = unpack_data(buf)
|
231
290
|
|
@@ -234,7 +293,7 @@ module Roma
|
|
234
293
|
end
|
235
294
|
|
236
295
|
def get_raw(vn, k, d)
|
237
|
-
buf =
|
296
|
+
buf = db_get(vn, k)
|
238
297
|
return nil unless buf
|
239
298
|
|
240
299
|
unpack_data(buf)
|
@@ -249,7 +308,7 @@ module Roma
|
|
249
308
|
end
|
250
309
|
|
251
310
|
def rdelete(vn, k, d, clk)
|
252
|
-
buf =
|
311
|
+
buf = db_get(vn, k)
|
253
312
|
t = Time.now.to_i
|
254
313
|
if buf
|
255
314
|
data = unpack_header(buf)
|
@@ -264,7 +323,7 @@ module Roma
|
|
264
323
|
# [ 8..11] logical clock
|
265
324
|
# [12..15] exptime(unix time) => 0
|
266
325
|
ret = [vn, t, clk, 0]
|
267
|
-
if
|
326
|
+
if db_put(vn, k, pack_header(*ret))
|
268
327
|
return ret
|
269
328
|
else
|
270
329
|
return nil
|
@@ -272,7 +331,7 @@ module Roma
|
|
272
331
|
end
|
273
332
|
|
274
333
|
def delete(vn, k, d)
|
275
|
-
buf =
|
334
|
+
buf = db_get(vn, k)
|
276
335
|
v = ret = nil
|
277
336
|
clk = 0
|
278
337
|
if buf
|
@@ -287,7 +346,7 @@ module Roma
|
|
287
346
|
# [ 8..11] logical clock
|
288
347
|
# [12..15] exptime(unix time) => 0
|
289
348
|
ret = [vn, Time.now.to_i, clk, 0, v]
|
290
|
-
if
|
349
|
+
if db_put(vn, k, pack_header(*ret[0..-2]))
|
291
350
|
return ret
|
292
351
|
else
|
293
352
|
return nil
|
@@ -299,7 +358,7 @@ module Roma
|
|
299
358
|
end
|
300
359
|
|
301
360
|
def incr(vn, k, d, v)
|
302
|
-
buf =
|
361
|
+
buf = db_get(vn, k)
|
303
362
|
return nil unless buf
|
304
363
|
|
305
364
|
# buf != nil
|
@@ -312,12 +371,12 @@ module Roma
|
|
312
371
|
v = v & 0xffffffffffffffff
|
313
372
|
|
314
373
|
ret = [vn, Time.now.to_i, clk, expt2, v.to_s]
|
315
|
-
return ret if
|
374
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
316
375
|
nil
|
317
376
|
end
|
318
377
|
|
319
378
|
def decr(vn, k, d, v)
|
320
|
-
buf =
|
379
|
+
buf = db_get(vn, k)
|
321
380
|
return nil unless buf
|
322
381
|
|
323
382
|
# buf != nil
|
@@ -330,19 +389,19 @@ module Roma
|
|
330
389
|
v = v & 0xffffffffffffffff
|
331
390
|
|
332
391
|
ret = [vn, Time.now.to_i, clk, expt2, v.to_s]
|
333
|
-
return ret if
|
392
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
334
393
|
nil
|
335
394
|
end
|
336
395
|
|
337
396
|
# set expire time
|
338
397
|
def set_expt(vn, k, d, expt)
|
339
|
-
buf =
|
398
|
+
buf = db_get(vn, k)
|
340
399
|
if buf
|
341
400
|
vn, t, clk, expt2, v = unpack_data(buf)
|
342
401
|
return nil if Time.now.to_i > expt2
|
343
402
|
clk = (clk + 1) & 0xffffffff
|
344
403
|
ret = [vn, Time.now.to_i, clk, expt, v]
|
345
|
-
return ret if
|
404
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
346
405
|
end
|
347
406
|
nil
|
348
407
|
end
|
@@ -353,19 +412,14 @@ module Roma
|
|
353
412
|
res
|
354
413
|
end
|
355
414
|
|
356
|
-
def add_vnode(vn)
|
357
|
-
end
|
358
|
-
|
359
|
-
def del_vnode(vn)
|
360
|
-
buf = get_vnode_hash(vn)
|
361
|
-
buf.each_key{ |k| @hdb[@hdiv[vn]].out(k) }
|
362
|
-
end
|
363
|
-
|
364
415
|
def each_clean_up(t, vnhash)
|
365
416
|
@do_clean_up = true
|
417
|
+
return unless @each_clean_up_lock.try_lock
|
366
418
|
nt = Time.now.to_i
|
367
|
-
@
|
368
|
-
|
419
|
+
@divnum.times do |i|
|
420
|
+
next if @dbs[i] != :normal
|
421
|
+
hdb = @hdb[i]
|
422
|
+
hdb.each do |k, v|
|
369
423
|
return unless @do_clean_up # 1st check
|
370
424
|
vn, last, clk, expt = unpack_header(v)
|
371
425
|
vn_stat = vnhash[vn]
|
@@ -380,12 +434,22 @@ module Roma
|
|
380
434
|
end
|
381
435
|
return unless @do_clean_up # 2nd ckeck
|
382
436
|
sleep @each_clean_up_sleep
|
383
|
-
|
384
|
-
|
437
|
+
end
|
438
|
+
end
|
439
|
+
ensure
|
440
|
+
@each_clean_up_lock.unlock if @each_clean_up_lock.locked?
|
385
441
|
end
|
386
442
|
|
387
|
-
def stop_clean_up
|
388
|
-
|
443
|
+
def stop_clean_up(&block)
|
444
|
+
@do_clean_up = false
|
445
|
+
if block
|
446
|
+
@each_clean_up_lock.lock
|
447
|
+
begin
|
448
|
+
block.call
|
449
|
+
ensure
|
450
|
+
@each_clean_up_lock.unlock
|
451
|
+
end
|
452
|
+
end
|
389
453
|
end
|
390
454
|
|
391
455
|
def load(dmp)
|
@@ -414,19 +478,40 @@ module Roma
|
|
414
478
|
end
|
415
479
|
|
416
480
|
def load_stream_dump(vn, last, clk, expt, k, v)
|
417
|
-
buf =
|
481
|
+
buf = db_get(vn, k)
|
418
482
|
if buf
|
419
483
|
data = unpack_header(buf)
|
420
484
|
if last - data[1] < @logic_clock_expire && cmp_clk(clk,data[2]) <= 0
|
421
485
|
return nil
|
422
486
|
end
|
423
487
|
end
|
424
|
-
|
488
|
+
|
489
|
+
ret = [vn, last, clk, expt, v]
|
490
|
+
if expt == 0
|
491
|
+
# for the deleted mark
|
492
|
+
return ret if db_put(vn, k, pack_header(*ret[0..3]))
|
493
|
+
else
|
494
|
+
return ret if db_put(vn, k, pack_data(*ret))
|
495
|
+
end
|
496
|
+
nil
|
497
|
+
end
|
498
|
+
|
499
|
+
def load_stream_dump_for_cachecleaning(vn, last, clk, expt, k, v)
|
500
|
+
n = @hdiv[vn]
|
501
|
+
buf = @hdb[n].get(k)
|
502
|
+
if buf
|
503
|
+
data = unpack_header(buf)
|
504
|
+
if last - data[1] < @logic_clock_expire && cmp_clk(clk,data[2]) <= 0
|
505
|
+
return nil
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
425
509
|
ret = [vn, last, clk, expt, v]
|
426
510
|
if expt == 0
|
427
|
-
|
511
|
+
# for the deleted mark
|
512
|
+
return ret if @hdb[n].put(k, pack_header(*ret[0..3]))
|
428
513
|
else
|
429
|
-
return ret if @hdb[
|
514
|
+
return ret if @hdb[n].put(k, pack_data(*ret))
|
430
515
|
end
|
431
516
|
nil
|
432
517
|
end
|
@@ -438,43 +523,68 @@ module Roma
|
|
438
523
|
Marshal.dump(buf)
|
439
524
|
end
|
440
525
|
|
441
|
-
def
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
526
|
+
def each_vn_dump(target_vn)
|
527
|
+
@do_each_vn_dump = true
|
528
|
+
n = @hdiv[target_vn]
|
529
|
+
if @dbs[n] == :normal
|
530
|
+
# in case of :normal status
|
531
|
+
each_unpacked_db(target_vn, @hdb) do |vn, last, clk, expt, k, val|
|
532
|
+
return unless @do_each_vn_dump
|
533
|
+
yield vn_dump_pack(vn, last, clk, expt, k, val)
|
448
534
|
end
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
535
|
+
else
|
536
|
+
# in case of out of :normal status
|
537
|
+
@each_cache_lock.synchronize do
|
538
|
+
each_unpacked_db(target_vn, @hdbc) do |cvn, clast, cclk, cexpt, k, cval|
|
539
|
+
return unless @do_each_vn_dump
|
540
|
+
data = @hdb[n].get(k)
|
541
|
+
if data
|
542
|
+
vn, last, clk, expt, val = unpack_data(data)
|
543
|
+
#puts "#{k} #{clk} #{cclk} #{cmp_clk(clk, cclk)} #{val}"
|
544
|
+
if cmp_clk(clk, cclk) > 0
|
545
|
+
yield vn_dump_pack(vn, last, clk, expt, k, val)
|
546
|
+
else
|
547
|
+
yield vn_dump_pack(cvn, clast, cclk, cexpt, k, cval)
|
548
|
+
end
|
549
|
+
else
|
550
|
+
yield vn_dump_pack(cvn, clast, cclk, cexpt, k, cval)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
end
|
554
|
+
each_unpacked_db(target_vn, @hdb) do |vn, last, clk, expt, k, val|
|
555
|
+
return unless @do_each_vn_dump
|
556
|
+
unless @hdbc[n].get(k)
|
557
|
+
yield vn_dump_pack(vn, last, clk, expt, k, val)
|
558
|
+
end
|
559
|
+
end
|
560
|
+
end
|
561
|
+
ensure
|
562
|
+
@do_each_vn_dump = false
|
459
563
|
end
|
460
564
|
|
461
|
-
def
|
565
|
+
def vn_dump_pack(vn, last, clk, expt, k, val)
|
566
|
+
if val
|
567
|
+
return [vn, last, clk, expt, k.length, k, val.length, val].pack("NNNNNa#{k.length}Na#{val.length}")
|
568
|
+
else
|
569
|
+
return [vn, last, clk, expt, k.length, k, 0].pack("NNNNNa#{k.length}N")
|
570
|
+
end
|
571
|
+
end
|
572
|
+
private :vn_dump_pack
|
573
|
+
|
574
|
+
def each_unpacked_db(target_vn, db)
|
462
575
|
count = 0
|
463
576
|
tn = Time.now.to_i
|
464
|
-
|
577
|
+
db[@hdiv[target_vn]].each do |k,v|
|
465
578
|
vn, last, clk, expt, val = unpack_data(v)
|
466
579
|
if vn != target_vn || (expt != 0 && tn > expt)
|
467
580
|
count += 1
|
468
581
|
sleep @each_vn_dump_sleep if count % @each_vn_dump_sleep_count == 0
|
469
582
|
next
|
470
583
|
end
|
471
|
-
|
472
|
-
|
473
|
-
else
|
474
|
-
yield [vn, last, clk, expt, k.length, k, 0].pack("NNNNNa#{k.length}N")
|
475
|
-
end
|
476
|
-
}
|
584
|
+
yield vn, last, clk, expt, k, val
|
585
|
+
end
|
477
586
|
end
|
587
|
+
private :each_unpacked_db
|
478
588
|
|
479
589
|
def each_hdb_dump(i,except_vnh = nil)
|
480
590
|
count = 0
|
@@ -490,6 +600,54 @@ module Roma
|
|
490
600
|
}
|
491
601
|
end
|
492
602
|
|
603
|
+
# Remove a key for the cache(@hdbc).
|
604
|
+
# +dn+:: number of database
|
605
|
+
# +key+:: key
|
606
|
+
def out_cache(dn, key)
|
607
|
+
@hdbc[dn].out(key)
|
608
|
+
end
|
609
|
+
|
610
|
+
# Calls the geven block,
|
611
|
+
# passes the cache(@hdbc) element.
|
612
|
+
# +dn+:: number of database
|
613
|
+
# +keys+:: key list
|
614
|
+
def each_cache_by_keys(dn, keys)
|
615
|
+
keys.each do |k|
|
616
|
+
v = @hdbc[dn].get(k)
|
617
|
+
vn, last, clk, expt, val = unpack_data(v)
|
618
|
+
yield [vn, last, clk, expt, k, val]
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
622
|
+
# Calls the geven block,
|
623
|
+
# passes the cache(@hdbc) element as the spushv command data format.
|
624
|
+
# +dn+:: number of database
|
625
|
+
# +keys+:: key list
|
626
|
+
def each_cache_dump_pack(dn, keys)
|
627
|
+
keys.each do |k|
|
628
|
+
v = @hdbc[dn].get(k)
|
629
|
+
vn, last, clk, expt, val = unpack_data(v)
|
630
|
+
yield vn_dump_pack(vn, last, clk, expt, k, val)
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
# Returns a key array in a cache(@hdbc).
|
635
|
+
# +dn+:: number of database
|
636
|
+
# +kn+:: number of keys which is return value
|
637
|
+
def get_keys_in_cache(dn, kn=100)
|
638
|
+
return nil if @do_each_vn_dump
|
639
|
+
ret = []
|
640
|
+
return ret unless @hdbc[dn]
|
641
|
+
count = 0
|
642
|
+
@each_cache_lock.synchronize do
|
643
|
+
@hdbc[dn].each do |k, v|
|
644
|
+
ret << k
|
645
|
+
break if (count+=1) >= kn
|
646
|
+
end
|
647
|
+
end
|
648
|
+
ret
|
649
|
+
end
|
650
|
+
|
493
651
|
# Create vnode dump.
|
494
652
|
def get_vnode_hash(vn)
|
495
653
|
buf = {}
|
@@ -504,6 +662,108 @@ module Roma
|
|
504
662
|
end
|
505
663
|
private :get_vnode_hash
|
506
664
|
|
665
|
+
def flush_db(dn)
|
666
|
+
@hdb[dn].sync
|
667
|
+
end
|
668
|
+
|
669
|
+
def cache_file_name(dn)
|
670
|
+
"#{@storage_path}/#{dn}.cache.#{@ext_name}"
|
671
|
+
end
|
672
|
+
|
673
|
+
def set_db_stat(dn, stat)
|
674
|
+
@stat_lock.synchronize do
|
675
|
+
case @dbs[dn]
|
676
|
+
when :normal
|
677
|
+
if stat == :safecopy_flushing
|
678
|
+
# open cache
|
679
|
+
@hdbc[dn] = open_db(cache_file_name(dn))
|
680
|
+
stop_clean_up { @dbs[dn] = stat }
|
681
|
+
write_log("#{dn} #{stat.to_s}")
|
682
|
+
stat
|
683
|
+
else
|
684
|
+
false
|
685
|
+
end
|
686
|
+
when :safecopy_flushing
|
687
|
+
if stat == :safecopy_flushed
|
688
|
+
write_log("#{dn} #{stat.to_s}")
|
689
|
+
@dbs[dn] = stat
|
690
|
+
else
|
691
|
+
false
|
692
|
+
end
|
693
|
+
when :safecopy_flushed
|
694
|
+
if stat == :cachecleaning
|
695
|
+
write_log("#{dn} #{stat.to_s}")
|
696
|
+
@dbs[dn] = stat
|
697
|
+
else
|
698
|
+
false
|
699
|
+
end
|
700
|
+
when :cachecleaning
|
701
|
+
if stat == :normal
|
702
|
+
write_log("#{dn} #{stat.to_s}")
|
703
|
+
@dbs[dn] = stat
|
704
|
+
# remove cache
|
705
|
+
close_db(@hdbc[dn])
|
706
|
+
@hdbc[dn] = nil
|
707
|
+
if File.exist?("#{@storage_path}/#{dn}.cache.#{@ext_name}")
|
708
|
+
File.unlink("#{@storage_path}/#{dn}.cache.#{@ext_name}")
|
709
|
+
end
|
710
|
+
stat
|
711
|
+
elsif stat == :safecopy_flushing
|
712
|
+
write_log("#{dn} #{stat.to_s}")
|
713
|
+
@dbs[dn] = stat
|
714
|
+
else
|
715
|
+
false
|
716
|
+
end
|
717
|
+
else
|
718
|
+
false
|
719
|
+
end
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
723
|
+
def get_logfile_list
|
724
|
+
l={}
|
725
|
+
files=Dir.glob("#{@storage_path}/status.log.*")
|
726
|
+
files.each{ |file|
|
727
|
+
if /$.+status\.log\.(\d+)$/=~file
|
728
|
+
l[$1.to_i]=$&
|
729
|
+
end
|
730
|
+
}
|
731
|
+
# sorted by old order
|
732
|
+
l.to_a.sort{|a,b| a[0]<=>b[0]}
|
733
|
+
end
|
734
|
+
|
735
|
+
def open_log
|
736
|
+
logs = get_logfile_list
|
737
|
+
if logs.length == 0
|
738
|
+
@log_name="#{@storage_path}/status.log.1"
|
739
|
+
else
|
740
|
+
if File::stat("#{@fname}.#{logs.last[0]}").size == 0
|
741
|
+
@log_name="#{@fname}.#{logs.last[0]}"
|
742
|
+
else
|
743
|
+
@log_name="#{@fname}.#{logs.last[0]+1}"
|
744
|
+
end
|
745
|
+
end
|
746
|
+
@log_fd=File.open(@log_name,"a")
|
747
|
+
end
|
748
|
+
|
749
|
+
def write_log(line)
|
750
|
+
return unless @log_name
|
751
|
+
# log rotation
|
752
|
+
if File::stat(@log_name).size > 1000 * 1024
|
753
|
+
close_log
|
754
|
+
open_log
|
755
|
+
end
|
756
|
+
t = Time.now
|
757
|
+
tstr = "#{t.strftime('%Y-%m-%dT%H:%M:%S')}.#{t.usec}"
|
758
|
+
@log_fd.write("#{tstr} #{line}\n")
|
759
|
+
@log_fd.flush
|
760
|
+
end
|
761
|
+
|
762
|
+
def close_log
|
763
|
+
@log_fd.close if @log_fd
|
764
|
+
@log_fd = nil
|
765
|
+
end
|
766
|
+
|
507
767
|
end # class BasicStorage
|
508
768
|
|
509
769
|
end # module Storage
|