roma 1.1.0 → 1.2.0

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +21 -0
  3. data/Gemfile.lock +47 -0
  4. data/bin/check_tc_flag +39 -0
  5. data/bin/roma-adm +43 -0
  6. data/bin/ssroute +0 -3
  7. data/lib/roma/async_process.rb +203 -208
  8. data/lib/roma/command/sys_command_receiver.rb +52 -10
  9. data/lib/roma/config.rb +3 -0
  10. data/lib/roma/event/handler.rb +11 -4
  11. data/lib/roma/event/jaro_winkler.rb +23 -0
  12. data/lib/roma/event/levenshtein.rb +23 -0
  13. data/lib/roma/plugin/plugin_cmd_aliases.rb +1 -32
  14. data/lib/roma/romad.rb +23 -0
  15. data/lib/roma/routing/cb_rttable.rb +2 -0
  16. data/lib/roma/routing/random_partitioner.rb +43 -36
  17. data/lib/roma/routing/rttable.rb +5 -3
  18. data/lib/roma/stats.rb +4 -1
  19. data/lib/roma/tools/check_tc_flag.rb +25 -0
  20. data/lib/roma/tools/cpdb.rb +3 -2
  21. data/lib/roma/tools/mkconfig.rb +22 -13
  22. data/lib/roma/tools/roma-adm.rb +82 -0
  23. data/lib/roma/version.rb +1 -1
  24. data/test/config4mhash.rb +2 -0
  25. data/test/config4storage_error.rb +2 -0
  26. data/test/config4test.rb +2 -0
  27. data/test/cpdbtest/config4cpdb_base.rb +67 -0
  28. data/test/cpdbtest/config4cpdb_dbm.rb +9 -0
  29. data/test/cpdbtest/config4cpdb_groonga.rb +9 -0
  30. data/test/cpdbtest/config4cpdb_rh.rb +9 -0
  31. data/test/cpdbtest/config4cpdb_sqlite3.rb +9 -0
  32. data/test/cpdbtest/config4cpdb_tc.rb +9 -0
  33. data/test/cpdbtest/config4cpdb_tcmem.rb +9 -0
  34. data/test/roma-test-utils.rb +140 -40
  35. data/test/t_cpdata.rb +76 -80
  36. data/test/t_cpdb.rb +95 -0
  37. data/test/t_logshift.rb +86 -0
  38. data/test/t_mhash.rb +56 -54
  39. data/test/t_routing_logic.rb +121 -0
  40. data/test/t_writebehind.rb +202 -207
  41. metadata +25 -8
  42. data/bin/tc_data_restore.rb +0 -123
@@ -39,19 +39,58 @@ module Roma
39
39
  @stop_event_loop = true
40
40
  end
41
41
 
42
- # shutdown_instance [node-id]
43
- def ev_shutdown_instance(s)
44
- if s.length != 2
45
- send_data("usage:shutdown_instance [node-id]\r\n")
42
+ # shutdown [reason]
43
+ def ev_shutdown(s)
44
+ send_data("*** ARE YOU REALLY SURE TO SHUTDOWN? *** (yes/no)\r\n")
45
+ if gets != "yes\r\n"
46
+ close_connection_after_writing
47
+ return
48
+ end
49
+
50
+ if s.length == 2
51
+ @log.info("Receive a shutdown #{s[1]}")
52
+ else
53
+ @log.info("Receive a shutdown command.")
54
+ end
55
+ @rttable.enabled_failover = false
56
+ res = broadcast_cmd("rshutdown\r\n")
57
+ res[@stats.ap_str] = "BYE"
58
+ send_data("#{res.inspect}\r\n")
59
+ close_connection_after_writing
60
+ @stop_event_loop = true
61
+ end
62
+
63
+ # rshutdown [reason]
64
+ def ev_rshutdown(s)
65
+ if s.length == 2
66
+ @log.info("Receive a rshutdown #{s[1]}")
46
67
  else
