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 CHANGED
@@ -1 +1 @@
1
- 0.4.2
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.4.2"
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-18}
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}
@@ -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
- help!("host is a required option") unless command_options.shard_host
263
- service.shards_for_hostname(command_options.shard_host).each do |shard|
264
- next if command_options.shard_type && shard.class_name !~ Regexp.new(command_options.shard_type)
265
- output shard.id.to_unix
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
@@ -23,6 +23,10 @@ module Gizzard
23
23
  "#{hostname}/#{table_prefix}"
24
24
  end
25
25
 
26
+ def <=>(o)
27
+ self.hostname <=> o.hostname
28
+ end
29
+
26
30
  alias_method :to_unix, :inspect
27
31
 
28
32
  def self.parse(string)
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
- - 4
8
- - 2
9
- version: 0.4.2
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-18 00:00:00 -07:00
17
+ date: 2010-08-23 00:00:00 -07:00
18
18
  default_executable: gizzmo
19
19
  dependencies: []
20
20