gizzmo 0.4.2 → 0.5.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.
- data/VERSION +1 -1
- data/gizzmo.gemspec +2 -2
- data/lib/gizzard/commands.rb +125 -5
- data/lib/gizzard/thrift.rb +4 -0
- data/lib/gizzmo.rb +15 -3
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/gizzmo.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{gizzmo}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Kyle Maxwell"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-23}
|
13
13
|
s.default_executable = %q{gizzmo}
|
14
14
|
s.description = %q{Gizzmo is a command-line client for managing gizzard clusters.}
|
15
15
|
s.email = %q{kmaxwell@twitter.com}
|
data/lib/gizzard/commands.rb
CHANGED
@@ -78,7 +78,7 @@ module Gizzard
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
class ForwardingsCommand < ShardCommand
|
83
83
|
def run
|
84
84
|
service.get_forwardings().sort_by do |f|
|
@@ -257,12 +257,132 @@ module Gizzard
|
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
260
|
+
class RebalanceCommand < ShardCommand
|
261
|
+
|
262
|
+
class NamedArray < Array
|
263
|
+
attr_reader :name
|
264
|
+
def initialize(name)
|
265
|
+
@name = name
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def run
|
270
|
+
ids = @argv.map{|arg| ShardId.new(*arg.split("/")) rescue nil }.compact
|
271
|
+
by_host = ids.inject({}) do |memo, id|
|
272
|
+
memo[id.hostname] ||= NamedArray.new(id.hostname)
|
273
|
+
memo[id.hostname] << id
|
274
|
+
memo
|
275
|
+
end
|
276
|
+
|
277
|
+
sets = by_host.values
|
278
|
+
|
279
|
+
begin
|
280
|
+
sorted = sets.sort_by{|s| s.length }
|
281
|
+
longest = sorted.last
|
282
|
+
shortest = sorted.first
|
283
|
+
shortest.push longest.pop
|
284
|
+
end while longest.length > shortest.length + 1
|
285
|
+
|
286
|
+
shard_info = nil
|
287
|
+
sets.each do |set|
|
288
|
+
host = set.name
|
289
|
+
set.each do |id|
|
290
|
+
if id.hostname != host
|
291
|
+
shard_info ||= service.get_shard(id)
|
292
|
+
old = id.to_unix
|
293
|
+
id.hostname = host
|
294
|
+
puts "gizzmo create #{shard_info.class_name} -s '#{shard_info.source_type}' -d '#{shard_info.destination_type}' #{old}"
|
295
|
+
puts "gizzmo copy #{old} #{id.to_unix}"
|
296
|
+
puts "gizzmo delete #{old}"
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
class PairCommand < ShardCommand
|
304
|
+
def run
|
305
|
+
ids = []
|
306
|
+
@argv.map do |host|
|
307
|
+
service.shards_for_hostname(host).each do |shard|
|
308
|
+
ids << shard.id
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
ids_by_table = {}
|
313
|
+
ids.map do |id|
|
314
|
+
ids_by_table[id.table_prefix] ||= []
|
315
|
+
ids_by_table[id.table_prefix] << id
|
316
|
+
end
|
317
|
+
|
318
|
+
ids_by_host = {}
|
319
|
+
ids.map do |id|
|
320
|
+
ids_by_host[id.hostname] ||= []
|
321
|
+
ids_by_host[id.hostname] << id
|
322
|
+
end
|
323
|
+
|
324
|
+
overlaps = {}
|
325
|
+
ids_by_table.values.each do |arr|
|
326
|
+
key = arr.map{|id| id.hostname }.sort
|
327
|
+
overlaps[key] ||= 0
|
328
|
+
overlaps[key] += 1
|
329
|
+
end
|
330
|
+
|
331
|
+
displayed = {}
|
332
|
+
overlaps.sort_by{|hosts, count| count }.reverse.each do |(host_a, host_b), count|
|
333
|
+
next if !host_a || !host_b || displayed[host_a] || displayed[host_b]
|
334
|
+
id_a = ids_by_host[host_a].first
|
335
|
+
id_b = ids_by_host[host_b].first
|
336
|
+
weight_a = service.list_upward_links(id_a).first.weight
|
337
|
+
weight_b = service.list_upward_links(id_b).first.weight
|
338
|
+
if weight_a > weight_b
|
339
|
+
puts "#{host_a}\t#{host_b}"
|
340
|
+
else
|
341
|
+
puts "#{host_b}\t#{host_a}"
|
342
|
+
end
|
343
|
+
displayed[host_a] = true
|
344
|
+
displayed[host_b] = true
|
345
|
+
end
|
346
|
+
remaining = @argv - displayed.keys
|
347
|
+
loop do
|
348
|
+
a = remaining.shift
|
349
|
+
b = remaining.shift
|
350
|
+
break unless a && b
|
351
|
+
puts "#{a}\t#{b}"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
class ReportCommand < ShardCommand
|
357
|
+
def run
|
358
|
+
regex = @argv.first
|
359
|
+
help!("regex is a required option") unless regex
|
360
|
+
regex = Regexp.compile(regex)
|
361
|
+
service.list_hostnames.map do |host|
|
362
|
+
puts host
|
363
|
+
counts = {}
|
364
|
+
service.shards_for_hostname(host).each do |shard|
|
365
|
+
id = shard.id.to_unix
|
366
|
+
if key = id[regex, 1] || id[regex, 0]
|
367
|
+
counts[key] ||= 0
|
368
|
+
counts[key] += 1
|
369
|
+
end
|
370
|
+
end
|
371
|
+
counts.sort.each do |k, v|
|
372
|
+
puts " %3d %s" % [v, k]
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
260
378
|
class FindCommand < ShardCommand
|
261
379
|
def run
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
380
|
+
hosts = @argv << command_options.shard_host
|
381
|
+
hosts.compact.each do |host|
|
382
|
+
service.shards_for_hostname(host).each do |shard|
|
383
|
+
next if command_options.shard_type && shard.class_name !~ Regexp.new(command_options.shard_type)
|
384
|
+
output shard.id.to_unix
|
385
|
+
end
|
266
386
|
end
|
267
387
|
end
|
268
388
|
end
|
data/lib/gizzard/thrift.rb
CHANGED
data/lib/gizzmo.rb
CHANGED
@@ -63,7 +63,7 @@ subcommands = {
|
|
63
63
|
'create' => OptionParser.new do |opts|
|
64
64
|
opts.banner = "Usage: #{zero} create [options] CLASS_NAME SHARD_ID [MORE SHARD_IDS...]"
|
65
65
|
separators(opts, DOC_STRINGS["create"])
|
66
|
-
|
66
|
+
|
67
67
|
opts.on("-s", "--source-type=TYPE") do |s|
|
68
68
|
subcommand_options.source_type = s
|
69
69
|
end
|
@@ -76,6 +76,18 @@ subcommands = {
|
|
76
76
|
opts.banner = "Usage: #{zero} wrap CLASS_NAME SHARD_ID_TO_WRAP [MORE SHARD_IDS...]"
|
77
77
|
separators(opts, DOC_STRINGS["wrap"])
|
78
78
|
end,
|
79
|
+
'report' => OptionParser.new do |opts|
|
80
|
+
opts.banner = "Usage: #{zero} report RUBY_REGEX"
|
81
|
+
separators(opts, DOC_STRINGS["report"])
|
82
|
+
end,
|
83
|
+
'rebalance' => OptionParser.new do |opts|
|
84
|
+
opts.banner = "Usage: #{zero} rebalance RUBY_REGEX"
|
85
|
+
separators(opts, DOC_STRINGS["rebalance"])
|
86
|
+
end,
|
87
|
+
'pair' => OptionParser.new do |opts|
|
88
|
+
opts.banner = "Usage: #{zero} pair"
|
89
|
+
separators(opts, DOC_STRINGS["pair"])
|
90
|
+
end,
|
79
91
|
'subtree' => OptionParser.new do |opts|
|
80
92
|
opts.banner = "Usage: #{zero} subtree SHARD_ID"
|
81
93
|
separators(opts, DOC_STRINGS["subtree"])
|
@@ -209,11 +221,11 @@ global = OptionParser.new do |opts|
|
|
209
221
|
opts.on("-P", "--port=PORT", "PORT of remote thrift service") do |port|
|
210
222
|
global_options.port = port
|
211
223
|
end
|
212
|
-
|
224
|
+
|
213
225
|
opts.on("--subtree", "Render in subtree mode") do
|
214
226
|
global_options.render << "subtree"
|
215
227
|
end
|
216
|
-
|
228
|
+
|
217
229
|
opts.on("--info", "Render in info mode") do
|
218
230
|
global_options.render << "info"
|
219
231
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 5
|
8
|
+
- 0
|
9
|
+
version: 0.5.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Kyle Maxwell
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-08-
|
17
|
+
date: 2010-08-23 00:00:00 -07:00
|
18
18
|
default_executable: gizzmo
|
19
19
|
dependencies: []
|
20
20
|
|