gizzmo 0.3.5 → 0.4.1
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/.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
|
|