roma 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/LICENSE.rdoc +675 -0
  2. data/README.rdoc +0 -0
  3. data/Rakefile +70 -0
  4. data/bin/mkrecent +7 -0
  5. data/bin/mkroute +7 -0
  6. data/bin/recoverlost +8 -0
  7. data/bin/recoverlost_alist +8 -0
  8. data/bin/romad +7 -0
  9. data/bin/sample_watcher +8 -0
  10. data/bin/sample_watcher2 +8 -0
  11. data/bin/simple_bench +8 -0
  12. data/bin/ssroute +7 -0
  13. data/bin/tribunus +7 -0
  14. data/lib/roma/async_process.rb +696 -0
  15. data/lib/roma/command/bg_command_receiver.rb +188 -0
  16. data/lib/roma/command/mh_command_receiver.rb +117 -0
  17. data/lib/roma/command/receiver.rb +287 -0
  18. data/lib/roma/command/rt_command_receiver.rb +147 -0
  19. data/lib/roma/command/st_command_receiver.rb +564 -0
  20. data/lib/roma/command/util_command_receiver.rb +67 -0
  21. data/lib/roma/command/vn_command_receiver.rb +143 -0
  22. data/lib/roma/command_plugin.rb +11 -0
  23. data/lib/roma/config.rb +64 -0
  24. data/lib/roma/event/con_pool.rb +140 -0
  25. data/lib/roma/event/handler.rb +159 -0
  26. data/lib/roma/plugin/plugin_alist.rb +1572 -0
  27. data/lib/roma/plugin/plugin_debug.rb +19 -0
  28. data/lib/roma/plugin/plugin_test.rb +14 -0
  29. data/lib/roma/romad.rb +582 -0
  30. data/lib/roma/routing/cb_rttable.rb +326 -0
  31. data/lib/roma/routing/merkle_tree.rb +54 -0
  32. data/lib/roma/routing/rttable.rb +148 -0
  33. data/lib/roma/stats.rb +112 -0
  34. data/lib/roma/storage/basic_storage.rb +510 -0
  35. data/lib/roma/storage/dbm_storage.rb +80 -0
  36. data/lib/roma/storage/dummy_storage.rb +44 -0
  37. data/lib/roma/storage/rh_storage.rb +35 -0
  38. data/lib/roma/storage/sqlite3_storage.rb +73 -0
  39. data/lib/roma/storage/tc_storage.rb +133 -0
  40. data/lib/roma/tools/mkrecent.rb +138 -0
  41. data/lib/roma/tools/mkroute.rb +52 -0
  42. data/lib/roma/tools/recoverlost.rb +9 -0
  43. data/lib/roma/tools/recoverlost_alist.rb +9 -0
  44. data/lib/roma/tools/recoverlost_lib.rb +217 -0
  45. data/lib/roma/tools/sample_watcher.rb +38 -0
  46. data/lib/roma/tools/sample_watcher2.rb +38 -0
  47. data/lib/roma/tools/simple_bench.rb +57 -0
  48. data/lib/roma/tools/ssroute.rb +23 -0
  49. data/lib/roma/tools/tribunus.rb +299 -0
  50. data/lib/roma/version.rb +4 -0
  51. data/lib/roma/write_behind.rb +179 -0
  52. data/test/rcirb.rb +16 -0
  53. data/test/roma-test-utils.rb +65 -0
  54. data/test/run-test.rb +16 -0
  55. data/test/t_cpdata.rb +277 -0
  56. data/test/t_listplugin.rb +592 -0
  57. data/test/t_rclient.rb +318 -0
  58. data/test/t_routing_data.rb +100 -0
  59. data/test/t_storage.rb +644 -0
  60. data/test/t_writebehind.rb +200 -0
  61. metadata +134 -0
