flare-tools 0.1.4 → 0.4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.gemtest +0 -0
  2. data/Flare-tools.txt +0 -0
  3. data/History.txt +114 -2
  4. data/LICENSE +21 -0
  5. data/Manifest.txt +65 -8
  6. data/README.txt +356 -0
  7. data/Rakefile +90 -25
  8. data/Tutorial.txt +370 -0
  9. data/bin/flare-admin +6 -0
  10. data/bin/flare-argv0 +6 -0
  11. data/bin/flare-deploy +6 -0
  12. data/bin/flare-keychecker +6 -0
  13. data/bin/flare-part +6 -0
  14. data/bin/flare-ping +6 -0
  15. data/bin/flare-stats +4 -10
  16. data/bin/flare-zkadmin +6 -0
  17. data/lib/flare/net/connection.rb +98 -0
  18. data/lib/flare/test/cluster.rb +140 -0
  19. data/lib/flare/test/daemon.rb +144 -0
  20. data/lib/flare/test/node.rb +62 -0
  21. data/lib/flare/tools.rb +18 -16
  22. data/lib/flare/tools/cli.rb +32 -0
  23. data/lib/flare/tools/cli/activate.rb +106 -0
  24. data/lib/flare/tools/cli/balance.rb +83 -0
  25. data/lib/flare/tools/cli/cli_util.rb +77 -0
  26. data/lib/flare/tools/cli/deploy.rb +170 -0
  27. data/lib/flare/tools/cli/down.rb +85 -0
  28. data/lib/flare/tools/cli/dump.rb +219 -0
  29. data/lib/flare/tools/cli/dumpkey.rb +117 -0
  30. data/lib/flare/tools/cli/flare_admin.rb +81 -0
  31. data/lib/flare/tools/cli/flare_argv0.rb +60 -0
  32. data/lib/flare/tools/cli/flare_keychecker.rb +106 -0
  33. data/lib/flare/tools/cli/flare_zkadmin.rb +226 -0
  34. data/lib/flare/tools/cli/index.rb +54 -0
  35. data/lib/flare/tools/cli/list.rb +93 -0
  36. data/lib/flare/tools/cli/master.rb +143 -0
  37. data/lib/flare/tools/cli/part.rb +100 -0
  38. data/lib/flare/tools/cli/ping.rb +81 -0
  39. data/lib/flare/tools/cli/reconstruct.rb +164 -0
  40. data/lib/flare/tools/cli/remove.rb +119 -0
  41. data/lib/flare/tools/cli/restore.rb +180 -0
  42. data/lib/flare/tools/cli/slave.rb +125 -0
  43. data/lib/flare/tools/cli/stats.rb +229 -122
  44. data/lib/flare/tools/cli/sub_command.rb +73 -0
  45. data/lib/flare/tools/cli/summary.rb +97 -0
  46. data/lib/flare/tools/cli/threads.rb +78 -0
  47. data/lib/flare/tools/cli/verify.rb +202 -0
  48. data/lib/flare/tools/client.rb +267 -0
  49. data/lib/flare/tools/cluster.rb +319 -0
  50. data/lib/flare/tools/common.rb +196 -0
  51. data/lib/flare/tools/index_server.rb +51 -0
  52. data/lib/flare/tools/node.rb +162 -0
  53. data/lib/flare/tools/stats.rb +75 -0
  54. data/lib/flare/tools/zk_util.rb +28 -0
  55. data/lib/flare/util.rb +34 -0
  56. data/lib/flare/util/bwlimit.rb +132 -0
  57. data/lib/flare/util/command_line.rb +79 -0
  58. data/lib/flare/util/conf.rb +71 -0
  59. data/lib/flare/util/constant.rb +25 -0
  60. data/lib/flare/util/conversion.rb +26 -0
  61. data/lib/flare/util/default_logger.rb +52 -0
  62. data/lib/flare/util/exception.rb +19 -0
  63. data/lib/flare/util/filesystem.rb +30 -0
  64. data/lib/flare/util/flared_conf.rb +33 -0
  65. data/lib/flare/util/flarei_conf.rb +32 -0
  66. data/lib/flare/util/hash_function.rb +32 -0
  67. data/lib/flare/util/interruption.rb +70 -0
  68. data/lib/flare/util/key_resolver.rb +67 -0
  69. data/lib/flare/util/log4r_logger.rb +79 -0
  70. data/lib/flare/util/logger.rb +40 -0
  71. data/lib/flare/util/logging.rb +84 -0
  72. data/lib/flare/util/result.rb +53 -0
  73. data/test/test/experimental/cache_test.rb +113 -0
  74. data/test/test/experimental/key_distribution_test.rb +38 -0
  75. data/test/test/experimental/keychecker_test.rb +60 -0
  76. data/test/test/experimental/list_test.rb +108 -0
  77. data/test/test/extra/replication_test.rb +184 -0
  78. data/test/test/integration/cli_test.rb +348 -0
  79. data/test/test/integration/dump_expired_test.rb +103 -0
  80. data/test/test/integration/dump_test.rb +128 -0
  81. data/test/test/integration/index_server_test.rb +35 -0
  82. data/test/test/integration/node_test.rb +78 -0
  83. data/test/test/integration/partition_test.rb +235 -0
  84. data/test/test/integration/proxy_test.rb +54 -0
  85. data/test/test/integration/stats_test.rb +79 -0
  86. data/test/test/system/flare_admin_test.rb +191 -0
  87. data/test/test/unit/bwlimit_test.rb +52 -0
  88. data/test/test/unit/cluster_test.rb +96 -0
  89. data/test/test/unit/daemon_test.rb +30 -0
  90. data/test/test/unit/logger_test.rb +46 -0
  91. data/test/test/unit/tools_test.rb +25 -0
  92. data/test/test/unit/util_test.rb +70 -0
  93. metadata +239 -84
  94. data/README.rdoc +0 -83
  95. data/bin/flare-partition-setting +0 -12
  96. data/lib/flare/tools/cli/partition_setting.rb +0 -86
  97. data/lib/flare/tools/core.rb +0 -189
  98. data/lib/flare/tools/logger.rb +0 -31
  99. data/test/test_flare-tools.rb +0 -11
  100. data/test/test_helper.rb +0 -3
