gizzmo 0.7.0 → 0.7.4
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 +3 -2
- data/lib/gizzard.rb +2 -1
- data/lib/gizzard/commands.rb +41 -15
- data/lib/gizzard/digest.rb +13 -0
- data/lib/gizzmo.rb +26 -5
- data/test/test.sh +9 -5
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
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.
|
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-
|
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
data/lib/gizzard/commands.rb
CHANGED
@@ -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,
|
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
|
-
|
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
|
-
|
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].
|
363
|
-
id_b = ids_by_host[host_b].
|
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,
|
421
|
-
help!("Requires table id and source
|
422
|
-
|
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}
|
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
|
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
|
23
|
-
g create
|
24
|
-
g create
|
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
|
-
-
|
9
|
-
version: 0.7.
|
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-
|
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
|