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 +1 -1
- data/gizzmo.gemspec +2 -2
- data/lib/gizzard/commands.rb +106 -0
- data/lib/gizzard/nameserver.rb +3 -4
- data/lib/gizzard/shard_template.rb +7 -1
- data/lib/gizzard/transformation.rb +2 -1
- data/lib/gizzmo.rb +24 -6
- data/test/gizzmo_spec.rb +119 -0
- data/test/spec_helper.rb +3 -3
- metadata +5 -5
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
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.
|
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-
|
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"]
|
data/lib/gizzard/commands.rb
CHANGED
@@ -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
|
data/lib/gizzard/nameserver.rb
CHANGED
@@ -87,7 +87,7 @@ module Gizzard
|
|
87
87
|
include ParallelMap
|
88
88
|
|
89
89
|
DEFAULT_PORT = 7917
|
90
|
-
DEFAULT_RETRIES =
|
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
|
-
|
179
|
-
|
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
|
-
|
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.
|
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['
|
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:
|
4
|
+
hash: 47
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
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-
|
18
|
+
date: 2011-05-05 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|