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.
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,67 @@
1
+ require 'roma/messaging/con_pool'
2
+
3
+ module Roma
4
+ module Command
5
+
6
+ module UtilCommandReceiver
7
+
8
+ def send_cmd(nid, cmd)
9
+ con = get_connection(nid)
10
+ con.send(cmd)
11
+ res = con.gets
12
+ if res
13
+ res.chomp!
14
+ @rttable.proc_succeed(nid)
15
+ return_connection(nid, con)
16
+ else
17
+ @rttable.proc_failed(nid)
18
+ end
19
+ res
20
+ rescue => e
21
+ @rttable.proc_failed(nid)
22
+ @log.error("#{e}\n#{$@}")
23
+ nil
24
+ end
25
+
26
+ def broadcast_cmd(cmd)
27
+ res={}
28
+ @rttable.nodes.each{|nid|
29
+ res[nid] = send_cmd(nid,cmd) if nid != @stats.ap_str
30
+ }
31
+ res
32
+ end
33
+
34
+ def async_send_cmd(nid, cmd)
35
+ con = Roma::Messaging::ConPool.instance.get_connection(nid)
36
+ con.write(cmd)
37
+ res = con.gets
38
+ Roma::Messaging::ConPool.instance.return_connection(nid, con)
39
+ if res
40
+ res.chomp!
41
+ @rttable.proc_succeed(nid)
42
+ else
43
+ @rttable.proc_failed(nid)
44
+ end
45
+ res
46
+ rescue => e
47
+ @rttable.proc_failed(nid)
48
+ @log.error("#{e}\n#{$@}")
49
+ nil
50
+ end
51
+
52
+ def async_broadcast_cmd(cmd,without_nids=nil)
53
+ without_nids=[@stats.ap_str] unless without_nids
54
+ res = {}
55
+ @rttable.nodes.each{ |nid|
56
+ res[nid] = async_send_cmd(nid,cmd) unless without_nids.include?(nid)
57
+ }
58
+ res
59
+ rescue => e
60
+ @log.error("#{e}\n#{$@}")
61
+ nil
62
+ end
63
+
64
+ end # module UtilCommandReceiver
65
+
66
+ end # module Command
67
+ end # module Roma
@@ -0,0 +1,143 @@
1
+ require 'roma/messaging/con_pool'
2
+ require 'roma/async_process'
3
+
4
+ module Roma
5
+ module Command
6
+
7
+ module VnodeCommandReceiver
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")
23
+ else
24
+ send_data("SERVER_ERROR #{res}\r\n")
25
+ end
26
+ rescue => e
27
+ @log.error("#{e}\n#{$@}")
28
+ end
29
+
30
+ # spushv <hash-name> <vnode-id>
31
+ # src dst
32
+ # | ['spushv' <hname> <vn>\r\n]->|
33
+ # |<-['READY'\r\n] |
34
+ # | [<dumpdata>]->|
35
+ # | : |
36
+ # | : |
37
+ # | [<end of dump>]->|
38
+ # |<-['STORED'\r\n] |
39
+ def ev_spushv(s)
40
+ send_data("READY\r\n")
41
+ @stats.run_receive_a_vnode = true
42
+ count = rcount = 0
43
+ @log.debug("#{__method__}:#{s.inspect} received.")
44
+ loop {
45
+ context_bin = read_bytes(20, 100)
46
+ vn, last, clk, expt, klen = context_bin.unpack('NNNNN')
47
+ break if klen == 0 # end of dump ?
48
+ k = read_bytes(klen)
49
+ vlen_bin = read_bytes(4, 100)
50
+ vlen, = vlen_bin.unpack('N')
51
+ if vlen != 0
52
+ v = read_bytes(vlen, 100)
53
+
54
+ if @storages[s[1]].load_stream_dump(vn, last, clk, expt, k, v)
55
+ count += 1
56
+ # @log.debug("#{__method__}:[#{vn} #{last} #{clk} #{expt} #{k}] was stored.")
57
+ else
58
+ rcount += 1
59
+ # @log.warn("#{__method__}:[#{vn} #{last} #{clk} #{expt} #{k}] was rejected.")
60
+ end
61
+ else
62
+ if @storages[s[1]].load_stream_dump(vn, last, clk, expt, k, nil)
63
+ # @log.debug("#{__method__}:[#{vn} #{last} #{clk} #{expt} #{k}] was stored.")
64
+ count += 1
65
+ else
66
+ rcount += 1
67
+ # @log.warn("#{__method__}:[#{vn} #{last} #{clk} #{expt} #{k}] was rejected.")
68
+ end
69
+ end
70
+ }
71
+ send_data("STORED\r\n")
72
+ @log.debug("#{__method__}:#{s[2]} #{count} keys loaded. #{rcount} keys rejected.")
73
+ rescue => e
74
+ @log.error("#{e}\n#{$@}")
75
+ ensure
76
+ @stats.run_receive_a_vnode = false
77
+ end
78
+
79
+ # reqpushv <vnode-id> <node-id> <is primary?>
80
+ # src dst
81
+ # |<-['reqpushv <vn> <nid> <p?>\r\n'] |
82
+ # | ['PUSHED'\r\n]->|
83
+ def ev_reqpushv(s)
84
+ if s.length!=4
85
+ send_data("CLIENT_ERROR usage:reqpushv vnode-id node-id primary-flag(true/false)\r\n")
86
+ return
87
+ end
88
+
89
+ if @stats.run_iterate_storage == true
90
+ @log.warn("reqpushv rejected:#{s}")
91
+ send_data("REJECTED\r\n")
92
+ return
93
+ end
94
+
95
+ Roma::AsyncProcess::queue.push(Roma::AsyncMessage.new('reqpushv',[s[1],s[2],s[3]]))
96
+ send_data("PUSHED\r\n")
97
+ rescue =>e
98
+ @log.error("#{e}\n#{$@}")
99
+ end
100
+
101
+ def req_push_a_vnode(vn, src_nid, is_primary)
102
+ con = Roma::Messaging::ConPool.instance.get_connection(src_nid)
103
+ con.write("reqpushv #{vn} #{@nid} #{is_primary}\r\n")
104
+ res = con.gets # receive 'PUSHED\r\n' | 'REJECTED\r\n'
105
+ Roma::Messaging::ConPool.instance.return_connection(src_nid,con)
106
+ # waiting for pushv
107
+ count = 0
108
+ while @rttable.search_nodes(vn).include?(@nid)==false && count < 300
109
+ sleep 0.1
110
+ count += 1
111
+ end
112
+ rescue =>e
113
+ @log.error("#{e}\n#{$@}")
114
+ @rttable.proc_failed(src_nid)
115
+ false
116
+ end
117
+
118
+ def em_receive_dump(hname, len)
119
+ dmp = read_bytes(len)
120
+ read_bytes(2)
121
+ if gets == "END\r\n"
122
+ if @storages.key?(hname)
123
+ n = @storages[hname].load(dmp)
124
+ @log.debug("#{dmp.length} bytes received.(#{n} keys loaded.)")
125
+ return true
126
+ else
127
+ @log.error("receive_dump:@storages[#{hname}] dose not found.")
128
+ return "@storages[#{hname}] dose not found."
129
+ end
130
+ else
131
+ @log.error("receive_dump:END was not able to be received.")
132
+ return "END was not able to be received."
133
+ end
134
+ rescue =>e
135
+ @log.error("#{e}\n#{$@}")
136
+ "#{e}"
137
+ end
138
+ private :em_receive_dump
139
+
140
+ end # module VnodeCommandReceiver
141
+
142
+ end # module Command
143
+ end # module Roma
@@ -0,0 +1,11 @@
1
+ module Roma
2
+ module CommandPlugin
3
+ @@plugins=[]
4
+ def self.plugins
5
+ @@plugins.dup
6
+ end
7
+ def self.included(mod)
8
+ @@plugins << mod
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,64 @@
1
+ require 'roma/routing/rttable'
2
+ require 'roma/routing/cb_rttable'
3
+ require 'roma/storage/rh_storage'
4
+
5
+ module Roma
6
+
7
+ module Config
8
+ DEFAULT_PORT = 12000
9
+ DEFAULT_NAME = 'ROMA'
10
+
11
+ # :no_action | :auto_assign | :shutdown
12
+ DEFAULT_LOST_ACTION = :auto_assign
13
+
14
+ # log setting
15
+ LOG_SHIFT_AGE = 10
16
+ LOG_SHIFT_SIZE = 1024 * 1024 * 10
17
+ LOG_PATH = '.'
18
+ # :debug | :info | :warn | :error
19
+ LOG_LEVEL = :debug
20
+
21
+ # routing setting
22
+ RTTABLE_PATH = '.'
23
+
24
+ # storage setting
25
+ STORAGE_CLASS = Roma::Storage::RubyHashStorage
26
+ STORAGE_DIVNUM = 10
27
+ STORAGE_PATH = '.'
28
+ STORAGE_DUMP_PATH = '/tmp'
29
+ STORAGE_OPTION = ''
30
+
31
+ # 5 days ago
32
+ STORAGE_DELMARK_EXPTIME = 60 * 60 * 24 * 5
33
+
34
+ # data copy setting
35
+ DATACOPY_STREAM_COPY_WAIT_PARAM = 0.0001
36
+
37
+ # plugin setting
38
+ PLUGIN_FILES = []
39
+
40
+ # write-behind setting
41
+ WRITEBEHIND_PATH = './wb'
42
+ WRITEBEHIND_SHIFT_SIZE = 1024 * 1024 * 10
43
+
44
+ # redundant setting
45
+ REDUNDANT_ZREDUNDANT_SIZE = 0
46
+
47
+ def self.get_stat
48
+ ret = {}
49
+ ret['config.DEFAULT_LOST_ACTION'] = DEFAULT_LOST_ACTION
50
+ ret['config.LOG_SHIFT_AGE'] = LOG_SHIFT_AGE
51
+ ret['config.LOG_SHIFT_SIZE'] = LOG_SHIFT_SIZE
52
+ ret['config.LOG_PATH'] = File.expand_path(LOG_PATH)
53
+ ret['config.RTTABLE_PATH'] = File.expand_path(RTTABLE_PATH)
54
+ ret['config.STORAGE_DELMARK_EXPTIME'] = STORAGE_DELMARK_EXPTIME
55
+ ret['config.DATACOPY_STREAM_COPY_WAIT_PARAM'] = DATACOPY_STREAM_COPY_WAIT_PARAM
56
+ ret['config.PLUGIN_FILES'] = PLUGIN_FILES.inspect
57
+ ret['config.WRITEBEHIND_PATH'] = File.expand_path(WRITEBEHIND_PATH)
58
+ ret['config.WRITEBEHIND_SHIFT_SIZE'] = WRITEBEHIND_SHIFT_SIZE
59
+ ret
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,140 @@
1
+ #
2
+ # File: con_pool.rb
3
+ #
4
+ require 'singleton'
5
+ require 'eventmachine'
6
+ require 'roma/logging/rlogger'
7
+
8
+ module Roma
9
+ module Event
10
+ module EMConnection
11
+ attr_writer :fiber
12
+ attr_reader :connected
13
+ attr_accessor :ap
14
+
15
+ def post_init
16
+ @rbuf = ''
17
+ @connected = true
18
+ end
19
+
20
+ def receive_data(data)
21
+ @rbuf << data
22
+ @fiber.resume
23
+ rescue =>e
24
+ Roma::Logging::RLogger.instance.error("#{__FILE__}:#{__LINE__}:#{e.inspect} #{$@}")
25
+ end
26
+
27
+ def unbind
28
+ @connected = nil
29
+ @fiber.resume
30
+ rescue FiberError
31
+ rescue =>e
32
+ Roma::Logging::RLogger.instance.warn("#{__FILE__}:#{__LINE__}:#{e.inspect} #{$@}")
33
+ end
34
+
35
+ def send(data)
36
+ send_data(data)
37
+ end
38
+
39
+ def pop(size)
40
+ if @rbuf.size >= size
41
+ r = @rbuf[0..size-1]
42
+ @rbuf = @rbuf[size..-1]
43
+ r
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ def read_bytes(size)
50
+ while(@connected) do
51
+ d = pop(size)
52
+ if d
53
+ return d
54
+ else
55
+ remain = size - @rbuf.size
56
+ Fiber.yield(remain)
57
+ end
58
+ end
59
+ nil
60
+ end
61
+
62
+ def gets
63
+ while(@connected) do
64
+ if idx = @rbuf.index("\n")
65
+ return pop(idx+1)
66
+ else
67
+ Fiber.yield(@rbuf.size)
68
+ end
69
+ end
70
+ nil
71
+ end
72
+
73
+ end # module EMConnection
74
+
75
+ class EMConPool
76
+ include Singleton
77
+ attr :pool
78
+ attr_accessor :maxlength
79
+
80
+ def initialize
81
+ @pool = {}
82
+ @maxlength = 10
83
+ @lock = Mutex.new
84
+ end
85
+
86
+ def get_connection(ap)
87
+ ret = @pool[ap].shift if @pool.key?(ap) && @pool[ap].length > 0
88
+ ret = create_connection(ap) if ret == nil || ret.connected != true
89
+ ret
90
+ end
91
+
92
+ def return_connection(ap, con)
93
+ return if con.connected == false
94
+ if @pool.key?(ap) && @pool[ap].length > 0
95
+ if @pool[ap].length > @maxlength
96
+ con.close_connection
97
+ else
98
+ @pool[ap] << con
99
+ end
100
+ else
101
+ @pool[ap] = [con]
102
+ end
103
+ end
104
+
105
+ def create_connection(ap)
106
+ addr,port = ap.split(/[:_]/)
107
+ con = EventMachine::connect(addr, port, Roma::Event::EMConnection)
108
+ con.ap = ap
109
+ con
110
+ end
111
+
112
+ def close_all
113
+ @pool.each_key{|ap| close_at(ap) }
114
+ end
115
+
116
+ def close_same_host(ap)
117
+ host,port = ap.split(/[:_]/)
118
+ @pool.each_key{|eap|
119
+ close_at(eap) if eap.split(/[:_]/)[0] == host
120
+ }
121
+ end
122
+
123
+ def close_at(ap)
124
+ return unless @pool.key?(ap)
125
+ @lock.synchronize {
126
+ while(@pool[ap].length > 0)
127
+ begin
128
+ @pool[ap].shift.close_connection
129
+ rescue =>e
130
+ Roma::Logging::RLogger.instance.error("#{__FILE__}:#{__LINE__}:#{e.inspect}")
131
+ end
132
+ end
133
+ @pool.delete(ap)
134
+ }
135
+ end
136
+
137
+ end # class EMConPool
138
+
139
+ end # module Event
140
+ end # module Roma
@@ -0,0 +1,159 @@
1
+ #
2
+ # File: handler.rb
3
+ #
4
+ require 'eventmachine'
5
+ require 'roma/event/con_pool'
6
+ require 'roma/logging/rlogger'
7
+ require 'socket'
8
+
9
+ module Roma
10
+ module Event
11
+
12
+ class Handler < EventMachine::Connection
13
+ @@ev_list={}
14
+
15
+ attr :stop_event_loop
16
+ attr :connected
17
+ attr :fiber
18
+ attr :rbuf
19
+
20
+ attr :storages
21
+ attr :rttable
22
+ attr_accessor :timeout
23
+ attr_reader :lastcmd
24
+
25
+ def initialize(storages, rttable)
26
+ @rbuf=''
27
+ unless has_event?
28
+ public_methods.each{|m|
29
+ if m.to_s.start_with?('ev_')
30
+ add_event(m.to_s[3..-1],m)
31
+ end
32
+ }
33
+ end
34
+
35
+ @storages = storages
36
+ @rttable = rttable
37
+ @timeout = 10
38
+ @log = Roma::Logging::RLogger.instance
39
+ end
40
+
41
+ def post_init
42
+ @addr = Socket.unpack_sockaddr_in(get_peername)
43
+ @log.info("Connected from #{@addr[1]}:#{@addr[0]}")
44
+ @connected = true
45
+ @fiber = Fiber.new { dispatcher }
46
+ end
47
+
48
+ def receive_data(data)
49
+ @rbuf << data
50
+ @fiber.resume
51
+ rescue =>e
52
+ @log.error("#{__FILE__}:#{__LINE__}:#{@addr[1]}:#{@addr[0]} #{e.inspect} #{$@}")
53
+ end
54
+
55
+ def unbind
56
+ @connected=false
57
+ @fiber.resume
58
+ EventMachine::stop_event_loop if @stop_event_loop
59
+ @log.info("Disconnected from #{@addr[1]}:#{@addr[0]}")
60
+ rescue =>e
61
+ @log.warn("#{__FILE__}:#{__LINE__}:#{@addr[1]}:#{@addr[0]} #{e.inspect} #{$@}")
62
+ end
63
+
64
+ protected
65
+
66
+ def has_event?
67
+ @@ev_list.length!=0
68
+ end
69
+
70
+ def add_event(c,m)
71
+ @@ev_list[c]=m
72
+ end
73
+
74
+ def exit
75
+ EventMachine::stop_event_loop
76
+ end
77
+
78
+ private
79
+
80
+ def get_connection(ap)
81
+ con=Roma::Event::EMConPool::instance.get_connection(ap)
82
+ con.fiber=@fiber
83
+ con
84
+ end
85
+
86
+ def return_connection(ap,con)
87
+ Roma::Event::EMConPool.instance.return_connection(ap,con)
88
+ end
89
+
90
+ def dispatcher
91
+ while(@connected) do
92
+ next unless s=gets
93
+ s=s.chomp.split(/ /)
94
+ if s[0] && @@ev_list.key?(s[0].downcase)
95
+ send(@@ev_list[s[0].downcase],s)
96
+ @lastcmd=s
97
+ elsif s.length==0
98
+ next
99
+ elsif s[0]=='!!'
100
+ send(@@ev_list[@lastcmd[0].downcase],@lastcmd)
101
+ else
102
+ @log.warn("command error:#{s}")
103
+ send_data("ERROR\r\n")
104
+ close_connection_after_writing
105
+ end
106
+ end
107
+ rescue =>e
108
+ @log.warn("#{__FILE__}:#{__LINE__}:#{@addr[1]}:#{@addr[0]} #{e} #{$@}")
109
+ close_connection
110
+ end
111
+
112
+ def pop(size)
113
+ if @rbuf.size >= size
114
+ r = @rbuf[0..size-1]
115
+ @rbuf = @rbuf[size..-1]
116
+ r
117
+ else
118
+ nil
119
+ end
120
+ end
121
+
122
+ def read_bytes(size, mult = 1)
123
+ t=Time.now.to_i
124
+ while(@connected) do
125
+ d = pop(size)
126
+ if d
127
+ return d
128
+ else
129
+ remain = size - @rbuf.size
130
+ Fiber.yield(remain)
131
+ if Time.now.to_i - t > @timeout * mult
132
+ @log.warn("#{__FILE__}:#{__LINE__}:#{@addr[1]}:#{@addr[0]} read_bytes time out");
133
+ close_connection
134
+ return nil
135
+ end
136
+ end
137
+ end
138
+ nil
139
+ end
140
+
141
+ def gets
142
+ while(@connected) do
143
+ if idx=@rbuf.index("\n")
144
+ return pop(idx+1)
145
+ else
146
+ Fiber.yield(@rbuf.size)
147
+ end
148
+ end
149
+ nil
150
+ end
151
+
152
+ def detach_socket
153
+ @connected = false
154
+ Socket::for_fd(detach)
155
+ end
156
+ end
157
+
158
+ end
159
+ end