lib/gizzmo.rb in gizzmo-0.3.5 vs lib/gizzmo.rb in gizzmo-0.4.1
- old
+ new
@@ -4,11 +4,18 @@
require "optparse"
require "ostruct"
require "gizzard"
require "yaml"
+DOC_STRINGS = {
+ "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.",
+ "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.",
+ "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."
+}
+
ORIGINAL_ARGV = ARGV.dup
+zero = File.basename($0)
# Container for parsed options
global_options = OpenStruct.new
global_options.render = []
subcommand_options = OpenStruct.new
@@ -26,88 +33,173 @@
# Do nothing...
rescue => e
abort "Unknown error loading ~/.gizzmorc: #{e.message}"
end
+def split(string)
+ return [] unless string
+ a = []
+ tokens = string.split(/\s+/)
+ a << tokens.shift
+ tokens.each do |token|
+ s = a.last
+ if s.length + token.length + 1 < 80
+ s << " #{token}"
+ else
+ a << token
+ end
+ end
+ a
+end
+
+def separators(opts, string)
+ opts.separator("")
+ split(string).each do |substr|
+ opts.separator(substr)
+ end
+ opts.separator("")
+end
+
subcommands = {
'create' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} create [options] HOST TABLE_PREFIX CLASS_NAME"
-
+ opts.banner = "Usage: #{zero} create [options] CLASS_NAME SHARD_ID [MORE SHARD_IDS...]"
+ separators(opts, DOC_STRINGS["create"])
+
opts.on("-s", "--source-type=TYPE") do |s|
subcommand_options.source_type = s
end
opts.on("-d", "--destination-type=TYPE") do |s|
subcommand_options.destination_type = s
end
end,
'wrap' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} wrap CLASS_NAME SHARD_ID_TO_WRAP [MORE SHARD_IDS...]"
+ opts.banner = "Usage: #{zero} wrap CLASS_NAME SHARD_ID_TO_WRAP [MORE SHARD_IDS...]"
+ separators(opts, DOC_STRINGS["wrap"])
end,
'subtree' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} subtree SHARD_ID"
+ opts.banner = "Usage: #{zero} subtree SHARD_ID"
+ separators(opts, DOC_STRINGS["subtree"])
end,
+ 'hosts' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} hosts"
+ separators(opts, DOC_STRINGS["hosts"])
+ end,
+ 'deleteforwarding' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} deleteforwarding TABLE_ID BASE_ID SHARD_ID"
+ separators(opts, DOC_STRINGS["deleteforwarding"])
+ end,
'delete' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} delete SHARD_ID_TO_DELETE [MORE SHARD_IDS]"
+ opts.banner = "Usage: #{zero} delete SHARD_ID_TO_DELETE [MORE SHARD_IDS]"
+ separators(opts, DOC_STRINGS["delete"])
end,
'addforwarding' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} addforwarding TABLE_ID BASE_ID SHARD_ID"
+ opts.banner = "Usage: #{zero} addforwarding TABLE_ID BASE_ID SHARD_ID"
+ separators(opts, DOC_STRINGS["addforwarding"])
end,
'forwardings' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} show [options]"
+ opts.banner = "Usage: #{zero} show [options]"
+ separators(opts, DOC_STRINGS["forwardings"])
opts.on("-t", "--tables=IDS", "Show only the specified table ids (comma separated)") do |table_ids|
subcommand_options.table_ids ||= []
subcommand_options.table_ids += table_ids.split(",").map { |s| s.to_i }
end
end,
'unwrap' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} unwrap SHARD_ID_TO_REMOVE [MORE SHARD_IDS]"
+ opts.banner = "Usage: #{zero} unwrap SHARD_ID_TO_REMOVE [MORE SHARD_IDS]"
+ separators(opts, DOC_STRINGS["unwrap"])
end,
'find' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} find [options]"
+ opts.banner = "Usage: #{zero} find [options]"
+ separators(opts, DOC_STRINGS["find"])
opts.on("-t", "--type=TYPE", "Return only shards of the specified TYPE") do |shard_type|
subcommand_options.shard_type = shard_type
end
opts.on("-H", "--host=HOST", "HOST of shard") do |shard_host|
subcommand_options.shard_host = shard_host
end
end,
'links' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} links SHARD_ID [MORE SHARD_IDS...]"
+ opts.banner = "Usage: #{zero} links SHARD_ID [MORE SHARD_IDS...]"
+ separators(opts, DOC_STRINGS["links"])
end,
'info' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} info SHARD_ID [MORE SHARD_IDS...]"
+ opts.banner = "Usage: #{zero} info SHARD_ID [MORE SHARD_IDS...]"
+ separators(opts, DOC_STRINGS["info"])
end,
'reload' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} reload"
+ opts.banner = "Usage: #{zero} reload"
+ separators(opts, DOC_STRINGS["reload"])
end,
'addlink' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} link PARENT_SHARD_ID CHILD_SHARD_ID WEIGHT"
+ opts.banner = "Usage: #{zero} link PARENT_SHARD_ID CHILD_SHARD_ID WEIGHT"
+ separators(opts, DOC_STRINGS["addlink"])
end,
'unlink' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} unlink PARENT_SHARD_ID CHILD_SHARD_ID"
+ opts.banner = "Usage: #{zero} unlink PARENT_SHARD_ID CHILD_SHARD_ID"
+ separators(opts, DOC_STRINGS["unlink"])
end,
'lookup' => OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} lookup TABLE_ID SOURCE_ID"
+ opts.banner = "Usage: #{zero} lookup TABLE_ID SOURCE_ID"
+ separators(opts, DOC_STRINGS["lookup"])
+ end,
+ 'copy' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} copy SOURCE_SHARD_ID DESTINATION_SHARD_ID"
+ separators(opts, DOC_STRINGS["copy"])
+ end,
+ 'busy' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} busy"
+ separators(opts, DOC_STRINGS["busy"])
+ end,
+ 'setup-migrate' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} setup-migrate SOURCE_SHARD_ID DESTINATION_SHARD_ID"
+ separators(opts, DOC_STRINGS["setup-migrate"])
+ end,
+ 'finish-migrate' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} finish-migrate SOURCE_SHARD_ID DESTINATION_SHARD_ID"
+ separators(opts, DOC_STRINGS["finish-migrate"])
+ end,
+ 'inject' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} inject PRIORITY JOBS..."
+ separators(opts, DOC_STRINGS["inject"])
end
}
global = OptionParser.new do |opts|
- opts.banner = "Usage: #{$0} [global-options] SUBCOMMAND [subcommand-options]"
+ opts.banner = "Usage: #{zero} [global-options] SUBCOMMAND [subcommand-options]"
opts.separator ""
+ opts.separator "Gizzmo is a tool for manipulating the forwardings and replication structure of"
+ opts.separator "Gizzard-based datastores. It can also perform bulk job operations."
+ opts.separator ""
+ opts.separator "You can type `#{zero} help SUBCOMMAND` for help on a specific subcommand. It's"
+ opts.separator "also useful to remember that global options come *before* the subcommand, while"
+ opts.separator "subcommand options come *after* the subcommand."
+ opts.separator ""
+ opts.separator "You may find it useful to create a ~/.gizzmorc file, which is simply YAML"
+ opts.separator "key/value pairs corresponding to options you want by default. A common .gizzmorc"
+ opts.separator "simply contain:"
+ opts.separator ""
+ opts.separator " host: localhost"
+ opts.separator " port: 7917"
+ opts.separator ""
opts.separator "Subcommands:"
subcommands.keys.compact.sort.each do |sc|
- opts.separator " #{sc}"
+ base = " #{sc}"
+ if doc = DOC_STRINGS[sc]
+ base += " " * (20 - base.length)
+ base += " -- "
+ base += doc[0..(76 - base.length)]
+ base += "..."
+ end
+ opts.separator base
end
opts.separator ""
- opts.separator "You can type `#{$0} help SUBCOMMAND` for help on a specific subcommand."
opts.separator ""
opts.separator "Global options:"
-
opts.on("-H", "--host=HOSTNAME", "HOSTNAME of remote thrift service") do |host|
global_options.host = host
end
opts.on("-P", "--port=PORT", "PORT of remote thrift service") do |port|
@@ -137,11 +229,11 @@
end
opts.on("-f", "--force", "Don't display confirmation dialogs") do |force|
global_options.force = force
end
-
+
opts.on_tail("-v", "--version", "Show version") do
puts GIZZMO_VERSION
exit
end
end
@@ -180,26 +272,25 @@
STDERR.puts "Subcommand not found: #{subcommand_name}"
exit 1
end
log = global_options.log || "./gizzmo.log"
-service = Gizzard::Thrift::ShardManager.new(global_options.host, global_options.port, log, global_options.dry)
while !$stdin.tty? && line = STDIN.gets
argv << line.strip
end
begin
- Gizzard::Command.run(subcommand_name, service, global_options, argv, subcommand_options)
+ Gizzard::Command.run(subcommand_name, global_options, argv, subcommand_options, log)
rescue HelpNeededError => e
if e.class.name != e.message
STDERR.puts("=" * 80)
STDERR.puts e.message
STDERR.puts("=" * 80)
end
STDERR.puts subcommands[subcommand_name]
exit 1
-rescue ThriftClient::Simple::ThriftException, Gizzard::Thrift::ShardException => e
+rescue ThriftClient::Simple::ThriftException, Gizzard::Thrift::ShardException, Errno::ECONNREFUSED => e
STDERR.puts e.message
exit 1
rescue Errno::EPIPE
# This is just us trying to puts into a closed stdout. For example, if you pipe into
# head -1, then this script will keep running after head closes. We don't care, and
\ No newline at end of file