@@ -0,0 +1,196 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'resolv'
7
+ require 'flare/tools/cluster'
8
+ require 'flare/tools/stats'
9
+ require 'flare/util/constant'
10
+ require 'flare/util/logging'
11
+
12
+ #
13
+ module Flare
14
+ module Tools
15
+ module Common
16
+ include Flare::Util::Logging
17
+
18
+ def fetch_cluster s
19
+ Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
20
+ end
21
+
22
+ def user_confirmed opt = { true => /^Y$/, false => /^N$/ }, &block
23
+ ret = nil
24
+ while ret.nil?
25
+ line = gets.chomp.upcase
26
+ opt.each do |key,pattern|
27
+ if patterns =~ line
28
+ ret = key
29
+ break
30
+ end
31
+ end
32
+ end
33
+ if block.nil?
34
+ ret
35
+ else
36
+ block.call(ret)
37
+ end
38
+ end
39
+
40
+ def nodekey_of *args
41
+ if args.size == 1
42
+ args = if args[0].kind_of?(Array)
43
+ args[0]
44
+ elsif args[0].kind_of?(String)
45
+ args[0].split(':')
46
+ end
47
+ end
48
+ if args.size >= 2
49
+ hostname, port = args
50
+ if hostname.kind_of?(String) && port.kind_of?(String)
51
+ if port.empty?
52
+ port = Flare::Util::Constant::DefaultNodePort
53
+ return "#{hostname}:#{port}"
54
+ elsif /^\d+$/ =~ port
55
+ return "#{hostname}:#{port}"
56
+ end
57
+ elsif hostname.kind_of?(String) && port.kind_of?(Integer)
58
+ return "#{hostname}:#{port}"
59
+ end
60
+ end
61
+ nil
62
+ end
63
+
64
+ def address_of_hostname(hostname)
65
+ Resolv.getaddress(hostname)
66
+ rescue Resolv::ResolvError
67
+ hostname
68
+ end
69
+
70
+ def hostname_of_address(ipaddr)
71
+ Resolv.getname(ipaddr)
72
+ rescue Resolv::ResolvError
73
+ ipaddr
74
+ end
75
+
76
+ NodeListHeader = [ ['%-32s', 'node'],
77
+ ['%9s', 'partition'],
78
+ ['%6s', 'role'],
79
+ ['%6s', 'state'],
80
+ ['%7s', 'balance'] ]
81
+ NodeListFormat = (NodeListHeader.map {|x| x[0]}.join(' '))
82
+
83
+ def string_of_nodelist(nodes, opt = {})
84
+ format = NodeListFormat+"\n"
85
+ ret = format % NodeListHeader.map{|x| x[1]}.flatten
86
+ nodes.each do |nodekey, node|
87
+ if opt.empty? || opt.include?(nodekey)
88
+ partition = if node['partition'] == "-1"
89
+ "-"
90
+ else
91
+ node['partition']
92
+ end
93
+ ret += format % [
94
+ nodekey,
95
+ partition,
96
+ node['role'],
97
+ node['state'],
98
+ node['balance'],
99
+ ]
100
+ end
101
+ end
102
+ ret
103
+ end
104
+
105
+ # s:IndexServer, nodekey:"hostname:port", timeout(second):Integer -> state:String
106
+ def wait_for_slave_construction(index_server, nodekey, timeout, silent = false)
107
+ cluster = Flare::Tools::Cluster.new(index_server.host, index_server.port, index_server.stats_nodes)
108
+ slave = cluster.node_stat(nodekey)
109
+ partition = slave['partition'].to_i
110
+ m_hostname, m_port = cluster.master_in_partition(partition).split(':')
111
+ s_hostname, s_port = nodekey.split(':')
112
+ m = Flare::Tools::Stats.open(m_hostname, m_port.to_i, timeout)
113
+ s = Flare::Tools::Stats.open(s_hostname, s_port.to_i, timeout)
114
+ start = Time.now
115
+ while true
116
+ cluster = Flare::Tools::Cluster.new(index_server.host, index_server.port, index_server.stats_nodes)
117
+ slave = cluster.node_stat(nodekey)
118
+ stats_master = m.stats
119
+ stats_slave = s.stats
120
+ ts_diff = Time.now-start
121
+ state_slave = slave['state'];
122
+ role_slave = slave['role'];
123
+ item_m = stats_master['curr_items'].to_i;
124
+ item_s = stats_slave['curr_items'].to_i;
125
+ eta = if ts_diff > 0 && item_s > 0
126
+ ((item_m - item_s) / (item_s / ts_diff)).to_i;
127
+ else
128
+ "n/a";
129
+ end
130
+ unless silent
131
+ STDERR.puts "%d/%d (role = %s, state = %s) [ETA: %s sec (elapsed = %d sec)]" % [item_s, item_m, role_slave, state_slave, eta, ts_diff]
132
+ end
133
+ break if role_slave == "slave" && state_slave == "active"
134
+ sleep 1
135
+ end
136
+ info "state is active -> stop waiting" unless silent
137
+ m.close
138
+ s.close
139
+ state_slave
140
+ end
141
+
142
+ # s:IndexServer, nodekey:"hostname:port", timeout(second):Integer -> state:String
143
+ def wait_for_master_construction(index_server, nodekey, timeout, silent = false)
144
+ cluster = Flare::Tools::Cluster.new(index_server.host, index_server.port, index_server.stats_nodes)
145
+ master = cluster.node_stat(nodekey)
146
+ partition = master['partition'].to_i
147
+ m_hostname, m_port = cluster.master_in_partition(partition).split(':')
148
+ m = Flare::Tools::Stats.open(m_hostname, m_port.to_i, timeout)
149
+ start = Time.now
150
+ while true
151
+ cluster = Flare::Tools::Cluster.new(index_server.host, index_server.port, index_server.stats_nodes)
152
+ master = cluster.node_stat(nodekey)
153
+ stats_master = m.stats
154
+ ts_diff = Time.now-start
155
+ state_master = master['state'];
156
+ role_master = master['role'];
157
+ item_m = stats_master['curr_items'].to_i;
158
+ eta = "n/a";
159
+ unless silent
160
+ STDERR.puts "%d (role = %s, state = %s) [ETA: %s sec (elapsed = %d sec)]" % [item_m, role_master, state_master, eta, ts_diff]
161
+ end
162
+ if role_master == "master" && state_master == "active"
163
+ if partition != 0
164
+ warn "The master should be ready after the reconstruction but it became active."
165
+ end
166
+ break
167
+ end
168
+ break if role_master == "master" && state_master == "ready"
169
+ sleep 1
170
+ end
171
+ info "state is ready -> stop waiting" unless silent
172
+ m.close
173
+ state_master
174
+ end
175
+
176
+ def wait_for_servers(index_server, timeout = Flare::Util::Constant::DefaultTimeout, silent = false)
177
+ index_server.stats_nodes.each do |nodekey, v|
178
+ hostname, port = nodekey.split(':')
179
+ is_alive = false
180
+ while is_alive
181
+ begin
182
+ Flare::Tools::Node.open(hostname, port.to_i, 2) do |n|
183
+ n.ping
184
+ is_alize = true
185
+ end
186
+ rescue Errno::ECONNREFUSED
187
+ rescue SocketError
188
+ end
189
+ sleep 1 unless is_alive
190
+ end
191
+ end
192
+ end
193
+
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,51 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/stats'
7
+
8
+ #
9
+ module Flare
10
+ module Tools
11
+
12
+ # == Description
13
+ #
14
+ class IndexServer < Stats
15
+
16
+ def set_role(host, port, role, balance, partition)
17
+ set_role_(host, port, role, balance, partition)
18
+ end
19
+ defcmd :set_role_, 'node role %s %d %s %d %d\r\n' do |resp|
20
+ resp
21
+ end
22
+
23
+ def set_state(host, port, state)
24
+ set_state_(host, port, state)
25
+ end
26
+ defcmd :set_state_, 'node state %s %s %s\r\n' do |resp|
27
+ resp
28
+ end
29
+
30
+ def node_remove(host, port)
31
+ node_remove_(host, port)
32
+ end
33
+ defcmd :node_remove_, 'node remove %s %s\r\n' do |resp|
34
+ resp
35
+ end
36
+
37
+ def meta()
38
+ meta_()
39
+ end
40
+ defcmd :meta_, 'meta\r\n' do |resp|
41
+ result = {}
42
+ resp.gsub(/META /, '').split("\r\n").each do |x|
43
+ key, val = x.split(" ", 2)
44
+ result[key] = val
45
+ end
46
+ result
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,162 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'flare/tools/stats'
7
+
8
+ #
9
+ module Flare
10
+ module Tools
11
+
12
+ # == Description
13
+ #
14
+ class Node < Stats
15
+
16
+ def set_state(host, port, state)
17
+ set_state_(host, port, state)
18
+ end
19
+ defcmd :set_state_, 'node state %s %s %s\r\n' do |resp| resp end
20
+
21
+ def flush_all
22
+ flush_all_
23
+ end
24
+ defcmd :flush_all_, 'flush_all\r\n' do |resp| resp end
25
+
26
+ def x_list_push(k, v, flag = 0, expire = 0)
27
+ x_list_push_(k.chomp, flag, expire, v.size, v)
28
+ end
29
+ defcmd :x_list_push_, 'list_push %s %d %d %d\r\n%s\r\n' do |resp| resp end
30
+
31
+ def x_list_unshift(k, v, flag = 0, expire = 0)
32
+ x_list_unshift_(k.chomp, flag, expire, v.size, v)
33
+ end
34
+ defcmd :x_list_unshift_, 'list_unshift %s %d %d %d\r\n%s\r\n' do |resp| resp end
35
+
36
+ def set(k, v, flag = 0, expire = 0)
37
+ set_(k.chomp, flag, expire, v.size, v)
38
+ end
39
+ defcmd :set_, 'set %s %d %d %d\r\n%s\r\n' do |resp| resp end
40
+
41
+ def set_noreply(k, v, flag = 0, expire = 0)
42
+ set_noreply_(k.chomp, flag, expire, v.size, v)
43
+ end
44
+ defcmd_noreply :set_noreply_, 'set %s %d %d %d noreply\r\n%s\r\n'
45
+
46
+ def cas(k, v, casunique, flag = 0, expire = 0)
47
+ r = cas_(k.chomp, flag, expire, v.size, casunique, v)
48
+ r = true if r == ""
49
+ r
50
+ end
51
+ defcmd :cas_, 'cas %s %d %d %d %d\r\n%s\r\n' do |resp| resp end
52
+
53
+ def delete(k)
54
+ delete_(k.chomp)
55
+ end
56
+ defcmd :delete_, 'delete %s\r\n' do |resp| resp end
57
+
58
+ def delete_noreply(k)
59
+ delete_noreply_(k.chomp)
60
+ end
61
+ defcmd_noreply :delete_noreply_, 'delete %s noreply\r\n'
62
+
63
+ def x_list_pop(k)
64
+ r = nil
65
+ x_list_pop_(k.chomp) do |data, key, flag, len, version, expire|
66
+ r = data
67
+ end
68
+ r
69
+ end
70
+ defcmd_value :x_list_pop_, 'list_pop %s\r\n'
71
+
72
+ def x_list_shift(k)
73
+ r = nil
74
+ x_list_shift_(k.chomp) do |data, key, flag, len, version, expire|
75
+ r = data
76
+ end
77
+ r
78
+ end
79
+ defcmd_value :x_list_shift_, 'list_shift %s\r\n'
80
+
81
+ def x_list_get(k, b, e, &block)
82
+ x_list_get_(k.chomp, b, e, &block)
83
+ end
84
+ defcmd_listelement :x_list_get_, 'list_get %s %d %d\r\n' do |data, key, rel, abs, flag, len, version, expire|
85
+ data
86
+ end
87
+
88
+ def get(*keys, &block)
89
+ return false if keys.size == 0
90
+ r = get_(keys.map{|x|x.chomp}.join(' '), &block)
91
+ if r && keys.size == 1
92
+ return false if r.size == 0
93
+ return r[0] if r.size == 1
94
+ end
95
+ r
96
+ end
97
+ defcmd_value :get_, 'get %s\r\n' do |data, key, flag, len, version, expire|
98
+ data
99
+ end
100
+
101
+ def gets(*keys, &block)
102
+ return false if keys.size == 0
103
+ r = gets_(keys.map{|x|x.chomp}.join(' '), &block)
104
+ if r && keys.size == 1
105
+ return false if r.size == 0
106
+ return r[0] if r.size == 1
107
+ end
108
+ r
109
+ end
110
+ defcmd_value :gets_, 'gets %s\r\n' do |data, key, flag, len, version, expire|
111
+ [data, version]
112
+ end
113
+
114
+ def dump(wait = 0, part = 0, partsize = 1, bwlimit = 0, &block)
115
+ dump_(wait, part, partsize, bwlimit.to_i, &block)
116
+ end
117
+ defcmd_value :dump_, 'dump %d %d %d %d\r\n' do |data, key, flag, len, version, expire|
118
+ false
119
+ end
120
+
121
+ def dumpkey(part = nil, partsize = nil, &block)
122
+ return dumpkey_0_(&block) if part.nil?
123
+ return dumpkey_1_(part, &block) if partsize.nil?
124
+ return dumpkey_2_(part, partsize, &block)
125
+ end
126
+ defcmd_key :dumpkey_0_, 'dump_key\r\n' do |key|
127
+ false
128
+ end
129
+ defcmd_key :dumpkey_1_, 'dump_key %d\r\n' do |key|
130
+ false
131
+ end
132
+ defcmd_key :dumpkey_2_, 'dump_key %d %d\r\n' do |key|
133
+ false
134
+ end
135
+
136
+ def incr_noreply(k, v)
137
+ incr_noreply_(k.chomp, v.to_s)
138
+ end
139
+ defcmd_noreply :incr_noreply_, 'incr %s %s noreply\r\n'
140
+
141
+ def incr(k, v)
142
+ incr_(k.chomp, v.to_s)
143
+ end
144
+ defcmd_oneline :incr_, 'incr %s %s\r\n' do |resp|
145
+ resp.chomp
146
+ end
147
+
148
+ def decr_noreply(k, v)
149
+ decr_noreply_(k.chomp, v.to_s)
150
+ end
151
+ defcmd_noreply :decr_noreply_, 'decr %s %s noreply\r\n'
152
+
153
+ def decr(k, v)
154
+ decr_(k.chomp, v.to_s)
155
+ end
156
+ defcmd_oneline :decr_, 'decr %s %s\r\n' do |resp|
157
+ resp.chomp
158
+ end
159
+
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,75 @@
1
+ # -*- coding: utf-8; -*-
2
+ # Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
3
+ # Copyright:: Copyright (C) GREE, Inc. 2011.
4
+ # License:: MIT-style
5
+
6
+ require 'timeout'
7
+ require 'flare/tools/client'
8
+
9
+ #
10
+ module Flare
11
+ module Tools
12
+
13
+ # == Description
14
+ #
15
+ class Stats < Client
16
+
17
+ defcmd :stats_nodes, 'stats nodes\r\n' do |resp|
18
+ result = {}
19
+ resp.gsub(/STAT /, '').split("\r\n").each do |x|
20
+ ip, port, stat = x.split(":", 3)
21
+ key, val = stat.split(" ")
22
+ result["#{ip}:#{port}"] = {} if result["#{ip}:#{port}"].nil?
23
+ result["#{ip}:#{port}"]['port'] = port
24
+ result["#{ip}:#{port}"][key] = val
25
+ end
26
+ result
27
+ end
28
+
29
+ defcmd :stats, 'stats\r\n' do |resp|
30
+ result = {}
31
+ resp.gsub(/STAT /, '').split("\r\n").each do |x|
32
+ key, val = x.split(" ", 2)
33
+ result[key] = val
34
+ end
35
+ result
36
+ end
37
+
38
+ def stats_threads_by_peer
39
+ result = {}
40
+ stats_threads.each do |thread_id, stat|
41
+ k = stat['peer']
42
+ result[k] = {} if result[k].nil?
43
+ result[k]['thread_id'] = thread_id
44
+ result[k].merge!(stat)
45
+ end
46
+ result
47
+ end
48
+
49
+ def stats_threads
50
+ return {} unless required_version?([1, 0, 10])
51
+ stats_threads_
52
+ end
53
+
54
+ defcmd :stats_threads_, 'stats threads\r\n' do |resp|
55
+ threads = {}
56
+ resp.gsub(/STAT /, '').split("\r\n").each do |x|
57
+ thread_id, stat = x.split(":", 2)
58
+ key, val = stat.split(" ")
59
+ threads[thread_id] = {} unless threads.has_key?(thread_id)
60
+ threads[thread_id][key] = val
61
+ end
62
+ threads
63
+ end
64
+
65
+ defcmd :ping, 'ping\r\n' do |resp|
66
+ true if resp
67
+ end
68
+
69
+ defcmd :quit, 'quit\r\n' do |resp|
70
+ true
71
+ end
72
+
73
+ end
74
+ end
75
+ end