gizzmo 0.7.0 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.7.4
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.7.0"
8
+ s.version = "0.7.4"
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-25}
12
+ s.date = %q{2010-10-04}
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}
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
29
29
  "gizzmo.gemspec",
30
30
  "lib/gizzard.rb",
31
31
  "lib/gizzard/commands.rb",
32
+ "lib/gizzard/digest.rb",
32
33
  "lib/gizzard/thrift.rb",
33
34
  "lib/gizzmo.rb",
34
35
  "lib/vendor/thrift_client/simple.rb",
data/lib/gizzard.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  $: << File.dirname(__FILE__)
2
2
  module Gizzard; end
3
3
  require "gizzard/thrift"
4
- require "gizzard/commands"
4
+ require "gizzard/commands"
5
+ require "gizzard/digest"
@@ -5,13 +5,13 @@ module Gizzard
5
5
 
6
6
  attr_reader :buffer
7
7
 
8
- def self.run(command_name, global_options, argv, subcommand_options, log)
8
+ def self.run(command_name, global_options, argv, subcommand_options, log, service=nil)
9
9
  command_class = Gizzard.const_get("#{classify(command_name)}Command")
10
- service = command_class.make_service(global_options, log)
10
+ service = command_class.make_service(global_options, log) if service.nil?
11
11
  command = command_class.new(service, global_options, argv, subcommand_options)
12
12
  command.run
13
13
  if command.buffer && command_name = global_options.render.shift
14
- run(command_name, service, global_options, command.buffer, OpenStruct.new)
14
+ run(command_name, global_options, command.buffer, OpenStruct.new, log, service)
15
15
  end
16
16
  end
17
17
 
@@ -86,7 +86,7 @@ module Gizzard
86
86
  end.reject do |forwarding|
87
87
  @command_options.table_ids && !@command_options.table_ids.include?(forwarding.table_id)
88
88
  end.each do |forwarding|
89
- output [ forwarding.table_id, forwarding.base_id, forwarding.shard_id.to_unix ].join("\t")
89
+ output [ forwarding.table_id, @command_options.hex ? ("%016x" % forwarding.base_id) : forwarding.base_id, forwarding.shard_id.to_unix ].join("\t")
90
90
  end
91
91
  end
92
92
  end
@@ -229,7 +229,7 @@ module Gizzard
229
229
  end
230
230
  end
231
231
  end
232
-
232
+
233
233
  class RepairCommand < ShardCommand
234
234
  def run
235
235
  args = @argv.dup.map{|a| a.split(/\s+/)}.flatten
@@ -289,7 +289,9 @@ module Gizzard
289
289
  end
290
290
 
291
291
  def run
292
- puts command_options.inspect
292
+ help! "No shards specified" if @argv.empty?
293
+ shards = []
294
+ command_options.write_only_shard ||= "com.twitter.gizzard.shards.WriteOnlyShard"
293
295
  additional_hosts = (command_options.hosts || "").split(/[\s,]+/)
294
296
  ids = @argv.map{|arg| ShardId.new(*arg.split("/")) rescue nil }.compact
295
297
  by_host = ids.inject({}) do |memo, id|
@@ -297,7 +299,7 @@ module Gizzard
297
299
  memo[id.hostname] << id
298
300
  memo
299
301
  end
300
-
302
+
301
303
  additional_hosts.each do |host|
302
304
  by_host[host] ||= NamedArray.new(host)
303
305
  end
@@ -312,7 +314,6 @@ module Gizzard
312
314
  end while longest.length > shortest.length + 1
313
315
 
314
316
  shard_info = nil
315
- puts sets.map{|l|l.length}.inspect
316
317
  sets.each do |set|
317
318
  host = set.name
318
319
  set.each do |id|
@@ -320,11 +321,17 @@ module Gizzard
320
321
  shard_info ||= service.get_shard(id)
321
322
  old = id.to_unix
322
323
  id.hostname = host
