roma 0.8.11 → 0.8.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,52 +11,53 @@ module Roma
11
11
 
12
12
  def ev_balance(s)
13
13
  res = broadcast_cmd("rbalance\r\n")
14
- if @stats.run_recover==false &&
15
- @stats.run_acquire_vnodes == false &&
14
+ if @stats.run_join == false &&
15
+ @stats.run_recover == false &&
16
+ @stats.run_balance == false &&
16
17
  @rttable.vnode_balance(@stats.ap_str)==:less
17
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_acquire_vnodes_process'))
18
+ Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_balance_process'))
18
19
  res[@stats.ap_str] = 'STARTED'
19
20
  else
20
- res[@stats.ap_str] = 'SERVER_ERROR Not unbalance or Balance/Recover/Sync process is already running.'
21
+ res[@stats.ap_str] = 'SERVER_ERROR Not unbalance or othre process is already running.'
21
22
  end
22
23
  send_data("#{res}\r\n")
23
24
  end
24
25
 
25
26
  def ev_rbalance(s)
26
- if @stats.run_recover==false &&
27
- @stats.run_acquire_vnodes == false &&
27
+ if @stats.run_join == false &&
28
+ @stats.run_recover == false &&
29
+ @stats.run_balance == false &&
28
30
  @rttable.vnode_balance(@stats.ap_str)==:less
29
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_acquire_vnodes_process'))
31
+ Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_balance_process'))
30
32
  send_data("STARTED\r\n")
31
33
  else
32
- send_data("SERVER_ERROR Not unbalance or Balance/Recover/Sync process is already running.\r\n")
34
+ send_data("SERVER_ERROR Not unbalance or other process is already running.\r\n")
33
35
  end
34
36
  end
35
37
 
36
38
  def ev_release(s)
37
- if @stats.run_recover==false &&
38
- @stats.run_acquire_vnodes == false &&
39
+ if @stats.run_join == false &&
40
+ @stats.run_recover == false &&
41
+ @stats.run_balance == false &&
39
42
  @stats.run_release == false &&
40
43
  @stats.run_iterate_storage == false
41
44
  Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_release_process'))
42
45
  send_data("STARTED\r\n")
43
46
  else
44
- send_data("SERVER_ERROR Release/Balance/Recover/Sync process is already running.\r\n")
47
+ send_data("SERVER_ERROR Other process is already running.\r\n")
45
48
  end
46
49
  end
47
50
 
48
- # recover [-r|-s]
51
+ # recover
49
52
  def ev_recover(s)
50
- option = s[1] if s.length == 2
51
53
  if @rttable.can_i_recover?
52
54
  cmd = "rrecover"
53
- cmd << " #{option}" if option
54
55
  res = broadcast_cmd("#{cmd}\r\n")
55
56
  unless @stats.run_recover
56
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_recover_process',[option]))
57
+ Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_recover_process'))
57
58
  res[@nid] = "STARTED"
58
59
  else
59
- res[@nid] = "SERVER_ERROR Recover/Sync process is already running."
60
+ res[@nid] = "SERVER_ERROR Recover process is already running."
60
61
  end
61
62
  send_data("#{res}\r\n")
62
63
  else
@@ -64,12 +65,11 @@ module Roma
64
65
  end
65
66
  end
66
67
 
67
- # rrecover [-r|-s]
68
+ # rrecover
68
69
  def ev_rrecover(s)
69
- option = s[1] if s.length == 2
70
70
  if @rttable.can_i_recover?
71
71
  unless @stats.run_recover
72
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_recover_process',[option]))
72
+ Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_recover_process'))
73
73
  send_data("STARTED\r\n")
74
74
  else
75
75
  send_data("SERVER_ERROR Recover process is already running.\r\n")
@@ -79,109 +79,6 @@ module Roma
79
79
  end
80
80
  end
81
81
 
