gizzmo 0.11.4 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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