47
- if s[1] == @stats.ap_str
48
- @rttable.enabled_failover = false
49
- send_data("BYE\r\n")
50
- @stop_event_loop = true
68
+ @log.info("Receive a rshutdown command.")
69
+ end
70
+ @rttable.enabled_failover = false
71
+ send_data("BYE\r\n")
72
+ close_connection_after_writing
73
+ @stop_event_loop = true
74
+ end
75
+
76
+ # shutdown_self
77
+ def ev_shutdown_self(s)
78
+ if s.length != 1
79
+ send_data("ERROR: shutdown_instance has irregular argument.\r\n")
80
+ else
81
+ send_data("\r\n=================================================================\r\n")
82
+ send_data("CAUTION!!: \r\n\tThis command kill the instance!\r\n\tThere is some possibility of occuring redundancy down!\r\n")
83
+ send_data("=================================================================\r\n")
84
+ send_data("\r\nAre you sure to shutdown this instance?(yes/no)\r\n")
85
+ if gets != "yes\r\n"
51
86
  close_connection_after_writing
52
- else
53
- send_data("invalid [node-id]\r\n")
87
+ return
54
88
  end
89
+ @log.info("Receive a shutdown_self command.")
90
+ @rttable.enabled_failover = false
91
+ send_data("BYE\r\n")
92
+ @stop_event_loop = true
93
+ close_connection_after_writing
55
94
  end
56
95
  end
57
96
 
@@ -243,6 +282,9 @@ module Roma
243
282
  else
244
283
  return send_data("CLIENT_ERROR no match log-level string\r\n")
245
284
  end
285
+
286
+ @stats.log_level = s[1].downcase
287
+
246
288
  send_data("STORED\r\n")
247
289
  end
248
290
 
@@ -3,6 +3,9 @@ require 'roma/storage/rh_storage'
3
3
  module Roma
4
4
 
5
5
  module Config
6
+ # check when the booting
7
+ VERSION = "1.2.0"
8
+
6
9
  DEFAULT_PORT = 12000
7
10
  DEFAULT_NAME = 'ROMA'
8
11
 
@@ -3,6 +3,8 @@
3
3
  #
4
4
  require 'eventmachine'
5
5
  require 'roma/event/con_pool'
6
+ require 'roma/event/jaro_winkler'
7
+ #require 'roma/event/levenshtein'
6
8
  require 'roma/logging/rlogger'
7
9
  require 'roma/stats'
8
10
  require 'roma/storage/basic_storage'
@@ -167,10 +169,15 @@ module Roma
167
169
  send(@@ev_list[@lastcmd[0].downcase],@lastcmd)
168
170
  next if @@system_commands.key?(@lastcmd[0].downcase)
169
171
  else
170
- @log.warn("command error:#{s}")
171
- send_data("ERROR\r\n")
172
- close_connection_after_writing
173
- next
172
+ distance, similar_cmd = Roma::Event::Distance.check_distance(s[0], @@ev_list)
173
+ if distance < 0.2
174
+ send_data("\r\nERROR: '#{s[0]}' is not roma command.\r\nDid you mean this?\r\n\t#{similar_cmd}\r\n")
175
+ next
176
+ else
177
+ @log.warn("command error:#{s}")
178
+ send_data("ERROR: '#{s[0]}' is not roma command. Please check command.\r\n(closing telnet connection command is 'quit')\r\n")
179
+ next
180
+ end
174
181
  end
175
182
 
176
183
  # hilatency check
@@ -0,0 +1,23 @@
1
+ #
2
+ # File: jaro_winkler.rb
3
+ #
4
+ require "jaro_winkler"
5
+
6
+ module Roma
7
+ module Event
8
+ module Distance
9
+ def self.check_distance(cmd, ev_list)
10
+ jaro_winkler_distance = 0.0000 # initialize
11
+ similar_cmd = ''
12
+ ev_list.each_key{|ev|
13
+ distance = JaroWinkler.distance(cmd, ev)
14
+ if distance > jaro_winkler_distance
15
+ jaro_winkler_distance = distance
16
+ similar_cmd = ev
17
+ end
18
+ }
19
+ return (1-jaro_winkler_distance), similar_cmd
20
+ end
21
+ end # module Distance
22
+ end # module Event
23
+ end # module Roma
@@ -0,0 +1,23 @@
1
+ #
2
+ # File: levenshtein.rb
3
+ #
4
+ require "levenshtein"
5
+
6
+ module Roma
7
+ module Event
8
+ module Distance
9
+ def self.check_distance(cmd, ev_list)
10
+ levenshtein_distance = 1.0 # initialize
11
+ similar_cmd = ''
12
+ ev_list.each_key{|ev|
13
+ distance = Levenshtein::normalized_distance(cmd, ev)
14
+ if distance < levenshtein_distance
15
+ levenshtein_distance = distance
16
+ similar_cmd = ev
17
+ end
18
+ }
19
+ return levenshtein_distance, similar_cmd
20
+ end
21
+ end # module Distance
22
+ end # module Event
23
+ end # module Roma
@@ -5,38 +5,7 @@ module Roma
5
5
  module PluginCommandAliases