82
- # sync <hname>
83
- def ev_sync(s)
84
- res = nil
85
- if s.length==1
86
- res = broadcast_cmd("rsync\r\n")
87
- else
88
- res = broadcast_cmd("rsync #{s[1]}\r\n")
89
- end
90
- unless @stats.run_recover
91
- if s.length==1
92
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_sync_process',@storages.keys))
93
- else
94
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_sync_process',[s[1]]))
95
- end
96
- res[@nid] = "STARTED"
97
- else
98
- res[@nid] = "SERVER_ERROR Recover/Sync process is already running."
99
- end
100
- send_data("#{res}\r\n")
101
- rescue => e
102
- @log.error("#{e}\n#{$@}")
103
- end
104
-
105
- # rsync <hname>
106
- def ev_rsync(s)
107
- unless @stats.run_recover
108
- if s.length==1
109
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_sync_process',@storages.keys))
110
- else
111
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_sync_process',[s[1]]))
112
- end
113
- send_data("STARTED\r\n")
114
- else
115
- send_data("SERVER_ERROR Recover/Sync process is already running.\r\n")
116
- end
117
- rescue => e
118
- @log.error("#{e}\n#{$@}")
119
- end
120
-
121
- # dumpfile <key> <path>
122
- def ev_dumpfile(s)
123
- if s.length != 3
124
- send_data("CLIENT_ERROR usage:dumpfile <key> <path>\r\n")
125
- return
126
- end
127
-
128
- res = broadcast_cmd("rdumpfile #{s[1]} #{s[2]}\r\n")
129
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_dumpfile_process',[s[1],s[2],:dumpfile]))
130
- path = Roma::Config::STORAGE_DUMP_PATH + '/' + s[2]
131
- res[@nid] = "STARTED #{path}/#{@nid}"
132
- send_data("#{res}\r\n")
133
- rescue => e
134
- @log.error("#{e}\n#{$@}")
135
- end
136
-
137
- # rdumpfile <key> <path>
138
- def ev_rdumpfile(s)
139
- if s.length != 3
140
- send_data("CLIENT_ERROR usage:rdumpfile <key> <path>\r\n")
141
- return
142
- end
143
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_dumpfile_process',[s[1],s[2],:rdumpfile]))
144
- path = Roma::Config::STORAGE_DUMP_PATH + '/' + s[2]
145
- send_data("STARTED #{path}/#{@nid}\r\n")
146
- rescue => e
147
- @log.error("#{e}\n#{$@}")
148
- end
149
-
150
- def acquire_vnodes
151
- count = 0
152
- nv = @rttable.v_idx.length
153
- while (@rttable.vnode_balance(@nid) == :less && count < nv) do
154
- count += 1
155
- break unless acquire_vnode
156
- end
157
- @log.info("acquire_vnodes has done.")
158
- rescue => e
159
- @log.error("#{e}\n#{$@}")
160
- end
161
-
162
- def acquire_vnode
163
- widthout_nodes = @rttable.nodes
164
-
165
- unless @stats.enabled_repetition_host_in_routing
166
- myhost = @stats.ap_str.split(/[:_]/)[0]
167
- widthout_nodes.delete_if{|nid| nid.split(/[:_]/)[0] != myhost }
168
- else
169
- widthout_nodes = [@stats.ap_str]
170
- end
171
-
172
- vn, nodes = @rttable.sample_vnode(widthout_nodes)
173
- unless vn
174
- @log.warn("acquire_vnode:sample_vnode dose not found")
175
- return false
176
- end
177
- #
178
- # tunning point
179
- # sleep 0.1
180
- #
181
- req_push_a_vnode(vn, nodes[0], rand(@rttable.rn) == 0)
182
- true
183
- end
184
-
185
82
  end # module BackgroundCommandReceiver
186
83
 
187
84
  end # module Command
@@ -6,25 +6,16 @@ module Roma
6
6
 
7
7
  module VnodeCommandReceiver
8
8
 
9
- # pushv <hash-name> <vnode-id>
10
- # src dst
11
- # | ['pushv' <hname> <vn>\r\n]->|
12
- # |<-['READY'\r\n] |
13
- # | [<length>\r\n]->|
14
- # | [<dump>\r\n]->|
15
- # | ['END'\r\n]->|
16
- # |<-['STORED'\r\n] |
17
- def ev_pushv(s)
18
- send_data("READY\r\n")
19
- len = gets
20
- res = em_receive_dump(s[1], len.to_i)
21
- if res == true
22
- send_data("STORED\r\n")
9
+ # spushv <true/false>
10
+ def ev_spushv_protection(s)
11
+ if s.length == 1
12
+ send_data("#{@stats.spushv_protection}\r\n")
13
+ elsif s.length == 2
14
+ @stats.spushv_protection = (s[1] == 'true')
15
+ send_data("#{@stats.spushv_protection}\r\n")
23
16
  else
