gizzmo 0.11.4 → 0.12.0

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 CHANGED
@@ -1 +1 @@
1
- 0.11.4
1
+ 0.12.0
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.11.4"
8
+ s.version = "0.12.0"
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{2011-04-19}
12
+ s.date = %q{2011-05-05}
13
13
  s.description = %q{Gizzmo is a command-line client for managing gizzard clusters.}
14
14
  s.email = %q{kmaxwell@twitter.com}
15
15
  s.executables = ["gizzmo", "setup_shards"]
@@ -892,4 +892,110 @@ module Gizzard
892
892
  scheduler_options
893
893
  end
894
894
  end
895
+
896
+
897
+ class CreateTableCommand < Command
898
+
899
+ DEFAULT_NUM_SHARDS = 1024
900
+ DEFAULT_BASE_NAME = "shard"
901
+
902
+ FORWARDING_SPACE = 2 ** 60
903
+ FORWARDING_SPACE_MIN = 0
904
+ FORWARDING_SPACE_MAX = 2 ** 60 - 1
905
+
906
+ def generate_base_ids(num_shards, min_id, max_id)
907
+ srand(42) # consistent randomization
908
+
909
+ id_space = max_id - min_id + 1
910
+ step_size = id_space / num_shards
911
+
912
+ enums = (0...num_shards).to_a
913
+ ids = enums.map {|i| min_id + (i * step_size) }.sort_by { rand }
914
+
915
+ enums.zip(ids)
916
+ end
917
+
918
+ def parse_templates_and_weights(arr)
919
+ templates_and_weights = {}
920
+
921
+ arr.each_slice(2) do |(weight_s, to_template_s)|
922
+ to = ShardTemplate.parse(to_template_s)
923
+ weight = weight_s.to_i
924
+
925
+ templates_and_weights[to] = weight
926
+ end
927
+
928
+ templates_and_weights
929
+ end
930
+
931
+ # This is all super hacky but I don't have time to generalize right now
932
+
933
+ def run
934
+ help!("must have an even number of arguments") unless @argv.length % 2 == 0
935
+
936
+ base_name = command_options.base_name || DEFAULT_BASE_NAME
937
+ num_shards = (command_options.shards || DEFAULT_NUM_SHARDS).to_i
938
+ max_id = (command_options.max_id || FORWARDING_SPACE_MAX).to_i
939
+ min_id = (command_options.min_id || FORWARDING_SPACE_MIN).to_i
940
+
941
+ be_quiet = global_options.force && command_options.quiet
942
+
943
+ templates_and_weights = parse_templates_and_weights(@argv)
944
+ total_weight = templates_and_weights.values.inject {|a,b| a + b }
945
+ templates = templates_and_weights.keys
946
+
947
+ base_ids = generate_base_ids(num_shards, min_id, max_id)
948
+
949
+ templates_and_base_ids = templates_and_weights.inject({}) do |h, (template, weight)|
950
+ share = (weight.to_f / total_weight * num_shards).floor
951
+ ids = []
952
+ share.times { ids << base_ids.pop }
953
+
954
+ h.update template => ids
955
+ end
956
+
957
+ # divvy up the remainder across all templates.
958
+ base_ids.each_with_index do |base, idx|
959
+ templates_and_base_ids.values[idx % templates_and_base_ids.length] << base
960
+ end
961
+
962
+ proto = templates.first
963
+ transform = Transformation.new(proto, proto)
964
+
965
+ op_sets = templates.inject({}) do |h, template|
966
+ ops = transform.create_tree(template).sort
967
+ h.update template => ops
968
+ end
969
+
970
+ unless be_quiet
971
+ puts "Create tables #{global_options.tables.join(", ")}:"
972
+ templates_and_base_ids.each do |template, base_ids|
973
+ puts " #{template.inspect}"
974
+ puts " for #{base_ids.length} base ids:"
975
+ base_ids.each {|(enum, base_id)| puts " #{base_id}" }
976
+ end
977
+ puts ""
978
+ end
979
+
980
+ unless global_options.force
981
+ print "Continue? (y/n) "; $stdout.flush
982
+ exit unless $stdin.gets.chomp == "y"
983
+ puts ""
984
+ end
985
+
986
+ global_options.tables.each do |table_id|
987
+ templates_and_base_ids.each do |template, base_ids|
988
+ ops = op_sets[template]
989
+
990
+ base_ids.each do |(enum, base_id)|
991
+ table_prefix = Shard.canonical_table_prefix(enum, table_id, base_name)
992
+ ops.each do |op|
993
+ puts "#{op.inspect}: #{table_prefix}"
994
+ op.apply(manager, table_id, base_id, table_prefix, {})
995
+ end
996
+ end
997
+ end
998
+ end
999
+ end
1000
+ end
895
1001
  end