6
6
  include ::Roma::CommandPlugin
7
7
 
8
- # shutdown [reason]
9
- def ev_shutdown(s)
10
- send_data("*** ARE YOU REALLY SURE TO SHUTDOWN? *** (yes/no)\r\n")
11
- if gets != "yes\r\n"
12
- close_connection_after_writing
13
- return
14
- end
15
-
16
- if s.length == 2
17
- @log.info("Receive a shutdown #{s[1]}")
18
- else
19
- @log.info("Receive a shutdown command.")
20
- end
21
- @rttable.enabled_failover = false
22
- res = broadcast_cmd("rshutdown\r\n")
23
- send_data("#{res.inspect}\r\n")
24
- close_connection_after_writing
25
- @stop_event_loop = true
26
- end
27
-
28
- # rshutdown [reason]
29
- def ev_rshutdown(s)
30
- if s.length == 2
31
- @log.info("Receive a rshutdown #{s[1]}")
32
- else
33
- @log.info("Receive a rshutdown command.")
34
- end
35
- @rttable.enabled_failover = false
36
- send_data("BYE\r\n")
37
- close_connection_after_writing
38
- @stop_event_loop = true
39
- end
8
+ # Please add your self if you want.
40
9
 
41
10
  end
42
11
  end
@@ -41,6 +41,26 @@ module Roma
41
41
  end
42
42
 
43
43
  def start
44
+ # config version check
45
+ if !Config.const_defined?(:VERSION)
46
+ @log.error("ROMA FAIL TO BOOT! : config.rb's version is too old.")
47
+ exit
48
+ elsif Config::VERSION != Roma::VERSION
49
+ if /(\d+)\.(\d+)\.(\d+)/ =~ Config::VERSION
50
+ version_config = ($1.to_i << 16) + ($2.to_i << 8) + $3.to_i
51
+ end
52
+ if /(\d+)\.(\d+)\.(\d+)/ =~ Roma::VERSION
53
+ version_roma = ($1.to_i << 16) + ($2.to_i << 8) + $3.to_i
54
+ end
55
+
56
+ if version_config == version_roma
57
+ @log.info("This version is development version.")
58
+ else
59
+ @log.error("ROMA FAIL TO BOOT! : config.rb's version is differ from current ROMA version.")
60
+ exit
61
+ end
62
+ end
63
+
44
64
  if node_check(@stats.ap_str)
45
65
  @log.error("#{@stats.ap_str} is already running.")
46
66
  return
@@ -171,6 +191,9 @@ module Roma
171
191
  if Config.const_defined?(:LOG_SHIFT_AGE)
172
192
  @stats.log_shift_age = Config::LOG_SHIFT_AGE
173
193
  end
194
+ if Config.const_defined?(:LOG_LEVEL)
195
+ @stats.log_level = Config::LOG_LEVEL
196
+ end
174
197
  end
175
198
 
176
199
  def initialize_connection
@@ -22,6 +22,7 @@ module Roma
22
22
  attr_accessor :event
23
23
  attr_accessor :event_limit_line
24
24
  attr_accessor :logs
25
+ attr_accessor :enabled_failover
25
26
  attr_reader :version_of_nodes
26
27
  attr_reader :min_version
27
28
 
@@ -57,6 +58,7 @@ module Roma
57
58
  ret['routing.event_limit_line'] = @event_limit_line
58
59
  ret['routing.version_of_nodes'] = @version_of_nodes.inspect
59
60
  ret['routing.min_version'] = @min_version
61
+ ret['routing.enabled_failover'] = @enabled_failover
60
62
  ret
61
63
  end
62
64
 
@@ -1,25 +1,23 @@
1
1
  module Roma
2
2
  module Routing
3
3
  module RandomPartitioner
4
-
5
4
  def exclude_nodes(ap_str, rep_host)
6
- exclude_nodes = self.nodes
5
+ exclude_nodes = nodes
7
6
  if rep_host