24
- send_data("SERVER_ERROR #{res}\r\n")
17
+ send_data("COMMAND ERROR\r\n")
25
18
  end
26
- rescue => e
27
- @log.error("#{e}\n#{$@}")
28
19
  end
29
20
 
30
21
  # spushv <hash-name> <vnode-id>
@@ -37,8 +28,20 @@ module Roma
37
28
  # | [<end of dump>]->|
38
29
  # |<-['STORED'\r\n] |
39
30
  def ev_spushv(s)
31
+ if s.length != 3
32
+ @log.error("#{__method__}:wrong number of arguments(#{s})")
33
+ return send_data("CLIENT_ERROR Wrong number of arguments.\r\n")
34
+ end
35
+ if @stats.spushv_protection
36
+ @log.info("#{__method__}:In spushv_protection")
37
+ return send_data("SERVER_ERROR In spushv_protection.\r\n")
38
+ end
39
+ @stats.run_receive_a_vnode["#{s[1]}_#{s[2]}"] = true
40
+
41
+ $roma.stop_clean_up
42
+
40
43
  send_data("READY\r\n")
41
- @stats.run_receive_a_vnode = true
44
+
42
45
  count = rcount = 0
43
46
  @log.debug("#{__method__}:#{s.inspect} received.")
44
47
  loop {
@@ -70,20 +73,27 @@ module Roma
70
73
  end
71
74
  end
72
75
  }
73
- send_data("STORED\r\n")
74
- @log.debug("#{__method__}:#{s[2]} #{count} keys loaded. #{rcount} keys rejected.")
76
+ if @stats.spushv_protection
77
+ @log.info("#{__method__}:Canceled because of spushv_protection")
78
+ send_data("CANCELED\r\n")
79
+ else
80
+ send_data("STORED\r\n")
81
+ end
82
+ @log.debug("#{__method__}:#{s[1]}_#{s[2]} #{count} keys loaded.")
83
+ @log.debug("#{__method__}:#{s[1]}_#{s[2]} #{rcount} keys rejected.") if rcount > 0
75
84
  rescue Storage::StorageException => e
76
85
  @log.error("#{e.inspect} #{$@}")
77
86
  close_connection
78
87
  if Config.const_defined?(:STORAGE_EXCEPTION_ACTION) &&
79
88
  Config::STORAGE_EXCEPTION_ACTION == :shutdown
80
- @log.error("Romad will stop")
89
+ @log.error("#{__method__}:Romad will be stop.")
81
90
  @stop_event_loop = true
82
91
  end
83
92
  rescue => e
84
93
  @log.error("#{e} #{$@}")
85
94
  ensure
86
- @stats.run_receive_a_vnode = false
95
+ @stats.run_receive_a_vnode.delete("#{s[1]}_#{s[2]}") if s.length == 3
96
+ @stats.last_clean_up = Time.now
87
97
  end
88
98
 
89
99
  # reqpushv <vnode-id> <node-id> <is primary?>
@@ -95,7 +105,7 @@ module Roma
95
105
  send_data("CLIENT_ERROR usage:reqpushv vnode-id node-id primary-flag(true/false)\r\n")
96
106
  return
97
107
  end
98
- if @stats.run_iterate_storage == true
108
+ if(@stats.run_iterate_storage || @stats.run_join || @stats.run_balance)
99
109
  @log.warn("reqpushv rejected:#{s}")
100
110
  send_data("REJECTED\r\n")
101
111
  return
@@ -123,28 +133,6 @@ module Roma
123
133
  false
124
134
  end
125
135
 
126
- def em_receive_dump(hname, len)
127
- dmp = read_bytes(len)
128
- read_bytes(2)
129
- if gets == "END\r\n"
130
- if @storages.key?(hname)
131
- n = @storages[hname].load(dmp)
132
- @log.debug("#{dmp.length} bytes received.(#{n} keys loaded.)")
133
- return true
134
- else
135
- @log.error("receive_dump:@storages[#{hname}] dose not found.")
136
- return "@storages[#{hname}] dose not found."
137
- end
138
- else
139
- @log.error("receive_dump:END was not able to be received.")
140
- return "END was not able to be received."
141
- end
142
- rescue =>e
143
- @log.error("#{e}\n#{$@}")
144
- "#{e}"
145
- end
146
- private :em_receive_dump
147
-
148
136
  end # module VnodeCommandReceiver