323
- puts "gizzmo create #{shard_info.class_name} -s '#{shard_info.source_type}' -d '#{shard_info.destination_type}' #{id.to_unix}"
324
- puts "gizzmo copy #{old} #{id.to_unix}"
324
+ shards << [old, id.to_unix]
325
325
  end
326
326
  end
327
327
  end
328
+
329
+ new_shards = shards.map{|(old, new)| new }
330
+
331
+ puts "gizzmo create #{shard_info.class_name} -s '#{shard_info.source_type}' -d '#{shard_info.destination_type}' #{new_shards.join(" ")}"
332
+ puts "gizzmo wrap #{command_options.write_only_shard} #{new_shards.join(" ")}"
333
+ shards.map {|(old, new)| puts "gizzmo copy #{old} #{new}" }
334
+ shards.map {|(old, new)| puts "gizzmo copy #{old} #{new}" }
328
335
  end
329
336
  end
330
337
 
@@ -359,8 +366,9 @@ module Gizzard
359
366
  displayed = {}
360
367
  overlaps.sort_by{|hosts, count| count }.reverse.each do |(host_a, host_b), count|
361
368
  next if !host_a || !host_b || displayed[host_a] || displayed[host_b]
362
- id_a = ids_by_host[host_a].first
363
- id_b = ids_by_host[host_b].first
369
+ id_a = ids_by_host[host_a].find{|id| service.list_upward_links(id).size > 0 }
370
+ id_b = ids_by_host[host_b].find{|id| service.list_upward_links(id).size > 0 }
371
+ next unless id_a && id_b
364
372
  weight_a = service.list_upward_links(id_a).first.weight
365
373
  weight_b = service.list_upward_links(id_b).first.weight
366
374
  if weight_a > weight_b
@@ -417,9 +425,15 @@ module Gizzard
417
425
 
418
426
  class LookupCommand < ShardCommand
419
427
  def run
420
- table_id, source_id = @argv
421
- help!("Requires table id and source id") unless table_id && source_id
422
- shard = service.find_current_forwarding(table_id.to_i, source_id.to_i)
428
+ table_id, source = @argv
429
+ help!("Requires table id and source") unless table_id && source
430
+ case @command_options.hash_function
431
+ when :fnv
432
+ source_id = Digest.fnv1a_64(source)
433
+ else
434
+ source_id = source.to_i
435
+ end
436
+ shard = service.find_current_forwarding(table_id.to_i, source_id)
423
437
  output shard.id.to_unix
424
438
  end
425
439
  end
@@ -521,4 +535,16 @@ module Gizzard
521
535
  STDERR.print "\n"
522
536
  end
523
537
  end
538
+
539
+ class FlushCommand < JobCommand
540
+ def run
541
+ args = @argv[0]
542
+ help!("Requires --all, or a job priority id.") unless args || command_options.flush_all
543
+ if command_options.flush_all
544
+ service.retry_errors()
545
+ else
546
+ service.retry_errors_for(args.to_i)
547
+ end
548
+ end
549
+ end
524
550
  end
@@ -0,0 +1,13 @@
1
+ module Gizzard
2
+ module Digest
3
+ def self.fnv1a_64(data)
4
+ prime = 1099511628211
5
+ rv = 0xcbf29ce484222325
6
+ data.each_byte do |byte|
7
+ rv = ((rv ^ (byte & 0xff)) * prime) & 0xffffffffffffffff
8
+ end
9
+ # trim to 60 bits for gizzard.
10
+ rv & 0x0fffffffffffffff
11
+ end
12
+ end
13
+ end
data/lib/gizzmo.rb CHANGED
@@ -9,7 +9,9 @@ require "yaml"
9
9
  DOC_STRINGS = {
10
10
  "create" => "Create shard(s) of a given Java/Scala class. If you don't know the list of available classes, you can just try a bogus class, and the exception will include a list of valid classes.",
11
11
  "wrap" => "Wrapping creates a new (virtual, e.g. blocking, replicating, etc.) shard, and relinks SHARD_ID_TO_WRAP's parent links to run through the new shard.",
12
- "inject" => "Inject jobs (as literal json) into the server. Jobs can be linefeed-terminated from stdin, or passed as arguments. Priority is server-defined, but typically lower numbers (like 1) are lower priority."
12
+ "inject" => "Inject jobs (as literal json) into the server. Jobs can be linefeed-terminated from stdin, or passed as arguments. Priority is server-defined, but typically lower numbers (like 1) are lower priority.",
13
+ "lookup" => "Lookup the shard id that holds the record for a given table / source_id.",
14
+ "flush" => "Flush error queue for a given priority."
13
15
  }
