gizzmo 0.4.2 → 0.5.0

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