149
137
 
150
138
  end # module Command
@@ -63,6 +63,8 @@ module Roma
63
63
  # typical value is 5 days
64
64
  STORAGE_DELMARK_EXPTIME = 60 * 60 * 24 * 5
65
65
 
66
+ STORAGE_CLEAN_UP_INTERVAL = 60 * 5
67
+
66
68
  # data copy setting
67
69
  DATACOPY_STREAM_COPY_WAIT_PARAM = 0.001
68
70
 
@@ -192,7 +192,12 @@ module Roma
192
192
  end
193
193
 
194
194
  def pop(size)
195
- return '' if size == 0
195
+ if size == 0
196
+ return ''
197
+ elsif size < 0
198
+ return nil
199
+ end
200
+
196
201
  if @rbuf.size >= size
197
202
  r = @rbuf[0..size-1]
198
203
  @rbuf = @rbuf[size..-1]
@@ -25,6 +25,7 @@ module Roma
25
25
  v = Marshal.load(ddata)[0]
26
26
  return send_data("END\r\n") if v.length <= s[2].to_i
27
27
  ret = v.at(s[2].to_i)
28
+ ret = "" unless ret
28
29
  return send_data("VALUE #{s[1]} 0 #{ret.length}\r\n#{ret}\r\nEND\r\n")
29
30
  else
30
31
  return send_data("END\r\n")
@@ -1248,8 +1249,20 @@ module Roma
1248
1249
  # | [<end of dump>]->|
1249
1250
  # |<-['STORED'\r\n] |
1250
1251
  def ev_alist_spushv(s)
1252
+ if s.length != 3
1253
+ @log.error("#{__method__}:wrong number of arguments(#{s})")
1254
+ return send_data("CLIENT_ERROR Wrong number of arguments.\r\n")
1255
+ end
1256
+ if @stats.spushv_protection
1257
+ @log.info("#{__method__}:In spushv_protection")
1258
+ return send_data("SERVER_ERROR In spushv_protection.\r\n")
1259
+ end
1260
+ @stats.run_receive_a_vnode["#{s[1]}_#{s[2]}"] = true
1261
+
1262
+ $roma.stop_clean_up
1263
+
1251
1264
  send_data("READY\r\n")
1252
- @stats.run_receive_a_vnode = true
1265
+
1253
1266
  count = 0
1254
1267
  loop {
1255
1268
  context_bin = read_bytes(20, 100)
@@ -1268,12 +1281,25 @@ module Roma
1268
1281
  count += 1 if @storages[s[1]].load_stream_dump(vn, last, clk, expt, k, v)
1269
1282
  end
1270
1283
  }
1271
- send_data("STORED\r\n")
1284
+ if @stats.spushv_protection
1285
+ @log.info("#{__method__}:Canceled because of spushv_protection")
1286
+ send_data("CANCELED\r\n")
1287
+ else
1288
+ send_data("STORED\r\n")
1289
+ end
1272
1290
  @log.debug("alist #{count} keys loaded.")
1291
+ rescue Storage::StorageException => e
1292
+ @log.error("#{e.inspect} #{$@}")
1293
+ close_connection
1294
+ if Config.const_defined?(:STORAGE_EXCEPTION_ACTION) &&
1295
+ Config::STORAGE_EXCEPTION_ACTION == :shutdown
1296
+ @log.error("#{__method__}:Romad will stop")
1297
+ @stop_event_loop = true
1298
+ end
1273
1299
  rescue => e
1274
1300
  @log.error("#{e}\n#{$@}")
1275
1301
  ensure
1276
- @stats.run_receive_a_vnode = false
1302
+ @stats.run_receive_a_vnode.delete("#{s[1]}_#{s[2]}") if s.length == 3
1277
1303
  end
1278
1304
 
1279
1305
  private
@@ -16,6 +16,11 @@ module Roma
16
16
 
17
17
  # get <key>*\r\n
18
18
  def ev_get(s)
19
+ if s.length < 2
20
+ @log.error("get:wrong number of arguments(#{s})")
21
+ return send_data("CLIENT_ERROR Wrong number of arguments.\r\n")
22
+ end
23
+
19
24
  return ev_gets(s) if s.length > 2
20
25
 
