roma 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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