@@ -0,0 +1,326 @@
1
+ require 'roma/routing/rttable'
2
+
3
+ module Roma
4
+ module Routing
5
+
6
+ class ChurnbasedRoutingTable < RoutingTable
7
+
8
+ attr :fname
9
+ attr :log_fd
10
+ attr :log_name
11
+ attr :trans # transaction
12
+ attr :leave_proc
13
+ attr :lost_proc
14
+ attr_accessor :lost_action
15
+ attr_reader :version_of_nodes
16
+ attr_reader :min_version
17
+
18
+ def initialize(rd,fname)
19
+ super(rd)
20
+ @rd.nodes.sort!
21
+ @trans={}
22
+ @fname=fname
23
+ @leave_proc=nil
24
+ @lost_proc=nil
25
+ @lost_action=:no_action
26
+ @enabled_failover=false
27
+ @lock = Mutex.new
28
+ @version_of_nodes = Hash.new(0)
29
+ @min_version = nil
30
+ open_log
31
+ end
32
+
33
+ def get_stat(ap)
34
+ ret = super(ap)
35
+ ret['routing.lost_action'] = @lost_action.to_s
36
+ ret['routing.version_of_nodes'] = @version_of_nodes.inspect
37
+ ret['routing.min_version'] = @min_version
38
+ ret
39
+ end
40
+
41
+ def set_version(nid,ver)
42
+ @version_of_nodes[nid] = ver
43
+ if @min_version == nil || @min_version > ver
44
+ @min_version = ver
45
+ end
46
+ end
47
+
48
+ def find_min_version
49
+ ret = 0xffffff
50
+ @version_of_nodes.each_value{|ver| ret = ver if ret > ver}
51
+ ret
52
+ end
53
+
54
+ def set_leave_proc(&block)
55
+ @leave_proc=block
56
+ end
57
+
58
+ def set_lost_proc(&block)
59
+ @lost_proc=block
60
+ end
61
+
62
+ def open_log
63
+ log_list=@rd.get_file_list(@fname)
64
+ if log_list.length==0
65
+ @log_name="#{@fname}.1"
66
+ else
67
+ if File::stat("#{@fname}.#{log_list.last[0]}").size == 0
68
+ @log_name="#{@fname}.#{log_list.last[0]}"
69
+ else
70
+ @log_name="#{@fname}.#{log_list.last[0]+1}"
71
+ end
72
+ end
73
+ @log_fd=File.open(@log_name,"a")
74
+ end
75
+
76
+ def write_log_setroute(vn, clk, nids)
77
+ log="setroute #{vn} #{clk}"
78
+ nids.each{ |nid| log << " #{nid}" }
79
+ write_log(log)
80
+ end
81
+
82
+ def write_log(line)
83
+ # log rotation
84
+ if File::stat(@log_name).size > 1000 * 1024
85
+ close_log
86
+ open_log
87
+ end
88
+ t = Time.now
89
+ tstr = "#{t.strftime('%Y-%m-%dT%H:%M:%S')}.#{t.usec}"
90
+ @log_fd.write("#{tstr} #{line}\n")
91
+ @log_fd.flush
92
+ end
93
+
94
+ def close_log
95
+ @log_fd.close
96
+ end
97
+
98
+ def can_i_recover?
99
+ @rd.nodes.length >= @rd.rn
100
+ end
101
+
102
+ # Retuens the list of losted-data vnode newer than argument time.
103
+ def search_lost_vnodes(t)
104
+ ret = []
105
+ @rd.each_log_all(@fname){|log_t,line|
106
+ next if t > log_t
107
+ s = line.split(/ /)
108
+ if s[0] == 'setroute' && s.length == 3
109
+ # vnode has a no pnode. therefor this vnode was lost.
110
+ ret << s[1].to_i
111
+ end
112
+ }
113
+ ret
114
+ end
115
+
116
+ # select a vnodes where short of redundancy.
117
+ def select_a_short_vnodes(exclued_nodes)
118
+ ret = []
119
+ @rd.v_idx.each_pair{|vn, nids|
120
+ if nids.length < @rd.rn && list_include?(nids,exclued_nodes) == false
121
+ ret << [vn,nids]
122
+ end
123
+ }
124
+ ret
125
+ end
126
+
127
+ # vnode sampling without +without_nodes+
128
+ def sample_vnode(without_nodes)
129
+ short_idx = {}
130
+ idx = {}
131
+ @rd.v_idx.each_pair{|vn, nids|
132
+ unless list_include?(nids, without_nodes)
133
+ idx[vn] = nids
134
+ short_idx[vn] = nids if nids.length < @rd.rn
135
+ end
136
+ }
137
+ idx = short_idx if short_idx.length > 0
138
+
139
+ ks = idx.keys
140
+ return nil if ks.length == 0
141
+ vn = ks[rand(ks.length)]
142
+ nids = idx[vn]
143
+ [vn, nids]
144
+ end
145
+
146
+ def list_include?(list,nodes)
147
+ nodes.each{|nid|
148
+ return true if list.include?(nid)
149
+ }
150
+ false
151
+ end
152
+ private :list_include?
153
+
154
+ def set_route(vn, clk, nids)
155
+ return "#{vn} is not found." unless @rd.v_idx.key?(vn)
156
+ @lock.synchronize {
157
+ return "It's old table." if @rd.v_clk[vn] > clk
158
+ nids.each{ |nid|
159
+ add_node(nid) unless @rd.nodes.include?(nid)
160
+ }
161
+ @rd.v_idx[vn] = nids.clone
162
+ clk += 1
163
+ @rd.v_clk[vn] = clk
164
+ @mtree.set(vn, nids)
165
+ write_log_setroute(vn, clk, nids)
166
+ return clk
167
+ }
168
+ end
169
+
170
+ def add_node(nid)
171
+ unless @rd.nodes.include?(nid)
172
+ @rd.nodes << nid
173
+ @rd.nodes.sort!
174
+ write_log("join #{nid}")
175
+ end
176
+ end
177
+
178
+ def enabled_failover=(b)
179
+ @enabled_failover=b
180
+ @fail_cnt.clear
181
+ end
182
+
183
+ def enabled_failover
184
+ @enabled_failover
185
+ end
186
+
187
+ def leave(nid)
188
+ unless @enabled_failover
189
+ return
190
+ end
191
+ return unless @rd.nodes.include?(nid)
192
+
193
+ @leave_proc.call(nid) if @leave_proc
194
+ @rd.nodes.delete(nid)
195
+ @version_of_nodes.delete(nid)
196
+ @min_version = find_min_version
197
+
198
+ @log.warn("#{nid} just failed.")
199
+ write_log("leave #{nid}")
200
+
201
+ lost_vnodes=[]
202
+ @lock.synchronize {
203
+ @rd.v_idx.each_pair{ |vn, nids|
204
+ buf = nids.clone
205
+ if buf.delete(nid)
206
+ set_route_and_inc_clk_inside_sync(vn, buf)
207
+ if buf.length == 0
208
+ lost_vnodes << vn
209
+ @log.error("Vnode data is lost.(Vnode=#{vn})")
210
+ end
211
+ end
212
+ }
213
+ }
214
+ if lost_vnodes.length > 0
215
+ @lost_proc.call if @lost_proc
216
+ if @lost_action == :auto_assign
217
+ lost_vnodes.each{ |vn|
218
+ set_route_and_inc_clk_inside_sync( vn, next_alive_vnode(vn) )
219
+ }
220
+ end
221
+ end
222
+ @fail_cnt.delete(nid)
223
+ end
224
+
225
+ def set_route_and_inc_clk_inside_sync(vn, nodes)
226
+ @rd.v_idx[vn] = nodes
227
+ clk = @rd.v_clk[vn] + 1
228
+ @rd.v_clk[vn] = clk
229
+ @mtree.set(vn, nodes)
230
+ write_log_setroute(vn, clk, nodes)
231
+ clk
232
+ end
233
+ private :set_route_and_inc_clk_inside_sync
234
+
235
+ def next_alive_vnode(vn)
236
+ svn = vn
237
+ while( (vn = @rd.next_vnode(vn)) != svn )
238
+ return @rd.v_idx[vn].clone if @rd.v_idx[vn].length != 0
239
+ end
240
+ []
241
+ end
242
+ private :next_alive_vnode
243
+
244
+ def each_vnode
245
+ @rd.v_idx.each_pair{ |k, v| yield(k, v) }
246
+ end
247
+
248
+ def v_idx
249
+ @rd.v_idx.clone
250
+ end
251
+
252
+ def search_nodes_for_write(vn)
253
+ return @trans[vn][0].clone if @trans.key?(vn)
254
+ @rd.v_idx[vn].clone
255
+ rescue
256
+ nil
257
+ end
258
+
259
+ def search_nodes_with_clk(vn)
260
+ @lock.synchronize {
261
+ return [@rd.v_clk[vn], @rd.v_idx[vn].clone]
262
+ }
263
+ rescue
264
+ nil
265
+ end
266
+
267
+ # +vn+: vnode-id
268
+ # +nids+: node-id list
269
+ def transaction(vn, nids)
270
+ return false if @trans.key?(vn)
271
+ @trans[vn]=[nids.clone, Time.now]
272
+ true
273
+ end
274
+
275
+ def commit(vn)
276
+ return false unless @trans.key?(vn)
277
+ @lock.synchronize {
278
+ @rd.v_idx[vn]=@trans[vn][0]
279
+ @trans.delete(vn)
280
+ clk = @rd.v_clk[vn] + 1
281
+ @rd.v_clk[vn] = clk
282
+ @mtree.set(vn, @rd.v_idx[vn])
283
+ write_log_setroute(vn, clk, @rd.v_idx[vn])
284
+ return clk
285
+ }
286
+ end
287
+
288
+ def rollback(vn)
289
+ @trans.delete(vn)
290
+ end
291
+
292
+ # +sec+: elapsed-time
293
+ def delete_old_trans(sec=3600)
294
+ @trans.delete_if{|vn,val| val[1] < Time.now-sec }
295
+ end
296
+
297
+ # Returns the status of vnode balance.
298
+ # +ap+: my address_port string(ex."roma0_11211")
299
+ def vnode_balance(ap)
300
+ # amount of primary at node = amount of vnode / amount of node
301
+ n = (2**div_bits) / nodes.length
302
+
303
+ pcount = scount = 0
304
+ @rd.v_idx.each_pair{ |vn, nids|
305
+ next if nids == nil or nids.length == 0
306
+ if nids[0] == ap
307
+ pcount += 1
308
+ elsif nids.include?(ap)
309
+ scount += 1
310
+ end
311
+ }
312
+
313
+ @log.debug("#{__FILE__}:#{__LINE__}:n=#{n} pcount=#{pcount} scount=#{scount}")
314
+
315
+ if pcount > n*1.1
316
+ return :over
317
+ elsif pcount < n*0.9
318
+ return :less
319
+ end
320
+ :even
321
+ end
322
+
323
+ end # class ChurnbasedRoutingTable
324
+
325
+ end # module Routing
326
+ end # module Roma
@@ -0,0 +1,54 @@
1
+ require 'digest/sha1'
2
+
3
+ module Roma
4
+ module Routing
5
+
6
+ class MerkleTree
7
+
8
+ attr :tree
9
+ attr :div_bits
10
+ attr :dgst_bits
11
+
12
+ def initialize(dgst_bits,div_bits)
13
+ @tree = {}
14
+ @dgst_bits = dgst_bits
15
+ @div_bits = div_bits
16
+ create_tree_instance('0')
17
+ end
18
+
19
+ def set(vn,nodes)
20
+ id = '0' + (vn >> (@dgst_bits-@div_bits)).to_s(2).rjust(@div_bits,'0')
21
+ @tree[id] = Digest::SHA1.hexdigest(nodes.to_s)
22
+ update(parent(id))
23
+ end
24
+
25
+ def get(id)
26
+ @tree[id]
27
+ end
28
+
29
+ def to_vn(id)
30
+ id[1,id.length].to_i(2) << (@dgst_bits-@div_bits)
31
+ end
32
+
33
+ private
34
+
35
+ def create_tree_instance(id)
36
+ @tree[id] = 0
37
+ return if id.length > @div_bits
38
+ create_tree_instance("#{id}0")
39
+ create_tree_instance("#{id}1")
40
+ end
41
+
42
+ def update(id)
43
+ @tree[id] = Digest::SHA1.hexdigest("#{@tree[id+'0']}:#{@tree[id+'1']}")
44
+ update(parent(id)) if id.length != 1
45
+ end
46
+
47
+ def parent(id)
48
+ id.chop
49
+ end
50
+
51
+ end # class MerkleTree
52
+
53
+ end # module Routing
54
+ end # module Roma
@@ -0,0 +1,148 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'roma/logging/rlogger'
3
+ require 'roma/routing/routing_data'
4
+ require 'roma/routing/merkle_tree'
5
+ require 'yaml'
6
+ require 'json'
7
+
8
+ module Roma
9
+ module Routing
10
+
11
+ class RoutingTable
12
+
13
+ attr :rd
14
+ attr :search_mask
15
+ attr :fail_cnt
16
+ attr :mtree
17
+ attr_reader :hbits
18
+ attr_reader :rn
19
+ attr_reader :div_bits
20
+ attr_accessor :fail_cnt_threshold
21
+ attr_accessor :fail_cnt_gap
22
+
23
+ def initialize(rd)
24
+ @log = Roma::Logging::RLogger.instance
25
+ @rd = rd
26
+ @rn = @rd.rn
27
+ @div_bits=@rd.div_bits
28
+ @hbits = 2**@rd.dgst_bits
29
+ @search_mask = @rd.search_mask
30
+ @fail_cnt = Hash.new(0)
31
+ @fail_cnt_threshold = 5
32
+ @fail_cnt_gap = 0
33
+ @fail_time = Time.now
34
+ init_mtree
35
+ end
36
+
37
+ def get_stat(ap)
38
+
39
+ pn = sn = short = lost = 0
40
+ @rd.v_idx.each_pair{|vn, nids|
41
+ if nids == nil || nids.length == 0
42
+ lost += 1
43
+ next
44
+ elsif nids[0] == ap
45
+ pn += 1
46
+ elsif nids.include?(ap)
47
+ sn += 1
48
+ end
49
+ short += 1 if nids.length < @rd.rn
50
+ }
51
+
52
+ ret = {}
53
+ ret['routing.redundant'] = @rn
54
+ ret['routing.nodes.length'] = nodes.length
55
+ ret['routing.nodes'] = nodes.inspect
56
+ ret['routing.dgst_bits'] = @rd.dgst_bits
57
+ ret['routing.div_bits'] = @div_bits
58
+ ret['routing.vnodes.length'] = vnodes.length
59
+ ret['routing.primary'] = pn
60
+ ret['routing.secondary'] = sn
61
+ ret['routing.short_vnodes'] = short
62
+ ret['routing.lost_vnodes'] = lost
63
+ ret['routing.fail_cnt_threshold'] = @fail_cnt_threshold
64
+ ret['routing.fail_cnt_gap'] = @fail_cnt_gap
65
+ ret
66
+ end
67
+
68
+ def init_mtree
69
+ @mtree = MerkleTree.new(@rd.dgst_bits,@rd.div_bits)
70
+ @rd.v_idx.each_pair{ |vn, nids|
71
+ @mtree.set(vn,nids)
72
+ }
73
+ end
74
+
75
+ def nodes
76
+ @rd.nodes.clone
77
+ end
78
+
79
+ def vnodes
80
+ @rd.v_idx.keys
81
+ end
82
+
83
+ # ハッシュ値からvnode idを返す
84
+ def get_vnode_id(d)
85
+ d & @search_mask
86
+ end
87
+
88
+ # vnode があるノードIDの配列を返す
89
+ # +vn+: vnode id
90
+ def search_nodes(vn)
91
+ @rd.v_idx[vn].clone
92
+ rescue
93
+ nil
94
+ end
95
+
96
+ # 離脱ノードを検索リストから削除する
97
+ # +nid+: 離脱ノード
98
+ def leave(nid)
99
+ @rd.nodes.delete(nid)
100
+ # リストから nid を消す
101
+ @rd.v_idx.each_pair{ |vn, nids|
102
+ nids.delete_if{ |nid2| nid2 == nid}
103
+ if nids.length == 0
104
+ @log.error("Vnode data is lost.(Vnode=#{vn})")
105
+ end
106
+ @mtree.set(vn,nids)
107
+ }
108
+ @fail_cnt.delete(nid)
109
+ end
110
+
111
+ def dump
112
+ Marshal.dump(@rd)
113
+ end
114
+
115
+ def dump_yaml
116
+ YAML.dump(@rd)
117
+ end
118
+
119
+ def dump_json
120
+ JSON.generate(
121
+ [{:dgst_bits=>@rd.dgst_bits,:div_bits=>@rd.div_bits,:rn=>@rd.rn},
122
+ @rd.nodes,@rd.v_idx])
123
+ end
124
+
125
+ def proc_failed(nid)
126
+ t = Time.now
127
+ if t - @fail_time > @fail_cnt_gap
128
+ @fail_cnt[nid] += 1
129
+ if @fail_cnt[nid] >= @fail_cnt_threshold
130
+ leave(nid)
131
+ end
132
+ end
133
+ @fail_time = t
134
+ end
135
+
136
+ def proc_succeed(nid)
137
+ @fail_cnt.delete(nid)
138
+ end
139
+
140
+ # v_idx から nodes を再構築する
141
+ def create_nodes_from_v_idx
142
+ @rd.create_nodes_from_v_idx
143
+ end
144
+
145
+ end # class RoutingTable
146
+
147
+ end # module Routing
148
+ end # module Roma
data/lib/roma/stats.rb ADDED
@@ -0,0 +1,112 @@
1
+ require 'singleton'
2
+ require 'roma/config'
3
+
4
+ module Roma
5
+
6
+ class Stats
7
+ include Singleton
8
+
9
+ # command options
10
+ attr_accessor :address, :port
11
+ attr_accessor :daemon
12
+ attr_accessor :join_ap
13
+ attr_accessor :start_with_failover
14
+ attr_accessor :name
15
+ attr_accessor :verbose
16
+ attr_accessor :enabled_repetition_host_in_routing
17
+
18
+ # proc mode
19
+ attr_accessor :enabled_vnodes_balance
20
+
21
+ # proc status
22
+ attr_accessor :run_acquire_vnodes
23
+ attr_accessor :run_recover
24
+ attr_accessor :run_sync_routing
25
+ attr_accessor :run_iterate_storage
26
+ attr_accessor :run_storage_clean_up
27
+ attr_accessor :run_receive_a_vnode
28
+ attr_accessor :run_release
29
+
30
+ # proc param
31
+ attr_accessor :stream_copy_wait_param
32
+
33
+ # compressed redundant param
34
+ attr_accessor :size_of_zredundant
35
+
36
+ # performance counter
37
+ attr_accessor :write_count
38
+ attr_accessor :read_count
39
+ attr_accessor :delete_count
40
+ attr_accessor :out_count
41
+ attr_accessor :out_message_count
42
+ attr_accessor :redundant_count
43
+
44
+ def initialize
45
+ @run_acquire_vnodes = false
46
+ @run_recover = false
47
+ @run_sync_routing = false
48
+ @run_iterate_storage = false
49
+ @run_storage_clean_up = false
50
+ @run_receive_a_vnode = false
51
+ @run_release = false
52
+ @stream_copy_wait_param =
53
+ Roma::Config::DATACOPY_STREAM_COPY_WAIT_PARAM
54
+ @enabled_vnodes_balance = nil
55
+ @write_count = 0
56
+ @read_count = 0
57
+ @delete_count = 0
58
+ @out_count = 0
59
+ @out_message_count = 0
60
+ @redundant_count = 0
61
+ @size_of_zredundant = 0
62
+ end
63
+
64
+ def ap_str
65
+ "#{@address}_#{port}"
66
+ end
67
+
68
+ def get_stat
69
+ ret = {}
70
+ ret['stats.address'] = @address
71
+ ret['stats.port'] = @port
72
+ ret['stats.daemon'] = @daemon
73
+ ret['stats.name'] = @name
74
+ ret['stats.verbose'] = @verbose
75
+ ret['stats.enabled_repetition_host_in_routing'] = @enabled_repetition_host_in_routing
76
+ ret['stats.run_acquire_vnodes'] = @run_acquire_vnodes
77
+ ret['stats.run_recover'] = @run_recover
78
+ ret['stats.run_sync_routing'] = @run_sync_routing
79
+ ret['stats.run_iterate_storage'] = @run_iterate_storage
80
+ ret['stats.run_storage_clean_up'] = @run_storage_clean_up
81
+ ret['stats.run_release'] = @run_release
82
+ ret['stats.stream_copy_wait_param'] = @stream_copy_wait_param
83
+ ret['stats.size_of_zredundant'] = @size_of_zredundant
84
+ ret['stats.write_count'] = @write_count
85
+ ret['stats.read_count'] = @read_count
86
+ ret['stats.delete_count'] = @delete_count
87
+ ret['stats.out_count'] = @out_count
88
+ ret['stats.out_message_count'] = @out_message_count
89
+ ret['stats.redundant_count'] = @redundant_count
90
+ ret
91
+ end
92
+
93
+ def clear_counters
94
+ clear_count(:@write_count)
95
+ clear_count(:@read_count)
96
+ clear_count(:@delete_count)
97
+ clear_count(:@out_count)
98
+ clear_count(:@out_message_count)
99
+ clear_count(:@redundant_count)
100
+ end
101
+
102
+ private
103
+
104
+ def clear_count(var)
105
+ if self.instance_variable_get(var) > 0xffffffff
106
+ self.instance_variable_set(var,0)
107
+ end
108
+ end
109
+
110
+ end # class Stats
111
+
112
+ end # module Roma