21
26
  key,hname = s[1].split("\e")
@@ -111,6 +116,11 @@ module Roma
111
116
 
112
117
  # delete <key> [<time>] [noreply]\r\n
113
118
  def ev_delete(s)
119
+ if s.length < 2
120
+ @log.error("delete:wrong number of arguments(#{s})")
121
+ return send_data("CLIENT_ERROR Wrong number of arguments.\r\n")
122
+ end
123
+
114
124
  key,hname = s[1].split("\e")
115
125
  hname ||= @defhash
116
126
  d = Digest::SHA1.hexdigest(key).hex % @rttable.hbits
@@ -490,16 +500,27 @@ module Roma
490
500
  end
491
501
 
492
502
  def set(fnc,s)
503
+ if s.length != 5
504
+ @log.error("set:wrong number of arguments(#{s})")
505
+ return send_data("CLIENT_ERROR Wrong number of arguments.\r\n")
506
+ end
507
+
508
+ bytes = s[4].to_i
509
+ if bytes < 0
510
+ @log.error("set:wrong key size(#{s})")
511
+ return send_data("CLIENT_ERROR Wrong key size.\r\n")
512
+ end
513
+
493
514
  key,hname = s[1].split("\e")
494
515
  hname ||= @defhash
495
516
  d = Digest::SHA1.hexdigest(key).hex % @rttable.hbits
496
- v = read_bytes(s[4].to_i)
517
+ v = read_bytes(bytes)
497
518
  read_bytes(2)
498
519
  vn = @rttable.get_vnode_id(d)
499
520
  nodes = @rttable.search_nodes_for_write(vn)
500
521
  if nodes[0] != @nid
501
522
  @log.warn("forward #{fnc} key=#{key} vn=#{vn} to #{nodes[0]}")
502
- res = send_cmd(nodes[0],"f#{fnc} #{s[1]} #{d} #{s[3]} #{v.length}\r\n#{v}\r\n")
523
+ res = send_cmd(nodes[0],"f#{fnc} #{s[1]} #{d} #{s[3]} #{s[4]}\r\n#{v}\r\n")
503
524
  if res == nil || res.start_with?("ERROR")
504
525
  return send_data("SERVER_ERROR Message forward failed.\r\n")
505
526
  end
@@ -53,6 +53,10 @@ module Roma
53
53
  start_wb_process
54
54
  timer
55
55
 
56
+ if @stats.join_ap
57
+ AsyncProcess::queue.push(AsyncMessage.new('start_join_process'))
58
+ end
59
+
56
60
  # select a kind of system call
57
61
  if Config.const_defined?(:CONNECTION_USE_EPOLL) && Config::CONNECTION_USE_EPOLL
58
62
  @log.info("use an epoll")
@@ -133,6 +137,15 @@ module Roma
133
137
 
134
138
  def daemon?; @stats.daemon; end
135
139
 
140
+ def stop_clean_up
141
+ @stats.last_clean_up = Time.now
142
+ while(@stats.run_storage_clean_up)
143
+ @log.info("Storage clean up process will be stop.")
144
+ @storages.each_value{|st| st.stop_clean_up}
145
+ sleep 0.005
146
+ end
147
+ end
148
+
136
149
  private
137
150
 
138
151
  def initialize_stats
@@ -144,7 +157,10 @@ module Roma
144
157
  end
145
158
  if Config.const_defined?(:WB_COMMAND_MAP)
146
159
  @stats.wb_command_map = Config::WB_COMMAND_MAP
147
- end
160
+ end
161
+ if Config.const_defined?(:STORAGE_CLEAN_UP_INTERVAL)
162
+ @stats.clean_up_interval = Config::STORAGE_CLEAN_UP_INTERVAL
163
+ end
148
164
  end
149
165
 
150
166
  def initialize_connection
@@ -463,14 +479,6 @@ module Roma
463
479
  nil
464
480
  end
465
481
 
466
- def acquire_vnodes
467
- return if @stats.run_acquire_vnodes || @rttable.nodes.length < 2
468
-
469
- if @rttable.vnode_balance(@stats.ap_str)==:less
470
- Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_acquire_vnodes_process'))
471
- end
472
- end
473
-
474
482
  def timer
475
483
  t = Thread.new do
476
484
  loop do
@@ -495,10 +503,9 @@ module Roma
495
503
  nodes_check(nodes)
