gizzmo 0.3.5 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/VERSION +1 -1
- data/gizzmo.gemspec +2 -2
- data/lib/gizzard/commands.rb +157 -25
- data/lib/gizzard/thrift.rb +17 -3
- data/lib/gizzmo.rb +114 -23
- metadata +4 -4
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.1
|
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.4.1"
|
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-07-
|
12
|
+
s.date = %q{2010-07-29}
|
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
@@ -2,11 +2,13 @@ require "pp"
|
|
2
2
|
module Gizzard
|
3
3
|
class Command
|
4
4
|
include Thrift
|
5
|
-
|
5
|
+
|
6
6
|
attr_reader :buffer
|
7
7
|
|
8
|
-
def self.run(command_name,
|
9
|
-
|
8
|
+
def self.run(command_name, global_options, argv, subcommand_options, log)
|
9
|
+
command_class = Gizzard.const_get("#{classify(command_name)}Command")
|
10
|
+
service = command_class.make_service(global_options, log)
|
11
|
+
command = command_class.new(service, global_options, argv, subcommand_options)
|
10
12
|
command.run
|
11
13
|
if command.buffer && command_name = global_options.render.shift
|
12
14
|
run(command_name, service, global_options, command.buffer, OpenStruct.new)
|
@@ -28,18 +30,30 @@ module Gizzard
|
|
28
30
|
def help!(message = nil)
|
29
31
|
raise HelpNeededError, message
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
def output(string)
|
33
35
|
if global_options.render.any?
|
34
36
|
@buffer ||= []
|
35
37
|
@buffer << string.strip
|
36
|
-
else
|
38
|
+
else
|
37
39
|
puts string
|
38
40
|
end
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
class
|
44
|
+
class ShardCommand < Command
|
45
|
+
def self.make_service(global_options, log)
|
46
|
+
Gizzard::Thrift::ShardManager.new(global_options.host, global_options.port, log, global_options.dry)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class JobCommand < Command
|
51
|
+
def self.make_service(global_options, log)
|
52
|
+
Gizzard::Thrift::JobManager.new(global_options.host, global_options.port + 2, log, global_options.dry)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class AddforwardingCommand < ShardCommand
|
43
57
|
def run
|
44
58
|
help! if argv.length != 3
|
45
59
|
table_id, base_id, shard_id_text = argv
|
@@ -48,7 +62,24 @@ module Gizzard
|
|
48
62
|
end
|
49
63
|
end
|
50
64
|
|
51
|
-
class
|
65
|
+
class DeleteforwardingCommand < ShardCommand
|
66
|
+
def run
|
67
|
+
help! if argv.length != 3
|
68
|
+
table_id, base_id, shard_id_text = argv
|
69
|
+
shard_id = ShardId.parse(shard_id_text)
|
70
|
+
service.remove_forwarding(Forwarding.new(table_id.to_i, base_id.to_i, shard_id))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class HostsCommand < ShardCommand
|
75
|
+
def run
|
76
|
+
service.list_hostnames.map do |host|
|
77
|
+
puts host
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class ForwardingsCommand < ShardCommand
|
52
83
|
def run
|
53
84
|
service.get_forwardings().sort_by do |f|
|
54
85
|
[ ((f.table_id.abs << 1) + (f.table_id < 0 ? 1 : 0)), f.base_id ]
|
@@ -60,7 +91,7 @@ module Gizzard
|
|
60
91
|
end
|
61
92
|
end
|
62
93
|
|
63
|
-
class SubtreeCommand <
|
94
|
+
class SubtreeCommand < ShardCommand
|
64
95
|
def run
|
65
96
|
@roots = []
|
66
97
|
argv.each do |arg|
|
@@ -81,7 +112,7 @@ module Gizzard
|
|
81
112
|
links.map { |link| roots_of(link.up_id) }.flatten
|
82
113
|
end
|
83
114
|
end
|
84
|
-
|
115
|
+
|
85
116
|
def down(id, depth = 0)
|
86
117
|
service.list_downward_links(id).map do |link|
|
87
118
|
printable = " " * depth + link.down_id.to_unix
|
@@ -91,7 +122,7 @@ module Gizzard
|
|
91
122
|
end
|
92
123
|
end
|
93
124
|
|
94
|
-
class ReloadCommand <
|
125
|
+
class ReloadCommand < ShardCommand
|
95
126
|
def run
|
96
127
|
if global_options.force || ask
|
97
128
|
service.reload_forwardings
|
@@ -106,7 +137,7 @@ module Gizzard
|
|
106
137
|
end
|
107
138
|
end
|
108
139
|
|
109
|
-
class DeleteCommand <
|
140
|
+
class DeleteCommand < ShardCommand
|
110
141
|
def run
|
111
142
|
argv.each do |arg|
|
112
143
|
id = ShardId.parse(arg)
|
@@ -116,7 +147,7 @@ module Gizzard
|
|
116
147
|
end
|
117
148
|
end
|
118
149
|
|
119
|
-
class AddlinkCommand <
|
150
|
+
class AddlinkCommand < ShardCommand
|
120
151
|
def run
|
121
152
|
up_id, down_id, weight = argv
|
122
153
|
help! if argv.length != 3
|
@@ -129,7 +160,7 @@ module Gizzard
|
|
129
160
|
end
|
130
161
|
end
|
131
162
|
|
132
|
-
class UnlinkCommand <
|
163
|
+
class UnlinkCommand < ShardCommand
|
133
164
|
def run
|
134
165
|
up_id, down_id = argv
|
135
166
|
up_id = ShardId.parse(up_id)
|
@@ -138,7 +169,7 @@ module Gizzard
|
|
138
169
|
end
|
139
170
|
end
|
140
171
|
|
141
|
-
class UnwrapCommand <
|
172
|
+
class UnwrapCommand < ShardCommand
|
142
173
|
def run
|
143
174
|
shard_ids = argv
|
144
175
|
help! "No shards specified" if shard_ids.empty?
|
@@ -158,20 +189,23 @@ module Gizzard
|
|
158
189
|
end
|
159
190
|
end
|
160
191
|
|
161
|
-
class CreateCommand <
|
192
|
+
class CreateCommand < ShardCommand
|
162
193
|
def run
|
163
|
-
help! if argv.length
|
164
|
-
|
194
|
+
help! if argv.length < 2
|
195
|
+
class_name, *shard_ids = argv
|
165
196
|
busy = 0
|
166
197
|
source_type = command_options.source_type || ""
|
167
198
|
destination_type = command_options.destination_type || ""
|
168
|
-
|
169
|
-
|
170
|
-
|
199
|
+
shard_ids.each do |id|
|
200
|
+
shard_id = ShardId.parse(id)
|
201
|
+
service.create_shard(ShardInfo.new(shard_id, class_name, source_type, destination_type, busy))
|
202
|
+
service.get_shard(shard_id)
|
203
|
+
output shard_id.to_unix
|
204
|
+
end
|
171
205
|
end
|
172
206
|
end
|
173
207
|
|
174
|
-
class LinksCommand <
|
208
|
+
class LinksCommand < ShardCommand
|
175
209
|
def run
|
176
210
|
shard_ids = @argv
|
177
211
|
shard_ids.each do |shard_id_text|
|
@@ -186,7 +220,7 @@ module Gizzard
|
|
186
220
|
end
|
187
221
|
end
|
188
222
|
|
189
|
-
class InfoCommand <
|
223
|
+
class InfoCommand < ShardCommand
|
190
224
|
def run
|
191
225
|
shard_ids = @argv
|
192
226
|
shard_ids.each do |shard_id|
|
@@ -196,7 +230,7 @@ module Gizzard
|
|
196
230
|
end
|
197
231
|
end
|
198
232
|
|
199
|
-
class WrapCommand <
|
233
|
+
class WrapCommand < ShardCommand
|
200
234
|
def self.derive_wrapper_shard_id(shard_info, wrapping_class_name)
|
201
235
|
prefix_prefix = wrapping_class_name.split(".").last.downcase.gsub("shard", "") + "_"
|
202
236
|
ShardId.new("localhost", prefix_prefix + shard_info.id.table_prefix)
|
@@ -223,7 +257,7 @@ module Gizzard
|
|
223
257
|
end
|
224
258
|
end
|
225
259
|
|
226
|
-
class FindCommand <
|
260
|
+
class FindCommand < ShardCommand
|
227
261
|
def run
|
228
262
|
help!("host is a required option") unless command_options.shard_host
|
229
263
|
service.shards_for_hostname(command_options.shard_host).each do |shard|
|
@@ -233,7 +267,7 @@ module Gizzard
|
|
233
267
|
end
|
234
268
|
end
|
235
269
|
|
236
|
-
class LookupCommand <
|
270
|
+
class LookupCommand < ShardCommand
|
237
271
|
def run
|
238
272
|
table_id, source_id = @argv
|
239
273
|
help!("Requires table id and source id") unless table_id && source_id
|
@@ -241,4 +275,102 @@ module Gizzard
|
|
241
275
|
output shard.id.to_unix
|
242
276
|
end
|
243
277
|
end
|
278
|
+
|
279
|
+
class CopyCommand < ShardCommand
|
280
|
+
def run
|
281
|
+
from_shard_id_string, to_shard_id_string = @argv
|
282
|
+
help!("Requires source & destination shard id") unless from_shard_id_string && to_shard_id_string
|
283
|
+
from_shard_id = ShardId.parse(from_shard_id_string)
|
284
|
+
to_shard_id = ShardId.parse(to_shard_id_string)
|
285
|
+
service.copy_shard(from_shard_id, to_shard_id)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
class BusyCommand < ShardCommand
|
290
|
+
def run
|
291
|
+
service.get_busy_shards().each { |shard_info| output shard_info.to_unix }
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
class SetupMigrateCommand < ShardCommand
|
296
|
+
def run
|
297
|
+
from_shard_id_string, to_shard_id_string = @argv
|
298
|
+
help!("Requires source & destination shard id") unless from_shard_id_string && to_shard_id_string
|
299
|
+
from_shard_id = ShardId.parse(from_shard_id_string)
|
300
|
+
to_shard_id = ShardId.parse(to_shard_id_string)
|
301
|
+
|
302
|
+
if service.list_upward_links(to_shard_id).size > 0
|
303
|
+
STDERR.puts "Destination shard #{to_shard_id} has links to it."
|
304
|
+
exit 1
|
305
|
+
end
|
306
|
+
|
307
|
+
write_only_shard_id = ShardId.new("localhost", "#{to_shard_id.table_prefix}_migrate_write_only")
|
308
|
+
replica_shard_id = ShardId.new("localhost", "#{to_shard_id.table_prefix}_migrate_replica")
|
309
|
+
service.create_shard(ShardInfo.new(write_only_shard_id, "com.twitter.gizzard.shards.WriteOnlyShard", "", "", 0))
|
310
|
+
service.create_shard(ShardInfo.new(replica_shard_id, "com.twitter.gizzard.shards.ReplicatingShard", "", "", 0))
|
311
|
+
service.add_link(write_only_shard_id, to_shard_id, 1)
|
312
|
+
service.list_upward_links(from_shard_id).each do |link|
|
313
|
+
service.remove_link(link.up_id, link.down_id)
|
314
|
+
service.add_link(link.up_id, replica_shard_id, link.weight)
|
315
|
+
end
|
316
|
+
service.add_link(replica_shard_id, from_shard_id, 1)
|
317
|
+
service.add_link(replica_shard_id, write_only_shard_id, 0)
|
318
|
+
service.replace_forwarding(from_shard_id, replica_shard_id)
|
319
|
+
output replica_shard_id.to_unix
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
class FinishMigrateCommand < ShardCommand
|
324
|
+
def run
|
325
|
+
from_shard_id_string, to_shard_id_string = @argv
|
326
|
+
help!("Requires source & destination shard id") unless from_shard_id_string && to_shard_id_string
|
327
|
+
from_shard_id = ShardId.parse(from_shard_id_string)
|
328
|
+
to_shard_id = ShardId.parse(to_shard_id_string)
|
329
|
+
|
330
|
+
write_only_shard_id = ShardId.new("localhost", "#{to_shard_id.table_prefix}_migrate_write_only")
|
331
|
+
replica_shard_id = ShardId.new("localhost", "#{to_shard_id.table_prefix}_migrate_replica")
|
332
|
+
|
333
|
+
# careful. need to validate some basic assumptions.
|
334
|
+
unless global_options.force
|
335
|
+
if service.list_upward_links(from_shard_id).map { |link| link.up_id }.to_a != [ replica_shard_id ]
|
336
|
+
STDERR.puts "Uplink from #{from_shard_id} is not a migration replica."
|
337
|
+
exit 1
|
338
|
+
end
|
339
|
+
if service.list_upward_links(to_shard_id).map { |link| link.up_id }.to_a != [ write_only_shard_id ]
|
340
|
+
STDERR.puts "Uplink from #{to_shard_id} is not a write-only barrier."
|
341
|
+
exit 1
|
342
|
+
end
|
343
|
+
if service.list_upward_links(write_only_shard_id).map { |link| link.up_id }.to_a != [ replica_shard_id ]
|
344
|
+
STDERR.puts "Uplink from write-only barrier is not a migration replica."
|
345
|
+
exit 1
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
service.remove_link(write_only_shard_id, to_shard_id)
|
350
|
+
service.list_upward_links(replica_shard_id).each do |link|
|
351
|
+
service.remove_link(link.up_id, link.down_id)
|
352
|
+
service.add_link(link.up_id, to_shard_id, link.weight)
|
353
|
+
end
|
354
|
+
service.replace_forwarding(replica_shard_id, to_shard_id)
|
355
|
+
service.delete_shard(replica_shard_id)
|
356
|
+
service.delete_shard(write_only_shard_id)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
class InjectCommand < JobCommand
|
361
|
+
def run
|
362
|
+
priority, *jobs = @argv
|
363
|
+
help!("Requires priority") unless priority and jobs.size > 0
|
364
|
+
count = 0
|
365
|
+
jobs.each do |job|
|
366
|
+
service.inject_job(priority.to_i, job)
|
367
|
+
count += 1
|
368
|
+
# FIXME add -q --quiet option
|
369
|
+
STDERR.print "."
|
370
|
+
STDERR.print "#{count}" if count % 100 == 0
|
371
|
+
STDERR.flush
|
372
|
+
end
|
373
|
+
STDERR.print "\n"
|
374
|
+
end
|
375
|
+
end
|
244
376
|
end
|
data/lib/gizzard/thrift.rb
CHANGED
@@ -86,7 +86,7 @@ module Gizzard
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
class
|
89
|
+
class GizzmoService < T::ThriftService
|
90
90
|
def initialize(host, port, log_path, dry_run = false)
|
91
91
|
super(host, port)
|
92
92
|
@dry = dry_run
|
@@ -122,8 +122,9 @@ module Gizzard
|
|
122
122
|
ts = timestamp ? "#{Time.now}\t" : ""
|
123
123
|
"#{ts}#{method_name}(#{args.map{|a| a.inspect}.join(', ')})"
|
124
124
|
end
|
125
|
+
end
|
125
126
|
|
126
|
-
|
127
|
+
class ShardManager < GizzmoService
|
127
128
|
thrift_method :create_shard, void, field(:shard, struct(ShardInfo), 1), :throws => exception(ShardException)
|
128
129
|
thrift_method :delete_shard, void, field(:id, struct(ShardId), 1)
|
129
130
|
thrift_method :get_shard, struct(ShardInfo), field(:id, struct(ShardId), 1)
|
@@ -141,6 +142,7 @@ module Gizzard
|
|
141
142
|
|
142
143
|
thrift_method :set_forwarding, void, field(:forwarding, struct(Forwarding), 1)
|
143
144
|
thrift_method :replace_forwarding, void, field(:old_id, struct(ShardId), 1), field(:new_id, struct(ShardId), 2)
|
145
|
+
thrift_method :remove_forwarding, void, field(:forwarding, struct(Forwarding), 1)
|
144
146
|
|
145
147
|
thrift_method :get_forwarding, struct(Forwarding), field(:table_id, i32, 1), field(:base_id, i64, 2)
|
146
148
|
thrift_method :get_forwarding_for_shard, struct(Forwarding), field(:shard_id, struct(ShardId), 1)
|
@@ -152,8 +154,20 @@ module Gizzard
|
|
152
154
|
|
153
155
|
thrift_method :shards_for_hostname, list(struct(ShardInfo)), field(:hostname, string, 1)
|
154
156
|
thrift_method :get_busy_shards, list(struct(ShardInfo))
|
157
|
+
thrift_method :list_hostnames, list(string)
|
155
158
|
|
156
159
|
thrift_method :rebuild_schema, void
|
157
160
|
end
|
161
|
+
|
162
|
+
class JobManager < GizzmoService
|
163
|
+
thrift_method :retry_errors, void
|
164
|
+
thrift_method :stop_writes, void
|
165
|
+
thrift_method :resume_writes, void
|
166
|
+
thrift_method :retry_errors_for, void, field(:priority, i32, 1)
|
167
|
+
thrift_method :stop_writes_for, void, field(:priority, i32, 1)
|
168
|
+
thrift_method :resume_writes_for, void, field(:priority, i32, 1)
|
169
|
+
thrift_method :is_writing, bool, field(:priority, i32, 1)
|
170
|
+
thrift_method :inject_job, void, field(:priority, i32, 1), field(:job, string, 2)
|
171
|
+
end
|
158
172
|
end
|
159
|
-
end
|
173
|
+
end
|
data/lib/gizzmo.rb
CHANGED
@@ -6,7 +6,14 @@ require "ostruct"
|
|
6
6
|
require "gizzard"
|
7
7
|
require "yaml"
|
8
8
|
|
9
|
+
DOC_STRINGS = {
|
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
|
+
"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."
|
13
|
+
}
|
14
|
+
|
9
15
|
ORIGINAL_ARGV = ARGV.dup
|
16
|
+
zero = File.basename($0)
|
10
17
|
|
11
18
|
# Container for parsed options
|
12
19
|
global_options = OpenStruct.new
|
@@ -28,10 +35,35 @@ rescue => e
|
|
28
35
|
abort "Unknown error loading ~/.gizzmorc: #{e.message}"
|
29
36
|
end
|
30
37
|
|
38
|
+
def split(string)
|
39
|
+
return [] unless string
|
40
|
+
a = []
|
41
|
+
tokens = string.split(/\s+/)
|
42
|
+
a << tokens.shift
|
43
|
+
tokens.each do |token|
|
44
|
+
s = a.last
|
45
|
+
if s.length + token.length + 1 < 80
|
46
|
+
s << " #{token}"
|
47
|
+
else
|
48
|
+
a << token
|
49
|
+
end
|
50
|
+
end
|
51
|
+
a
|
52
|
+
end
|
53
|
+
|
54
|
+
def separators(opts, string)
|
55
|
+
opts.separator("")
|
56
|
+
split(string).each do |substr|
|
57
|
+
opts.separator(substr)
|
58
|
+
end
|
59
|
+
opts.separator("")
|
60
|
+
end
|
61
|
+
|
31
62
|
subcommands = {
|
32
63
|
'create' => OptionParser.new do |opts|
|
33
|
-
opts.banner = "Usage: #{
|
34
|
-
|
64
|
+
opts.banner = "Usage: #{zero} create [options] CLASS_NAME SHARD_ID [MORE SHARD_IDS...]"
|
65
|
+
separators(opts, DOC_STRINGS["create"])
|
66
|
+
|
35
67
|
opts.on("-s", "--source-type=TYPE") do |s|
|
36
68
|
subcommand_options.source_type = s
|
37
69
|
end
|
@@ -41,19 +73,32 @@ subcommands = {
|
|
41
73
|
end
|
42
74
|
end,
|
43
75
|
'wrap' => OptionParser.new do |opts|
|
44
|
-
opts.banner = "Usage: #{
|
76
|
+
opts.banner = "Usage: #{zero} wrap CLASS_NAME SHARD_ID_TO_WRAP [MORE SHARD_IDS...]"
|
77
|
+
separators(opts, DOC_STRINGS["wrap"])
|
45
78
|
end,
|
46
79
|
'subtree' => OptionParser.new do |opts|
|
47
|
-
opts.banner = "Usage: #{
|
80
|
+
opts.banner = "Usage: #{zero} subtree SHARD_ID"
|
81
|
+
separators(opts, DOC_STRINGS["subtree"])
|
82
|
+
end,
|
83
|
+
'hosts' => OptionParser.new do |opts|
|
84
|
+
opts.banner = "Usage: #{zero} hosts"
|
85
|
+
separators(opts, DOC_STRINGS["hosts"])
|
86
|
+
end,
|
87
|
+
'deleteforwarding' => OptionParser.new do |opts|
|
88
|
+
opts.banner = "Usage: #{zero} deleteforwarding TABLE_ID BASE_ID SHARD_ID"
|
89
|
+
separators(opts, DOC_STRINGS["deleteforwarding"])
|
48
90
|
end,
|
49
91
|
'delete' => OptionParser.new do |opts|
|
50
|
-
opts.banner = "Usage: #{
|
92
|
+
opts.banner = "Usage: #{zero} delete SHARD_ID_TO_DELETE [MORE SHARD_IDS]"
|
93
|
+
separators(opts, DOC_STRINGS["delete"])
|
51
94
|
end,
|
52
95
|
'addforwarding' => OptionParser.new do |opts|
|
53
|
-
opts.banner = "Usage: #{
|
96
|
+
opts.banner = "Usage: #{zero} addforwarding TABLE_ID BASE_ID SHARD_ID"
|
97
|
+
separators(opts, DOC_STRINGS["addforwarding"])
|
54
98
|
end,
|
55
99
|
'forwardings' => OptionParser.new do |opts|
|
56
|
-
opts.banner = "Usage: #{
|
100
|
+
opts.banner = "Usage: #{zero} show [options]"
|
101
|
+
separators(opts, DOC_STRINGS["forwardings"])
|
57
102
|
|
58
103
|
opts.on("-t", "--tables=IDS", "Show only the specified table ids (comma separated)") do |table_ids|
|
59
104
|
subcommand_options.table_ids ||= []
|
@@ -61,10 +106,12 @@ subcommands = {
|
|
61
106
|
end
|
62
107
|
end,
|
63
108
|
'unwrap' => OptionParser.new do |opts|
|
64
|
-
opts.banner = "Usage: #{
|
109
|
+
opts.banner = "Usage: #{zero} unwrap SHARD_ID_TO_REMOVE [MORE SHARD_IDS]"
|
110
|
+
separators(opts, DOC_STRINGS["unwrap"])
|
65
111
|
end,
|
66
112
|
'find' => OptionParser.new do |opts|
|
67
|
-
opts.banner = "Usage: #{
|
113
|
+
opts.banner = "Usage: #{zero} find [options]"
|
114
|
+
separators(opts, DOC_STRINGS["find"])
|
68
115
|
|
69
116
|
opts.on("-t", "--type=TYPE", "Return only shards of the specified TYPE") do |shard_type|
|
70
117
|
subcommand_options.shard_type = shard_type
|
@@ -75,37 +122,82 @@ subcommands = {
|
|
75
122
|
end
|
76
123
|
end,
|
77
124
|
'links' => OptionParser.new do |opts|
|
78
|
-
opts.banner = "Usage: #{
|
125
|
+
opts.banner = "Usage: #{zero} links SHARD_ID [MORE SHARD_IDS...]"
|
126
|
+
separators(opts, DOC_STRINGS["links"])
|
79
127
|
end,
|
80
128
|
'info' => OptionParser.new do |opts|
|
81
|
-
opts.banner = "Usage: #{
|
129
|
+
opts.banner = "Usage: #{zero} info SHARD_ID [MORE SHARD_IDS...]"
|
130
|
+
separators(opts, DOC_STRINGS["info"])
|
82
131
|
end,
|
83
132
|
'reload' => OptionParser.new do |opts|
|
84
|
-
opts.banner = "Usage: #{
|
133
|
+
opts.banner = "Usage: #{zero} reload"
|
134
|
+
separators(opts, DOC_STRINGS["reload"])
|
85
135
|
end,
|
86
136
|
'addlink' => OptionParser.new do |opts|
|
87
|
-
opts.banner = "Usage: #{
|
137
|
+
opts.banner = "Usage: #{zero} link PARENT_SHARD_ID CHILD_SHARD_ID WEIGHT"
|
138
|
+
separators(opts, DOC_STRINGS["addlink"])
|
88
139
|
end,
|
89
140
|
'unlink' => OptionParser.new do |opts|
|
90
|
-
opts.banner = "Usage: #{
|
141
|
+
opts.banner = "Usage: #{zero} unlink PARENT_SHARD_ID CHILD_SHARD_ID"
|
142
|
+
separators(opts, DOC_STRINGS["unlink"])
|
91
143
|
end,
|
92
144
|
'lookup' => OptionParser.new do |opts|
|
93
|
-
opts.banner = "Usage: #{
|
145
|
+
opts.banner = "Usage: #{zero} lookup TABLE_ID SOURCE_ID"
|
146
|
+
separators(opts, DOC_STRINGS["lookup"])
|
147
|
+
end,
|
148
|
+
'copy' => OptionParser.new do |opts|
|
149
|
+
opts.banner = "Usage: #{zero} copy SOURCE_SHARD_ID DESTINATION_SHARD_ID"
|
150
|
+
separators(opts, DOC_STRINGS["copy"])
|
151
|
+
end,
|
152
|
+
'busy' => OptionParser.new do |opts|
|
153
|
+
opts.banner = "Usage: #{zero} busy"
|
154
|
+
separators(opts, DOC_STRINGS["busy"])
|
155
|
+
end,
|
156
|
+
'setup-migrate' => OptionParser.new do |opts|
|
157
|
+
opts.banner = "Usage: #{zero} setup-migrate SOURCE_SHARD_ID DESTINATION_SHARD_ID"
|
158
|
+
separators(opts, DOC_STRINGS["setup-migrate"])
|
159
|
+
end,
|
160
|
+
'finish-migrate' => OptionParser.new do |opts|
|
161
|
+
opts.banner = "Usage: #{zero} finish-migrate SOURCE_SHARD_ID DESTINATION_SHARD_ID"
|
162
|
+
separators(opts, DOC_STRINGS["finish-migrate"])
|
163
|
+
end,
|
164
|
+
'inject' => OptionParser.new do |opts|
|
165
|
+
opts.banner = "Usage: #{zero} inject PRIORITY JOBS..."
|
166
|
+
separators(opts, DOC_STRINGS["inject"])
|
94
167
|
end
|
95
168
|
}
|
96
169
|
|
97
170
|
global = OptionParser.new do |opts|
|
98
|
-
opts.banner = "Usage: #{
|
171
|
+
opts.banner = "Usage: #{zero} [global-options] SUBCOMMAND [subcommand-options]"
|
172
|
+
opts.separator ""
|
173
|
+
opts.separator "Gizzmo is a tool for manipulating the forwardings and replication structure of"
|
174
|
+
opts.separator "Gizzard-based datastores. It can also perform bulk job operations."
|
175
|
+
opts.separator ""
|
176
|
+
opts.separator "You can type `#{zero} help SUBCOMMAND` for help on a specific subcommand. It's"
|
177
|
+
opts.separator "also useful to remember that global options come *before* the subcommand, while"
|
178
|
+
opts.separator "subcommand options come *after* the subcommand."
|
179
|
+
opts.separator ""
|
180
|
+
opts.separator "You may find it useful to create a ~/.gizzmorc file, which is simply YAML"
|
181
|
+
opts.separator "key/value pairs corresponding to options you want by default. A common .gizzmorc"
|
182
|
+
opts.separator "simply contain:"
|
183
|
+
opts.separator ""
|
184
|
+
opts.separator " host: localhost"
|
185
|
+
opts.separator " port: 7917"
|
99
186
|
opts.separator ""
|
100
187
|
opts.separator "Subcommands:"
|
101
188
|
subcommands.keys.compact.sort.each do |sc|
|
102
|
-
|
189
|
+
base = " #{sc}"
|
190
|
+
if doc = DOC_STRINGS[sc]
|
191
|
+
base += " " * (20 - base.length)
|
192
|
+
base += " -- "
|
193
|
+
base += doc[0..(76 - base.length)]
|
194
|
+
base += "..."
|
195
|
+
end
|
196
|
+
opts.separator base
|
103
197
|
end
|
104
198
|
opts.separator ""
|
105
|
-
opts.separator "You can type `#{$0} help SUBCOMMAND` for help on a specific subcommand."
|
106
199
|
opts.separator ""
|
107
200
|
opts.separator "Global options:"
|
108
|
-
|
109
201
|
opts.on("-H", "--host=HOSTNAME", "HOSTNAME of remote thrift service") do |host|
|
110
202
|
global_options.host = host
|
111
203
|
end
|
@@ -139,7 +231,7 @@ global = OptionParser.new do |opts|
|
|
139
231
|
opts.on("-f", "--force", "Don't display confirmation dialogs") do |force|
|
140
232
|
global_options.force = force
|
141
233
|
end
|
142
|
-
|
234
|
+
|
143
235
|
opts.on_tail("-v", "--version", "Show version") do
|
144
236
|
puts GIZZMO_VERSION
|
145
237
|
exit
|
@@ -182,14 +274,13 @@ unless subcommands.include?(subcommand_name)
|
|
182
274
|
end
|
183
275
|
|
184
276
|
log = global_options.log || "./gizzmo.log"
|
185
|
-
service = Gizzard::Thrift::ShardManager.new(global_options.host, global_options.port, log, global_options.dry)
|
186
277
|
|
187
278
|
while !$stdin.tty? && line = STDIN.gets
|
188
279
|
argv << line.strip
|
189
280
|
end
|
190
281
|
|
191
282
|
begin
|
192
|
-
Gizzard::Command.run(subcommand_name,
|
283
|
+
Gizzard::Command.run(subcommand_name, global_options, argv, subcommand_options, log)
|
193
284
|
rescue HelpNeededError => e
|
194
285
|
if e.class.name != e.message
|
195
286
|
STDERR.puts("=" * 80)
|
@@ -198,7 +289,7 @@ rescue HelpNeededError => e
|
|
198
289
|
end
|
199
290
|
STDERR.puts subcommands[subcommand_name]
|
200
291
|
exit 1
|
201
|
-
rescue ThriftClient::Simple::ThriftException, Gizzard::Thrift::ShardException => e
|
292
|
+
rescue ThriftClient::Simple::ThriftException, Gizzard::Thrift::ShardException, Errno::ECONNREFUSED => e
|
202
293
|
STDERR.puts e.message
|
203
294
|
exit 1
|
204
295
|
rescue Errno::EPIPE
|
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
|
+
- 4
|
8
|
+
- 1
|
9
|
+
version: 0.4.1
|
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-07-
|
17
|
+
date: 2010-07-29 00:00:00 -07:00
|
18
18
|
default_executable: gizzmo
|
19
19
|
dependencies: []
|
20
20
|
|