8
7
  exclude_nodes = [ap_str]
9
8
  else
10
9
  myhost = ap_str.split(/[:_]/)[0]
11
- exclude_nodes.delete_if{|nid| nid.split(/[:_]/)[0] != myhost }
10
+ exclude_nodes.delete_if { |nid| nid.split(/[:_]/)[0] != myhost }
12
11
  end
13
12
  exclude_nodes
14
13
  end
15
-
16
- def exclude_nodes_for_join(ap_str, rep_host)
14
+
15
+ def exclude_nodes_for_join(ap_str, _rep_host)
17
16
  [ap_str]
18
17
  end
19
18
 
20
- #alias :exclude_nodes_for_join :exclude_nodes
21
- alias :exclude_nodes_for_recover :exclude_nodes
22
- alias :exclude_nodes_for_balance :exclude_nodes
19
+ alias_method :exclude_nodes_for_recover, :exclude_nodes
20
+ alias_method :exclude_nodes_for_balance, :exclude_nodes
23
21
 
24
22
  def myhost_include?(nodes, myhost)
25
23
  nodes.each do |nid|
@@ -30,44 +28,54 @@ module Roma
30
28
  private :myhost_include?
31
29
 
32
30
  # vnode sampling exclude +exclude_nodes+
33
- def select_vn_for_join(exclude_nodes)
31
+ def select_vn_for_join(exclude_nodes, rep_host)
34
32
  short_idx = {}
35
33
  myhost_idx = {}
36
34
  idx = {}
37
35
  myhost = exclude_nodes[0].split(/[:_]/)[0]
36
+
38
37
  @rd.v_idx.each_pair do |vn, nids|
39
38
  unless list_include?(nids, exclude_nodes)
40
39
  if myhost_include?(nids, myhost)
41
40
  myhost_idx[vn] = nids
42
41
  else
43
- idx[vn] = nids # other nodes
42
+ idx[vn] = nids # other hosts
44
43
  end
45
44
  short_idx[vn] = nids if nids.length < @rd.rn
46
45
  end
47
46
  end
48
- idx = short_idx if short_idx.length > 0
49
-
50
- ks = idx.keys
51
- if ks.length == 0
47
+
48
+ # vnodes sampling priority:
49
+ # 1. Short vnodes
50
+ # 2. Other hosts vnodes
51
+ # 3. My host vnodes
52
+ if short_idx.length > 0
53
+ idx = short_idx
54
+ elsif idx.length == 0
52
55
  idx = myhost_idx
53
- ks = idx.keys
54
- return nil if ks.length == 0
55
- vn = ks[rand(ks.length)]
56
- nids = idx[vn]
57
- [vn, nids, nids[0].split(/[:_]/)[0] == myhost]
56
+ end
57
+
58
+ return nil if idx.length == 0
59
+
60
+ ks = idx.keys
61
+ vn = ks[rand(ks.length)]
62
+ nids = idx[vn]
63
+
64
+ if !rep_host && nids[0].split(/[:_]/)[0] == myhost
65
+ is_primary = true
58
66
  else
59
- vn = ks[rand(ks.length)]
60
- nids = idx[vn]
61
- [vn, nids, rand(@rd.rn) == 0]
67
+ is_primary = rand(@rd.rn) == 0
62
68
  end
69
+
70
+ [vn, nids, is_primary]
63
71
  end
64
72
 
65
73
  # select a vnodes where short of redundancy.
66
- def select_vn_for_recover(exclude_nodes)
74
+ def select_vn_for_recover(exclude_nodes, _rep_host)
67
75
  ret = []
68
76
  @rd.v_idx.each_pair do |vn, nids|
69
- if nids.length < @rd.rn && list_include?(nids,exclude_nodes) == false
70
- ret << [vn,nids]
77
+ if nids.length < @rd.rn && list_include?(nids, exclude_nodes) == false
78
+ ret << [vn, nids]
71
79
  end
72
80
  end
73
81
  if ret.length == 0
@@ -79,27 +87,27 @@ module Roma
79
87
  end
80
88
 
81
89
  def select_node_for_release(ap_str, rep_host, nids)
82
- buf = self.nodes
90
+ buf = nodes
83
91
 
84
92
  unless rep_host
85
93
  deny_hosts = []