496
504
  end
497
505
 
498
- if (@stats.run_acquire_vnodes || @stats.run_recover) &&
506
+ if (@stats.run_join || @stats.run_recover || @stats.run_balance) &&
499
507
  @stats.run_storage_clean_up
500
- @storages.each_value{|st| st.stop_clean_up}
501
- @log.info("stop a storage clean up process")
508
+ stop_clean_up
502
509
  end
503
510
  end
504
511
 
@@ -522,15 +529,14 @@ module Roma
522
529
  start_sync_routing_process
523
530
  end
524
531
 
525
- if @stats.join_ap || @stats.enabled_vnodes_balance
526
- acquire_vnodes
527
- end
528
-
529
532
  if (@rttable.enabled_failover &&
530
533
  @stats.run_storage_clean_up == false &&
531
- @stats.run_acquire_vnodes == false &&
534
+ @stats.run_balance == false &&
532
535
  @stats.run_recover == false &&
533
- @stats.run_iterate_storage == false)
536
+ @stats.run_iterate_storage == false &&
537
+ @stats.run_join == false &&
538
+ @stats.run_receive_a_vnode.empty? &&
539
+ @stats.do_clean_up?)
534
540
  Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('start_storage_clean_up_process'))
535
541
  end
536
542
 
@@ -570,7 +576,7 @@ module Roma
570
576
  end
571
577
 
572
578
  def start_sync_routing_process
573
- return if @stats.run_acquire_vnodes || @stats.run_recover || @stats.run_sync_routing
579
+ return if @stats.run_join || @stats.run_recover || @stats.run_balance || @stats.run_sync_routing
574
580
 
575
581
  nodes = @rttable.nodes
576
582
  return if nodes.length == 1 && nodes[0] == @stats.ap_str
@@ -612,7 +618,7 @@ module Roma
612
618
  end
613
619
 
614
620
  def routing_hash_comparison(nid,id='0')
615
- return :skip if @stats.run_acquire_vnodes || @stats.run_recover
621
+ return :skip if @stats.run_join || @stats.run_recover || @stats.run_balance
616
622
 
617
623
  h = async_send_cmd(nid,"mklhash #{id}\r\n")
618
624
  if h && h.start_with?("ERROR") == false && @rttable.mtree.get(id) != h
@@ -1,10 +1,13 @@
1
1
  require 'roma/routing/rttable'
2
+ require 'roma/routing/random_partitioner'
2
3
 
3
4
  module Roma
4
5
  module Routing
5
6
 
6
7
  class ChurnbasedRoutingTable < RoutingTable
7
8
 
9
+ include Routing::RandomPartitioner
10
+
8
11
  attr :fname
9
12
  attr :log_fd
10
13
  attr :log_name
@@ -97,6 +100,23 @@ module Roma
97
100
  @rd.nodes.length >= @rd.rn
98
101
  end
99
102
 
103
+ def can_i_release?(ap_str, rep_host)
104
+ buf = self.nodes
105
+ buf.delete(ap_str)
106
+ hosts = []
107
+
108
+ unless rep_host
109
+ buf.each{ |node|
110
+ host = node.split(/[:_]/)[0]
111
+ hosts << host unless hosts.include?(host)
112
+ }
113
+ else
114
+ hosts = buf
115
+ end
116
+
117
+ hosts.length < @rd.rn
118
+ end
119
+
100
120
  # Retuens the list of losted-data vnode newer than argument time.
101
121
  def search_lost_vnodes(t)
102
122
  ret = []
@@ -308,7 +328,7 @@ module Roma
308
328
  end
309
329
  }
310
330
 
311
- @log.debug("#{__FILE__}:#{__LINE__}:n=#{n} pcount=#{pcount} scount=#{scount}")
331
+ @log.debug("#{__method__}:n=#{n} pcount=#{pcount} scount=#{scount}")
312
332
 
313
333
  if pcount > n
314
334
  return :over
@@ -318,6 +338,13 @@ module Roma
318
338
  :even
319
339
  end
320
340
 
341
+ def has_node?(ap_str)
342
+ self.each_vnode do |vn, nids|
343
+ return true if nids.include?(ap_str)
344
+ end
345
+ false
346
+ end
347
+
321
348
  end # class ChurnbasedRoutingTable
322
349
 
323
350
  end # module Routing