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,60 @@
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
+ cliname = File.basename($PROGRAM_NAME)
7
+ cliname[/flare-/] = ""
8
+
9
+ require 'resolv'
10
+ require 'flare/tools'
11
+ require 'flare/tools/cli/cli_util'
12
+ require 'flare/util/logging'
13
+ begin
14
+ require "flare/tools/cli/#{cliname}"
15
+ rescue LoadError
16
+ exit 1
17
+ end
18
+ require 'flare/util/command_line.rb'
19
+ require 'flare/util/conversion.rb'
20
+
21
+ include Flare::Util::Logging
22
+ include Flare::Util::Constant
23
+ include Flare::Tools::Cli::CliUtil
24
+
25
+ index_server_hostname = nil
26
+ index_server_port = nil
27
+ timeout = DefaultTimeout
28
+ dry_run = false
29
+ cluster = nil
30
+
31
+ if ENV.has_key? "FLARE_INDEX_SERVER"
32
+ h, p = ENV["FLARE_INDEX_SERVER"].split(':')
33
+ index_server_hostname = h unless h.nil?
34
+ index_server_port = p unless p.nil?
35
+ end
36
+
37
+ subc = eval "Flare::Tools::Cli::#{cliname.capitalize}.new"
38
+
39
+ setup do |opt|
40
+ opt.banner = "#{Flare::Tools::TITLE}\nUsage: flare-#{cliname} [options]"
41
+ opt.on('-n', '--dry-run', "dry run") {dry_run = true}
42
+ opt.on('-i HOSTNAME', '--index-server=HOSTNAME', "index server hostname(default:#{DefaultIndexServerName})") {|v| index_server_hostname = v}
43
+ opt.on('-p PORT', '--index-server-port=PORT', "index server port(default:#{DefaultIndexServerPort})") {|v| index_server_port = v.to_i}
44
+ opt.on( '--log-file=LOGFILE', "output log to LOGFILE") {|v| Flare::Util::Logging.set_logger(v)}
45
+ opt.on( '--cluster=NAME', "specify a cluster name") {|v| cluster = v}
46
+
47
+ subc.setup(opt)
48
+ end
49
+
50
+ execute do |args|
51
+ ihostname, iport = get_index_server_from_nodekeys(args) ||
52
+ get_index_server_name_and_port(index_server_hostname, index_server_port)
53
+ ihostname, iport = get_index_server_from_cluster(cluster) unless cluster.nil?
54
+ subc.execute({ :command => File.basename($PROGRAM_NAME),
55
+ :index_server_hostname => ihostname,
56
+ :index_server_port => iport,
57
+ :dry_run => dry_run,
58
+ :timeout => timeout },
59
+ *args)
60
+ end
@@ -0,0 +1,106 @@
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 'optparse'
7
+ require "zlib"
8
+
9
+ # Hash
10
+ hashfunc = {
11
+ "simple" => lambda {|k| r = 0; k.each_byte {|c| r += c }; r },
12
+ "bitshift" => lambda {|k| r = 19790217; k.each_byte {|c| r = (r << 5) + (r << 2) + r + c }; r },
13
+ "crc32" => lambda {|k| Zlib.crc32(k, 0) },
14
+ }
15
+
16
+ # Variables
17
+ delimiter = "::"
18
+ use_prefix = false
19
+ use_bucket = false
20
+ prefixes = {}
21
+ virtual = 4096
22
+ size = 0
23
+ buckets = {}
24
+ bucket_file = nil
25
+ partition_size = 100
26
+ hint = 1
27
+ hash = hashfunc["simple"]
28
+ output_file = nil
29
+ input_file = nil
30
+ default_bucket_file = "bucket.csv"
31
+
32
+ # Options
33
+ opt = OptionParser.new
34
+ opt.on('-d', '--delimiter=STRING', "delimiter (defalut #{delimiter})") {|v| delimiter = v; use_prefix = true }
35
+ opt.on('-b', '--bucket-file=CSVFILE', "bucket file (default #{default_bucket_file})") {|v| bucket_file = v; }
36
+ opt.on('-i', '--input=CSVFILE', "input file") {|v| input_file = v; }
37
+ opt.on('-o', '--output=CSVFILE', "output file") {|v| output_file = v; }
38
+ opt.on('-s', '--partition-size=SIZE', "max partition size (default #{partition_size})") {|v| partition_size = v.to_i }
39
+ opt.on('-h', '--hash=TYPE', "hash function (simple,bitshift,crc32)") {|v|
40
+ default_bucket_file = "bucket.#{v}.csv"
41
+ hash = if hashfunc.has_key? v then hashfunc[v] else abort "invalid hash function." end
42
+ }
43
+ opt.on('-n', '--hint=SIZE', "hint (default #{hint})") {|v| hint = v; }
44
+ opt.parse!(ARGV)
45
+
46
+ # Bucket
47
+ if bucket_file.nil? || (!input_file.nil? && File.exist?(input_file))
48
+ bucket_file = default_bucket_file
49
+ input = if input_file.nil? then STDIN else open(input_file) end
50
+ while line = input.gets
51
+ key = line.chomp
52
+ parts = split(delimiter)
53
+ suffix = parts.pop
54
+ prefix = parts.join(delimiter)
55
+ unless prefixes.has_key? prefix
56
+ prefixes[prefix] = 0
57
+ buckets[prefix] = Array.new(virtual, 0)
58
+ end
59
+ prefixes[prefix] += 1
60
+ key_hash_value = [hash.call(key)].pack("l").unpack("L")[0]
61
+ key_hash_value = -key_hash_value if key_hash_value < 0
62
+ buckets[prefix][key_hash_value%virtual] += 1
63
+ size += 1
64
+ end
65
+ if File.exist? bucket_file
66
+ print "#{bucket_file} exists. overwrite? (y/n): "
67
+ exit unless gets.chomp.upcase == "Y"
68
+ end
69
+ open(bucket_file, 'w') do |f|
70
+ f.puts "# key, total, ..."
71
+ prefixes.each do |k,total|
72
+ f.puts k+", "+total.to_s+", "+buckets[k].join(" ,")
73
+ end
74
+ end
75
+ else
76
+ open(bucket_file) do |f|
77
+ while line = f.gets
78
+ prefix, total, data = line.split(',', 3)
79
+ prefixes[prefix] = total.to_i
80
+ buckets[prefix] = data.split(',').map {|x| x.to_i}
81
+ end
82
+ end
83
+ end
84
+
85
+ # Assign
86
+ map = Array.new(partition_size+1).map!{Array.new(virtual, 0)}
87
+ (1..partition_size).each do |i|
88
+ counter = Array.new(partition_size, 0)
89
+ (0..hint).each {|j| map[i][j] = j % i }
90
+ ((hint+1)...virtual).each do |j|
91
+ k = map[i-1][j]
92
+ counter[k] += 1
93
+ map[i][j] = if (counter[k] % i) == (i - 1) then i - 1 else map[i-1][j] end
94
+ end
95
+ end
96
+
97
+ # Result
98
+ output = if output_file.nil? || !File.exist?(output_file) then STDOUT else open(output_file, "w") end
99
+ output.puts "partition size, prefix, "+(0...partition_size).map{|x| "#{x}"}.join(' ,')
100
+ for i in 1..partition_size
101
+ prefixes.each do |prefix, total|
102
+ nitem = Array.new(i, 0)
103
+ (0...virtual).each {|j| nitem[map[i][j]] += buckets[prefix][j] }
104
+ output.puts "#{i}, #{prefix},"+nitem.join(' ,')
105
+ end
106
+ end
@@ -0,0 +1,226 @@
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 'rubygems'
7
+ require 'optparse'
8
+ require 'uri'
9
+ require 'zookeeper'
10
+ require 'flare/tools/cluster'
11
+
12
+ uri = "zookeeper://localhost:2181/ckvs/clusters/mycluster"
13
+ path = nil
14
+ indexdb_elements = []
15
+
16
+ ZOK = Zookeeper::ZOK
17
+
18
+ def init z, path
19
+ puts "initializing #{path}"
20
+ path_cluster = ""
21
+ path.split('/').each do |e|
22
+ unless e.empty?
23
+ path_cluster += "/#{e}"
24
+ z.create(:path => path_cluster)
25
+ end
26
+ end
27
+
28
+ path_index = "#{path_cluster}/index"
29
+ r = z.create(:path => "#{path_index}")
30
+ raise "already initialized." unless r[:rc] == ZOK
31
+
32
+ z.create(:path => "#{path_index}/lock")
33
+ z.create(:path => "#{path_index}/primary")
34
+ z.create(:path => "#{path_index}/servers")
35
+ z.create(:path => "#{path_index}/nodemap")
36
+
37
+ path_meta = "#{path_index}/meta"
38
+ z.create(:path => path_meta)
39
+ entries = [['partition-size', '1024'],
40
+ ['key-hash-algorithm', 'crc32'],
41
+ ['partition-type', 'modular'],
42
+ ['partition-modular-hint', '1'],
43
+ ['partition-modular-virtual', '65536']]
44
+ entries.each do |k,v|
45
+ r = z.create(:path => "#{path_meta}/#{k}", :data => v)
46
+ end
47
+
48
+ clear_nodemap z, path
49
+ end
50
+
51
+ def destroy z, path
52
+ result = z.get_children(:path => path)
53
+ raise "failed to fetch child nodes." if result[:rc] != ZOK
54
+ result[:children].each do |entry|
55
+ destroy z, "#{path}/#{entry}"
56
+ end
57
+ z.delete(:path => path)
58
+ end
59
+
60
+ def nodemap z, path
61
+ result = z.get(:path => "#{path}/index/nodemap")
62
+ if result[:rc] == ZOK
63
+ xml = result[:data]
64
+ unless xml.nil?
65
+ cluster = Flare::Tools::Cluster.build xml
66
+ print cluster.serialize
67
+ end
68
+ end
69
+ end
70
+
71
+ def set_nodemap z, path
72
+ path_nodemap = "#{path}/index/nodemap"
73
+ xml = ""
74
+ while line = STDIN.gets
75
+ xml += line
76
+ end
77
+ result = z.set(:path => path_nodemap, :data => xml)
78
+ rc = result[:rc]
79
+ raise "failed to set nodemap (#{rc})" if rc != ZOK
80
+ end
81
+
82
+ def clear_nodemap z, path
83
+ path_nodemap = "#{path}/index/nodemap"
84
+ xml = <<EOS
85
+ <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
86
+ <!DOCTYPE boost_serialization>
87
+ <boost_serialization signature="serialization::archive" version="4">
88
+ <node_map class_id="0" tracking_level="0" version="0">
89
+ <count>0</count>
90
+ <item_version>0</item_version>
91
+ </node_map>
92
+ <thread_type>16</thread_type>
93
+ </boost_serialization>
94
+ EOS
95
+ STDOUT.print "do you really want to clear nodemap? (y/n):"
96
+ STDOUT.flush
97
+ if gets.chomp.upcase == 'Y'
98
+ result = z.set(:path => path_nodemap, :data => xml)
99
+ rc = result[:rc]
100
+ raise "failed to clear nodemap (#{rc})" if rc != ZOK
101
+ end
102
+ end
103
+
104
+ def servers z, path
105
+ result = z.get(:path => "#{path}/index/servers")
106
+ if result[:rc] == ZOK
107
+ puts result[:data].split(',').join(' ')
108
+ end
109
+ end
110
+
111
+ def set_servers z, path, *args
112
+ path_servers = "#{path}/index/servers"
113
+ result = z.set(:path => path_servers, :data => args.join(','))
114
+ rc = result[:rc]
115
+ raise "failed to set nodemap (#{rc})" if rc != ZOK
116
+ end
117
+
118
+ def show z, path
119
+ path_index = "#{path}/index"
120
+ path_lock = "#{path_index}/lock"
121
+ path_servers = "#{path_index}/servers"
122
+ path_nodemap = "#{path_index}/nodemap"
123
+ path_primary = "#{path_index}/primary"
124
+ path_meta = "#{path_index}/meta"
125
+ result = z.get_children(:path => path_index)
126
+ raise "failed to fetch child nodes." if result[:rc] != ZOK
127
+ result[:children].each do |entry|
128
+ puts "#{entry}:"
129
+ case entry
130
+ when "lock"
131
+ r = z.get_children(:path => path_lock)
132
+ if r[:rc] == ZOK
133
+ r[:children].sort_by {|n| n.split('-').last}.each do |m|
134
+ r2 = z.get(:path => "#{path_lock}/#{m}")
135
+ if r2[:rc] == ZOK
136
+ puts "\t#{m} #{r2[:data]}"
137
+ else
138
+ puts "\t#{m}"
139
+ end
140
+ end
141
+ end
142
+ when "primary"
143
+ r = z.get(:path => path_primary)
144
+ if r[:rc] == ZOK && !r[:data].nil?
145
+ puts "\t#{r[:data]}"
146
+ end
147
+ when "servers"
148
+ r = z.get(:path => path_servers)
149
+ puts "\t#{r[:data]}" if r[:rc] == ZOK && !r[:data].nil?
150
+ when "nodemap"
151
+ role_to_s = ["master", "slave", "proxy"]
152
+ state_to_s = ["active", "prepare", "down", "ready"]
153
+ r = z.get(:path => path_nodemap)
154
+ if r[:rc] == ZOK
155
+ xml = r[:data]
156
+ unless xml.nil?
157
+ cluster = Flare::Tools::Cluster.build xml
158
+ cluster.nodekeys.each do |nodekey|
159
+ n = cluster.node_stat(nodekey)
160
+ p = if n.partition == -1 then "-" else n.partition end
161
+ m = "#{n.server_name}:#{n.server_port}:#{n.balance}:#{p}"
162
+ puts "\t#{m} #{role_to_s[n.role.to_i]} #{state_to_s[n.state.to_i]} #{n.thread_type}"
163
+ end
164
+ end
165
+ end
166
+ when "meta"
167
+ r = z.get_children(:path => path_meta)
168
+ if r[:rc] == ZOK
169
+ r[:children].each do |m|
170
+ r2 = z.get(:path => "#{path_meta}/#{m}")
171
+ puts "\t#{m} #{r2[:data]}" if r2[:rc] == ZOK
172
+ end
173
+ end
174
+ else
175
+ puts "\tunknown entry"
176
+ end
177
+ end
178
+ end
179
+
180
+ def execute(subc, args, options)
181
+ scheme, userinfo, host, port, registry, path, opaque, query, flagment = URI.split(options[:indexdb])
182
+ # p scheme, userinfo, host, port, registry, path, opaque, query, flagment
183
+
184
+ z = case scheme
185
+ when "zookeeper"
186
+ Zookeeper.new("#{host}:#{port}")
187
+ else
188
+ raise "invalid scheme: #{scheme}"
189
+ end
190
+
191
+ case subc
192
+ when "set-servers"
193
+ set_servers z, path, *args
194
+ when "servers"
195
+ servers z, path
196
+ when "set-nodemap"
197
+ set_nodemap z, path
198
+ when "clear-nodemap"
199
+ clear_nodemap z, path
200
+ when "nodemap"
201
+ nodemap z, path
202
+ when "init"
203
+ init z, path
204
+ when "destroy"
205
+ destroy z, path
206
+ when "show"
207
+ show z, path
208
+ end
209
+ z.close
210
+ end
211
+
212
+ options = {
213
+ :indexdb => 'zookeeper://localhost:2181/ckvs/clusters/mycluster'
214
+ }
215
+
216
+ opt = OptionParser.new
217
+ opt.on('-i URI', '--index-db=URI') {|v|
218
+ options[:indexdb] = v
219
+ }
220
+
221
+ opt.parse!(ARGV)
222
+
223
+ subc = ARGV.shift
224
+ args = ARGV.dup
225
+
226
+ execute(subc, args, options)
@@ -0,0 +1,54 @@
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
+ require 'flare/tools/common'
8
+ require 'flare/tools/cluster'
9
+ require 'flare/tools/cli/sub_command'
10
+ require 'flare/util/conversion'
11
+
12
+ module Flare
13
+ module Tools
14
+ module Cli
15
+ class Index < SubCommand
16
+ include Flare::Util::Conversion
17
+
18
+ myname :index
19
+ desc "print the index XML document from a cluster information."
20
+ usage "index"
21
+
22
+ def setup(opt)
23
+ opt.on('--indexdb=URI', "index database" ) {|v| @indexdb = v}
24
+ opt.on('--output=FILE', "output index to a file") {|v| @output = v}
25
+ end
26
+
27
+ def initialize
28
+ super
29
+ @output = nil
30
+ @indexdb = nil
31
+ end
32
+
33
+ def execute(config, *args)
34
+ cluster = Flare::Tools::Stats.open(config[:index_server_hostname], config[:index_server_port], config[:timeout]) do |s|
35
+ nodes = s.stats_nodes.sort_by{|key, val| [val['partition'], val['role'], key]}
36
+ Flare::Tools::Cluster.new(s.host, s.port, s.stats_nodes)
37
+ end
38
+
39
+ output = cluster.serialize
40
+ if @output.nil?
41
+ info output
42
+ else
43
+ open(@output, "w") do |f|
44
+ f.write(output)
45
+ end
46
+ end
47
+
48
+ S_OK
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+