86
- nids.each{ |nid|
94
+ nids.each do |nid|
87
95
  host = nid.split(/[:_]/)[0]
88
96
  deny_hosts << host if host != ap_str.split(/[:_]/)[0]
89
- }
90
- buf.delete_if{|nid| deny_hosts.include?(nid.split(/[:_]/)[0])}
97
+ end
98
+ buf.delete_if { |nid| deny_hosts.include?(nid.split(/[:_]/)[0]) }
91
99
  else
92
- nids.each{|nid| buf.delete(nid) }
100
+ nids.each { |nid| buf.delete(nid) }
93
101
  end
94
-
95
- buf.delete_if{|instance| instance == ap_str}
102
+
103
+ buf.delete_if { |instance| instance == ap_str }
96
104
  to_nid = buf.sample
97
- new_nids = nids.map{|n| n == ap_str ? to_nid : n }
105
+ new_nids = nids.map { |n| n == ap_str ? to_nid : n }
98
106
  [to_nid, new_nids]
99
107
  end
100
108
 
101
109
  # vnode sampling exclude +exclude_nodes+
102
- def select_vn_for_balance(exclude_nodes)
110
+ def select_vn_for_balance(exclude_nodes, _rep_host)
103
111
  short_idx = {}
104
112
  idx = {}
105
113
  @rd.v_idx.each_pair do |vn, nids|
@@ -109,14 +117,13 @@ module Roma
109
117
  end
110
118
  end
111
119
  idx = short_idx if short_idx.length > 0
112
-
120
+
113
121
  ks = idx.keys
114
122
  return nil if ks.length == 0
115
123
  vn = ks[rand(ks.length)]
116
124
  nids = idx[vn]
117
125
  [vn, nids, rand(@rd.rn) == 0]
118
126
  end
119
-
120
127
  end
121
128
  end
122
129
  end
@@ -36,7 +36,8 @@ module Roma
36
36
  end
37
37
 
38
38
  def num_of_vn(ap)
39
- pn = sn = short = lost = 0
39
+ pn = short = lost = 0
40
+ sn = Array.new(@rd.rn - 1, 0)
40
41
  @rd.v_idx.each_pair do |vn, nids|
41
42
  if nids == nil || nids.length == 0
42
43
  lost += 1
@@ -44,7 +45,8 @@ module Roma
44
45
  elsif nids[0] == ap
45
46
  pn += 1
46
47
  elsif nids.include?(ap)
47
- sn += 1
48
+ i = nids.index(ap) - 1
49
+ sn[i] += 1
48
50
  end
49
51
  short += 1 if nids.length < @rd.rn
50
52
  end
@@ -61,7 +63,7 @@ module Roma
61
63
  ret['routing.div_bits'] = @div_bits
62
64
  ret['routing.vnodes.length'] = vnodes.length
63
65
  ret['routing.primary'] = pn
64
- ret['routing.secondary'] = sn
66
+ (@rn-1).times{|i| ret["routing.secondary#{i+1}"] = sn[i]}
65
67
  ret['routing.short_vnodes'] = short
66
68
  ret['routing.lost_vnodes'] = lost
67
69
  ret['routing.fail_cnt_threshold'] = @fail_cnt_threshold
@@ -77,9 +77,10 @@ module Roma
77
77
  attr_accessor :gui_run_gather_logs
78
78
  attr_accessor :gui_last_snapshot
79
79
 
80
- # for log rotate
80
+ # for log
81
81
  attr_accessor :log_shift_size
82
82
  attr_accessor :log_shift_age
83
+ attr_accessor :log_level
83
84
 
84
85
  def initialize
85
86
  @config_path = nil
@@ -121,6 +122,7 @@ module Roma
121
122
  @routing_trans_timeout = 3600 * 3 # 3hr
122
123
  @log_shift_size = 1048576
123
124
  @log_shift_age = 0
125
+ @log_level = :debug
124
126
  end
125
127
 
126
128
  def ap_str
@@ -171,6 +173,7 @@ module Roma
171
173
  ret['stats.routing_trans_timeout'] = @routing_trans_timeout
172
174
  ret['stats.log_shift_size'] = @log_shift_size
173
175
  ret['stats.log_shift_age'] = @log_shift_age
176
+ ret['stats.log_level'] = @log_level
174
177
  ret
175
178
  end
176
179