@@ -87,7 +87,7 @@ module Gizzard
87
87
  include ParallelMap
88
88
 
89
89
  DEFAULT_PORT = 7917
90
- DEFAULT_RETRIES = 20
90
+ DEFAULT_RETRIES = 10
91
91
  PARALLELISM = 10
92
92
 
93
93
  attr_reader :hosts, :logfile, :dryrun, :framed
@@ -175,9 +175,8 @@ module Gizzard
175
175
  times ||= @retries
176
176
  yield
177
177
  rescue Exception => e
178
- puts "retrying #{e.inspect} ..."
179
- #times -= 1
180
- (times < 0) ? raise : (sleep 2; retry)
178
+ times -= 1
179
+ (times < 0) ? raise : (sleep 0.1; retry)
181
180
  end
182
181
 
183
182
  class Manifest
@@ -126,7 +126,13 @@ module Gizzard
126
126
  def shared_host?(other)
127
127
  raise ArgumentError, "other is not a ShardTemplate" unless other.is_a? ShardTemplate
128
128
 
129
- (self.concrete_descendants & other.concrete_descendants).length > 0
129
+ self.concrete_descendants.each do |s|
130
+ other.concrete_descendants.each do |o|
131
+ return true if s.shard_eql? o
132
+ end
133
+ end
134
+
135
+ false
130
136
  end
131
137
 
132
138
  def hash
@@ -147,8 +147,9 @@ module Gizzard
147
147
 
148
148
  def copies_required?
149
149
  return @copies_required unless @copies_required.nil?
150
+
150
151
  @copies_required = !from.nil? &&
151
- to.concrete_descendants.reject {|d| from.shared_host? d }.length > 0
152
+ to.concrete_descendants.select {|d| !from.shared_host? d }.length > 0
152
153
  end
153
154
 
154
155
  def involved_in_copy?(template)
data/lib/gizzmo.rb CHANGED
@@ -345,6 +345,30 @@ subcommands = {
345
345
  opts.on("-q", "--quiet", "Do not display transformation info (only valid with --force)") do
346
346
  subcommand_options.quiet = true
347
347
  end
348
+ end,
349
+ 'create-table' => OptionParser.new do |opts|
350
+ opts.banner = "Usage: #{zero} create-table [options] WEIGHT TEMPLATE ..."
351
+ separators(opts, DOC_STRINGS["create-table"])
352
+
353
+ opts.on("--shards=COUNT", "Create COUNT shards for each table.") do |count|
354
+ subcommand_options.shards = count.to_i
355
+ end
356
+
357
+ opts.on("--min-id=NUM", "Set lower bound on the id space to NUM (default min signed long: -1 * 2^63)") do |min_id|
358
+ subcommand_options.min_id = min_id.to_i
359
+ end
360
+
361
+ opts.on("--max-id=NUM", "Set upper bound on the id space to NUM (default max signed long: 2^63 - 1)") do |max_id|
362
+ subcommand_options.max_id = max_id.to_i
363
+ end
364
+
365
+ opts.on("--base-name=NAME", "Use NAME as the base prefix for each shard's table prefix (default 'shard')") do |base_name|
366
+ subcommand_options.base_name = base_name
367
+ end
368
+
369
+ opts.on("-q", "--quiet", "Do not display table creation info (only valid with --force)") do
370
+ subcommand_options.quiet = true
371
+ end
348
372
  end
349
373
  }