14
16
 
15
17
  ORIGINAL_ARGV = ARGV.dup
@@ -84,6 +86,10 @@ subcommands = {
84
86
  opts.banner = "Usage: #{zero} rebalance"
85
87
  separators(opts, DOC_STRINGS["rebalance"])
86
88
 
89
+ opts.on("-w", "--write-only=CLASS") do |w|
90
+ subcommand_options.write_only_shard = w
91
+ end
92
+
87
93
  opts.on("-h", "--hosts=list") do |h|
88
94
  subcommand_options.hosts = h
89
95
  end
@@ -128,6 +134,9 @@ subcommands = {
128
134
  subcommand_options.table_ids ||= []
129
135
  subcommand_options.table_ids += table_ids.split(",").map { |s| s.to_i }
130
136
  end
137
+ opts.on("-x", "--hex", "Show base ids in hex") do
138
+ subcommand_options.hex = true
139
+ end
131
140
  end,
132
141
  'unwrap' => OptionParser.new do |opts|
133
142
  opts.banner = "Usage: #{zero} unwrap SHARD_ID_TO_REMOVE [MORE SHARD_IDS]"
@@ -158,7 +167,7 @@ subcommands = {
158
167
  separators(opts, DOC_STRINGS["reload"])
159
168
  end,
160
169
  'addlink' => OptionParser.new do |opts|
161
- opts.banner = "Usage: #{zero} link PARENT_SHARD_ID CHILD_SHARD_ID WEIGHT"
170
+ opts.banner = "Usage: #{zero} addlink PARENT_SHARD_ID WEIGHT"
162
171
  separators(opts, DOC_STRINGS["addlink"])
163
172
  end,
164
173
  'unlink' => OptionParser.new do |opts|
@@ -166,8 +175,12 @@ subcommands = {
166
175
  separators(opts, DOC_STRINGS["unlink"])
167
176
  end,
168
177
  'lookup' => OptionParser.new do |opts|
169
- opts.banner = "Usage: #{zero} lookup TABLE_ID SOURCE_ID"
178
+ opts.banner = "Usage: #{zero} lookup [options] TABLE_ID SOURCE"
170
179
  separators(opts, DOC_STRINGS["lookup"])
180
+
181
+ opts.on("--fnv", "Use FNV1A_64 hash on source") do
182
+ subcommand_options.hash_function = :fnv
183
+ end
171
184
  end,
172
185
  'copy' => OptionParser.new do |opts|
173
186
  opts.banner = "Usage: #{zero} copy SOURCE_SHARD_ID DESTINATION_SHARD_ID"
@@ -188,6 +201,14 @@ subcommands = {
188
201
  'inject' => OptionParser.new do |opts|
189
202
  opts.banner = "Usage: #{zero} inject PRIORITY JOBS..."
190
203
  separators(opts, DOC_STRINGS["inject"])
204
+ end,
205
+ 'flush' => OptionParser.new do |opts|
206
+ opts.banner = "Usage: #{zero} flush --all|PRIORITY"
207
+ separators(opts, DOC_STRINGS["flush"])
208
+
209
+ opts.on("--all", "Flush all error queues.") do
210
+ subcommand_options.flush_all = true
211
+ end
191
212
  end
192
213
  }
193
214
 
@@ -227,7 +248,7 @@ global = OptionParser.new do |opts|
227
248
  end
228
249
 
229
250
  opts.on("-P", "--port=PORT", "PORT of remote thrift service") do |port|
230
- global_options.port = port
251
+ global_options.port = port.to_i
231
252
  end
232
253
 
233
254
  opts.on("-r", "--retry=TIMES", "TIMES to retry the command") do |r|
@@ -338,4 +359,4 @@ rescue Errno::EPIPE
338
359
  # seeing the backtrace is annoying!
339
360
  rescue Interrupt
340
361
  exit 1
341
- end
362
+ end
data/test/test.sh CHANGED
@@ -6,7 +6,7 @@ function g {
6
6
  }
7
7
 
8
8
  function expect {
9
- diff -u - "expected/$1" && echo " success." || echo " failed." && exit 1
9
+ diff -u - "expected/$1" && echo " success." || (echo " failed." && exit 1)
10
10
  }
11
11
 
12
12
  function expect-string {
@@ -19,9 +19,9 @@ g find -hlocalhost | expect empty-file.txt
19
19
 
20
20
  for i in {0..9}
21
21
  do
22
- g create localhost "table_repl_$i" com.twitter.service.flock.edges.ReplicatingShard
23
- g create localhost "table_a_$i" com.twitter.service.flock.edges.SqlShard --source-type="INT UNSIGNED" --destination-type="INT UNSIGNED"
24
- g create localhost "table_b_$i" com.twitter.service.flock.edges.SqlShard --source-type="INT UNSIGNED" --destination-type="INT UNSIGNED"
22
+ g create com.twitter.service.flock.edges.ReplicatingShard localhost/table_repl_$i
23
+ g create com.twitter.service.flock.edges.SqlShard localhost/table_a_$i --source-type="INT UNSIGNED" --destination-type="INT UNSIGNED"
24
+ g create com.twitter.service.flock.edges.SqlShard localhost/table_b_$i --source-type="INT UNSIGNED" --destination-type="INT UNSIGNED"
25
25
  g addlink "localhost/table_repl_$i" "localhost/table_a_$i" 2
26
26
  g addlink "localhost/table_repl_$i" "localhost/table_b_$i" 1
27
27
  done
@@ -52,6 +52,7 @@ g links localhost/replicating_table_b_0 | expect links-for-replicating_table_b_0
52
52
  g --subtree --info find -Hlocalhost | expect subtree-info.txt
53
53
 
54
54
  g lookup 1 100 | expect-string "localhost/forward_1"
55
+ g lookup --fnv 1 "hello" | expect-string "localhost/forward_1"
55
56
 
56
57
  g unwrap localhost/replicating_table_b_0 | expect unwrapped-replicating_table_b_0.txt
57
58
  g links localhost/table_b_0 | expect unwrapped-table_b_0.txt
@@ -72,4 +73,7 @@ do
72
73
  g addlink "localhost/table_deep_repl_$last" "localhost/table_deep_repl_$i" 2
73
74
  done
74
75
 
75
- g subtree localhost/table_deep_repl_5 | expect deep.txt
76
+ g subtree localhost/table_deep_repl_5 | expect deep.txt
77
+
78
+ g flush --all
79
+ g flush 1
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 7
8
- - 0
9
- version: 0.7.0
8
+ - 4
9
+ version: 0.7.4
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-25 00:00:00 -07:00
17
+ date: 2010-10-04 00:00:00 -07:00
18
18
  default_executable: gizzmo
19
19
  dependencies: []
20
20
 
@@ -38,6 +38,7 @@ files:
38
38
  - gizzmo.gemspec
39
39
  - lib/gizzard.rb
40
40
  - lib/gizzard/commands.rb
41
+ - lib/gizzard/digest.rb
41
42
  - lib/gizzard/thrift.rb
42
43
  - lib/gizzmo.rb
43
44
  - lib/vendor/thrift_client/simple.rb