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,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