350
374
 
@@ -388,12 +412,6 @@ global = OptionParser.new do |opts|
388
412
  global_options.hosts = hosts.split(",").map {|h| h.strip }
389
413
  end
390
414
 
391
- opts.on("-H", "--host=HOST", "HOST of application servers") do |hosts|
392
- global_options.hosts = hosts.split(",").map {|h| h.strip }
393
- end
394
-
395
-
396
-
397
415
  opts.on("-P", "--port=PORT", "PORT of remote manager service. default 7920") do |port|
398
416
  global_options.port = port.to_i
399
417
  end
data/test/gizzmo_spec.rb CHANGED
@@ -440,6 +440,38 @@ FINISHING:
440
440
  link(id("localhost", "s_0_002_replicating"), id("localhost", "s_0_002_a"), 1)]
441
441
  end
442
442
 
443
+ it "properly re-weights shards" do
444
+ 1.upto(2) do |i|
445
+ gizzmo "create TestShard -s Int -d Int localhost/s_0_00#{i}_a"
446
+ gizzmo "create ReplicatingShard localhost/s_0_00#{i}_replicating"
447
+ gizzmo "addlink localhost/s_0_00#{i}_replicating localhost/s_0_00#{i}_a 1"
448
+ gizzmo "addforwarding 0 #{i} localhost/s_0_00#{i}_replicating"
449
+ end
450
+ gizzmo "-f reload"
451
+
452
+ gizzmo('-f -T0 transform --no-progress --poll-interval=1 --max-copies=1 \
453
+ "ReplicatingShard -> TestShard(localhost,1,Int,Int)" \
454
+ "ReplicatingShard -> TestShard(localhost,3,Int,Int)"').should == <<-EOF
455
+ ReplicatingShard(1) -> TestShard(localhost,1,Int,Int) => ReplicatingShard(1) -> TestShard(localhost,3,Int,Int) :
456
+ PREPARE
457
+ add_link(ReplicatingShard -> TestShard/localhost)
458
+ remove_link(ReplicatingShard -> TestShard/localhost)
459
+ Applied to 2 shards:
460
+ [0] 1 = localhost/s_0_001_replicating
461
+ [0] 2 = localhost/s_0_002_replicating
462
+
463
+ STARTING:
464
+ [0] 2 = localhost/s_0_002_replicating: ReplicatingShard(1) -> TestShard(localhost,1,Int,Int) => ReplicatingShard(1) -> TestShard(localhost,3,Int,Int)
465
+ FINISHING:
466
+ [0] 2 = localhost/s_0_002_replicating: ReplicatingShard(1) -> TestShard(localhost,1,Int,Int) => ReplicatingShard(1) -> TestShard(localhost,3,Int,Int)
467
+ STARTING:
468
+ [0] 1 = localhost/s_0_001_replicating: ReplicatingShard(1) -> TestShard(localhost,1,Int,Int) => ReplicatingShard(1) -> TestShard(localhost,3,Int,Int)
469
+ FINISHING:
470
+ [0] 1 = localhost/s_0_001_replicating: ReplicatingShard(1) -> TestShard(localhost,1,Int,Int) => ReplicatingShard(1) -> TestShard(localhost,3,Int,Int)
471
+ 2 transformations applied. Total time elapsed: 2 seconds
472
+ EOF
473
+ end
474
+
443
475
  it "works with multiple pages" do
444
476
  1.upto(2) do |i|
445
477
  gizzmo "create TestShard -s Int -d Int localhost/s_0_00#{i}_a"
@@ -625,4 +657,91 @@ FINISHING:
625
657
  EOF
626
658
  end
627
659
  end
660
+
661
+ describe "create-table" do
662
+ it "works" do
663
+ gizzmo('-f -T0,1 create-table --shards=4 --base-name=s \
664
+ 1 "ReplicatingShard -> TestShard(127.0.0.1,1)" \
665
+ 1 "ReplicatingShard -> TestShard(localhost,1)"').should match(Regexp.new(Regexp.escape(<<-EOF).gsub("X", "\\d")))
666
+ Create tables 0, 1:
667
+ ReplicatingShard(1) -> TestShard(127.0.0.1,1)
668
+ for 2 base ids:
669
+ 288230376151711744
670
+ 576460752303423488
671
+ ReplicatingShard(1) -> TestShard(localhost,1)
672
+ for 2 base ids:
673
+ 864691128455135232
674
+ 0
675
+
676
+ create_shard(ReplicatingShard): s_0_0003
677
+ create_shard(TestShard/127.0.0.1): s_0_0003
678
+ add_link(ReplicatingShard -> TestShard/127.0.0.1): s_0_0003
679
+ set_forwarding(ReplicatingShard): s_0_0003
680
+ create_shard(ReplicatingShard): s_0_0002
681
+ create_shard(TestShard/127.0.0.1): s_0_0002
682
+ add_link(ReplicatingShard -> TestShard/127.0.0.1): s_0_0002
683
+ set_forwarding(ReplicatingShard): s_0_0002
684
+ create_shard(ReplicatingShard): s_0_0001
685
+ create_shard(TestShard/localhost): s_0_0001
686
+ add_link(ReplicatingShard -> TestShard/localhost): s_0_0001
687
+ set_forwarding(ReplicatingShard): s_0_0001
688
+ create_shard(ReplicatingShard): s_0_0000
689
+ create_shard(TestShard/localhost): s_0_0000
690
+ add_link(ReplicatingShard -> TestShard/localhost): s_0_0000
691
+ set_forwarding(ReplicatingShard): s_0_0000
692
+ create_shard(ReplicatingShard): s_1_0003
693
+ create_shard(TestShard/127.0.0.1): s_1_0003
694
+ add_link(ReplicatingShard -> TestShard/127.0.0.1): s_1_0003
695
+ set_forwarding(ReplicatingShard): s_1_0003
696
+ create_shard(ReplicatingShard): s_1_0002
697
+ create_shard(TestShard/127.0.0.1): s_1_0002
698
+ add_link(ReplicatingShard -> TestShard/127.0.0.1): s_1_0002
699
+ set_forwarding(ReplicatingShard): s_1_0002
700
+ create_shard(ReplicatingShard): s_1_0001
701
+ create_shard(TestShard/localhost): s_1_0001
702
+ add_link(ReplicatingShard -> TestShard/localhost): s_1_0001
703
+ set_forwarding(ReplicatingShard): s_1_0001
704
+ create_shard(ReplicatingShard): s_1_0000
705
+ create_shard(TestShard/localhost): s_1_0000
706
+ add_link(ReplicatingShard -> TestShard/localhost): s_1_0000
707
+ set_forwarding(ReplicatingShard): s_1_0000
708
+ EOF
709
+
710
+ nameserver_db[:shards].should == [info("127.0.0.1", "s_0_0002", "TestShard"),
711
+ info("127.0.0.1", "s_0_0003", "TestShard"),
712
+ info("127.0.0.1", "s_1_0002", "TestShard"),
713
+ info("127.0.0.1", "s_1_0003", "TestShard"),
714
+ info("localhost", "s_0_0000", "TestShard"),
715
+ info("localhost", "s_0_0000_replicating", "ReplicatingShard"),
716
+ info("localhost", "s_0_0001", "TestShard"),
717
+ info("localhost", "s_0_0001_replicating", "ReplicatingShard"),
718
+ info("localhost", "s_0_0002_replicating", "ReplicatingShard"),
719
+ info("localhost", "s_0_0003_replicating", "ReplicatingShard"),
720
+ info("localhost", "s_1_0000", "TestShard"),
721
+ info("localhost", "s_1_0000_replicating", "ReplicatingShard"),
722
+ info("localhost", "s_1_0001", "TestShard"),
723
+ info("localhost", "s_1_0001_replicating", "ReplicatingShard"),
724
+ info("localhost", "s_1_0002_replicating", "ReplicatingShard"),
725
+ info("localhost", "s_1_0003_replicating", "ReplicatingShard")]
726
+
727
+ nameserver_db[:links].should == [link(id("localhost", "s_0_0000_replicating"), id("localhost", "s_0_0000"), 1),
728
+ link(id("localhost", "s_0_0001_replicating"), id("localhost", "s_0_0001"), 1),
729
+ link(id("localhost", "s_0_0002_replicating"), id("127.0.0.1", "s_0_0002"), 1),
730
+ link(id("localhost", "s_0_0003_replicating"), id("127.0.0.1", "s_0_0003"), 1),
731
+ link(id("localhost", "s_1_0000_replicating"), id("localhost", "s_1_0000"), 1),
732
+ link(id("localhost", "s_1_0001_replicating"), id("localhost", "s_1_0001"), 1),
733
+ link(id("localhost", "s_1_0002_replicating"), id("127.0.0.1", "s_1_0002"), 1),
734
+ link(id("localhost", "s_1_0003_replicating"), id("127.0.0.1", "s_1_0003"), 1)]
735
+
736
+ nameserver_db[:forwardings].should == [forwarding(0, 0, id("localhost", "s_0_0000_replicating")),
737
+ forwarding(1, 0, id("localhost", "s_1_0000_replicating")),
738
+ forwarding(0, 288230376151711744, id("localhost", "s_0_0003_replicating")),
739
+ forwarding(1, 288230376151711744, id("localhost", "s_1_0003_replicating")),
740
+ forwarding(0, 576460752303423488, id("localhost", "s_0_0002_replicating")),
741
+ forwarding(1, 576460752303423488, id("localhost", "s_1_0002_replicating")),
742
+ forwarding(0, 864691128455135232, id("localhost", "s_0_0001_replicating")),
743
+ forwarding(1, 864691128455135232, id("localhost", "s_1_0001_replicating"))]
744
+
745
+ end
746
+ end
628
747
  end
data/test/spec_helper.rb CHANGED
@@ -130,7 +130,7 @@ def as_link(h)
130
130
  end
131
131
 
132
132
  def as_forwarding(h)
133
- Gizzard::Forwarding.new(h['table_id'].to_i, h['base_id'].to_i, as_shard_id(h, 'shard'))
133
+ Gizzard::Forwarding.new(h['table_id'].to_i, h['base_source_id'].to_i, as_shard_id(h, 'shard'))
134
134
  end
135
135
 
136
136
  def as_host(h)
@@ -144,14 +144,14 @@ def gizzmo(cmd)
144
144
  end
145
145
 
146
146
  def nameserver
147
- @nameserver ||= Gizzard::Nameserver.new('localhost:' + MANAGER_PORT.to_s)
147
+ @nameserver ||= Gizzard::Nameserver.new('localhost:' + MANAGER_PORT.to_s, :retries => 5)
148
148
  end
149
149
 
150
150
  alias ns nameserver
151
151
 
152
152
  # setup
153
153
 
154
- mysql_connect!("localhost", '', '')
154
+ mysql_connect!("localhost", 'root', '')
155
155
  reset_databases!
156
156
 
157
157
  unless ENV['EXTERNAL_TEST_SERVER']
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gizzmo
3
3
  version: !ruby/object:Gem::Version
4
- hash: 59
4
+ hash: 47
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 11
9
- - 4
10
- version: 0.11.4
8
+ - 12
9
+ - 0
10
+ version: 0.12.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kyle Maxwell
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-19 00:00:00 -07:00
18
+ date: 2011-05-05 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies: []
21
21