lib/gizzmo.rb in gizzmo-0.11.0 vs lib/gizzmo.rb in gizzmo-0.11.1
- old
+ new
@@ -20,23 +20,26 @@
"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.",
"links" => "List parent & child links for shards.",
"lookup" => "Lookup the shard id that holds the record for a given table / source_id.",
"markbusy" => "Mark a shard as busy.",
"pair" => "Report the replica pairing structure for a list of hosts.",
- "reload" => "Instruct an appserver to reload its nameserver state.",
+ "reload" => "Instruct application servers to reload the nameserver state.",
"report" => "Show each unique replica structure for a given list of shards. Usually this shard list comes from << gizzmo forwardings | awk '{ print $3 }' >>.",
"setup-replica" => "Add a replica to be parallel to an existing replica, in write-only mode, ready to be copied to.",
"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.",
}
ORIGINAL_ARGV = ARGV.dup
zero = File.basename($0)
# Container for parsed options
-global_options = OpenStruct.new
-global_options.render = []
-global_options.framed = false
+global_options = OpenStruct.new
+global_options.port = 7920
+global_options.injector_port = 7921
+global_options.render = []
+global_options.framed = false
+
subcommand_options = OpenStruct.new
# Leftover arguments
argv = nil
@@ -76,14 +79,33 @@
opts.separator("")
end
def load_config(options, filename)
YAML.load(File.open(filename)).each do |k, v|
+ v = v.split(",").map {|h| h.strip } if k == "hosts"
options.send("#{k}=", v)
end
end
+def add_scheduler_opts(subcommand_options, opts)
+ opts.on("--max-copies=COUNT", "Limit max simultaneous copies to COUNT.") do |c|
+ (subcommand_options.scheduler_options ||= {})[:max_copies] = c.to_i
+ end
+ opts.on("--copies-per-host=COUNT", "Limit max copies per individual destination host to COUNT") do |c|
+ (subcommand_options.scheduler_options ||= {})[:copies_per_host] = c.to_i
+ end
+ opts.on("--poll-interval=SECONDS", "Sleep SECONDS between polling for copy status") do |c|
+ (subcommand_options.scheduler_options ||= {})[:poll_interval] = c.to_i
+ end
+ opts.on("--copy-wrapper=TYPE", "Wrap copy destination shards with TYPE. default WriteOnlyShard") do |t|
+ (subcommand_options.scheduler_options ||= {})[:copy_wrapper] = t
+ end
+ opts.on("--no-progress", "Do not show progress bar at bottom.") do
+ (subcommand_options.scheduler_options ||= {})[:no_progress] = true
+ end
+end
+
subcommands = {
'create' => OptionParser.new do |opts|
opts.banner = "Usage: #{zero} create [options] CLASS_NAME SHARD_ID [MORE SHARD_IDS...]"
separators(opts, DOC_STRINGS["create"])
@@ -104,11 +126,11 @@
separators(opts, DOC_STRINGS["rebalance"])
opts.on("-w", "--write-only=CLASS") do |w|
subcommand_options.write_only_shard = w
end
- opts.on("-h", "--hosts=list") do |h|
+ opts.on("-h", "--shard-hosts=list") do |h|
subcommand_options.hosts = h
end
opts.on("-x", "--exclude-hosts=list") do |x|
subcommand_options.exclude_hosts = x
end
@@ -147,14 +169,10 @@
end,
'addforwarding' => OptionParser.new do |opts|
opts.banner = "Usage: #{zero} addforwarding TABLE_ID BASE_ID SHARD_ID"
separators(opts, DOC_STRINGS["addforwarding"])
end,
- 'currentforwarding' => OptionParser.new do |opts|
- opts.banner = "Usage: #{zero} currentforwarding SOURCE_ID [ANOTHER_SOURCE_ID...]"
- separators(opts, DOC_STRINGS["addforwarding"])
- end,
'forwardings' => OptionParser.new do |opts|
opts.banner = "Usage: #{zero} forwardings [options]"
separators(opts, DOC_STRINGS["forwardings"])
opts.on("-t", "--tables=IDS", "Show only the specified table ids (comma separated)") do |table_ids|
@@ -175,11 +193,11 @@
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|
+ opts.on("-h", "--shard-host=HOST", "HOST of shard") do |shard_host|
subcommand_options.shard_host = shard_host
end
end,
'links' => OptionParser.new do |opts|
opts.banner = "Usage: #{zero} links SHARD_ID [MORE SHARD_IDS...]"
@@ -265,10 +283,50 @@
separators(opts, DOC_STRINGS["flush"])
opts.on("--all", "Flush all error queues.") do
subcommand_options.flush_all = true
end
+ end,
+ 'add-host' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} add-host HOSTS"
+ separators(opts, DOC_STRINGS["add-host"])
+ end,
+ 'remove-host' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} remove-host HOST"
+ separators(opts, DOC_STRINGS["remove-host"])
+ end,
+ 'list-hosts' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} list-hosts"
+ separators(opts, DOC_STRINGS["list-hosts"])
+ end,
+ 'topology' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} topology [options]"
+ separators(opts, DOC_STRINGS["topology"])
+
+ opts.on("--forwardings", "Show topology of forwardings instead of counts") do
+ subcommand_options.forwardings = true
+ end
+ end,
+ 'transform-tree' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} transform-tree [options] ROOT_SHARD_ID TEMPLATE"
+ separators(opts, DOC_STRINGS['transform-tree'])
+
+ add_scheduler_opts subcommand_options, opts
+
+ opts.on("-q", "--quiet", "Do not display transformation info (only valid with --force)") do
+ subcommand_options.quiet = true
+ end
+ end,
+ 'transform' => OptionParser.new do |opts|
+ opts.banner = "Usage: #{zero} transform [options] FROM_TEMPLATE TO_TEMPLATE"
+ separators(opts, DOC_STRINGS['transform'])
+
+ add_scheduler_opts subcommand_options, opts
+
+ opts.on("-q", "--quiet", "Do not display transformation info (only valid with --force)") do
+ subcommand_options.quiet = true
+ end
end
}
if ENV['GIZZMORC']
load_config(global_options, ENV['GIZZMORC'])
@@ -286,11 +344,11 @@
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 contains:"
opts.separator ""
- opts.separator " host: localhost"
+ opts.separator " hosts: localhost"
opts.separator " port: 7917"
opts.separator ""
opts.separator "Subcommands:"
subcommands.keys.compact.sort.each do |sc|
base = " #{sc}"
@@ -303,39 +361,47 @@
opts.separator base
end
opts.separator ""
opts.separator ""
opts.separator "Global options:"
- opts.on("-H", "--host=HOSTNAME", "HOSTNAME of remote thrift service") do |host|
- global_options.host = host
+ opts.on("-H", "--hosts=HOST[,HOST,...]", "HOSTS of application servers") do |hosts|
+ global_options.hosts = hosts.split(",").map {|h| h.strip }
end
- opts.on("-P", "--port=PORT", "PORT of remote thrift service") do |port|
+ opts.on("-P", "--port=PORT", "PORT of remote manager service. default 7920") do |port|
global_options.port = port.to_i
end
+ opts.on("-I", "--injector=PORT", "PORT of remote job injector service. default 7921") do |port|
+ global_options.injector_port = port.to_i
+ end
+
+ opts.on("-T", "--tables=TABLE[,TABLE,...]", "TABLE ids of forwardings to affect") do |tables|
+ global_options.tables = tables.split(",").map {|t| t.to_i }
+ end
+
opts.on("-F", "--framed", "use the thrift framed transport") do |framed|
global_options.framed = true
end
opts.on("-r", "--retry=TIMES", "TIMES to retry the command") do |r|
- global_options.retry = r
+ global_options.retry = r.to_i
end
opts.on("-t", "--timeout=SECONDS", "SECONDS to let the command run") do |r|
- global_options.timeout = r
+ global_options.timeout = r.to_i
end
opts.on("--subtree", "Render in subtree mode") do
global_options.render << "subtree"
end
opts.on("--info", "Render in info mode") do
global_options.render << "info"
end
- opts.on("-D", "--dry-run", "") do |port|
+ opts.on("-D", "--dry-run", "") do
global_options.dry = true
end
opts.on("-C", "--config=YAML_FILE", "YAML_FILE of option key/values") do |filename|
load_config(global_options, filename)
@@ -399,16 +465,16 @@
def custom_timeout(seconds)
if seconds
begin
require "rubygems"
require "system_timer"
- SystemTimer.timeout_after(seconds.to_i) do
+ SystemTimer.timeout_after(seconds) do
yield
end
rescue LoadError
require "timeout"
- Timeout.timeout(seconds.to_i) do
+ Timeout.timeout(seconds) do
yield
end
end
else
yield
@@ -425,11 +491,12 @@
STDERR.puts e.message
STDERR.puts("=" * 80)
end
STDERR.puts subcommands[subcommand_name]
exit 1
-rescue ThriftClient::Simple::ThriftException, Gizzard::Thrift::ShardException, Errno::ECONNREFUSED => e
+rescue ThriftClient::Simple::ThriftException, Gizzard::GizzardException, Errno::ECONNREFUSED => e
STDERR.puts e.message
+ STDERR.puts e.backtrace
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
# seeing the backtrace is annoying!