gizzmo 0.11.0 → 0.11.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +11 -16
- data/VERSION +1 -1
- data/bin/setup_shards +173 -0
- data/lib/gizzard.rb +4 -0
- data/lib/gizzard/commands.rb +286 -152
- data/lib/gizzard/migrator.rb +192 -0
- data/lib/gizzard/nameserver.rb +206 -0
- data/lib/gizzard/shard_template.rb +252 -0
- data/lib/gizzard/thrift.rb +187 -135
- data/lib/gizzard/transformation.rb +230 -0
- data/lib/gizzard/transformation_op.rb +181 -0
- data/lib/gizzard/transformation_scheduler.rb +220 -0
- data/lib/gizzmo.rb +87 -20
- data/test/gizzmo_spec.rb +499 -0
- data/test/nameserver_spec.rb +139 -0
- data/test/scheduler_spec.rb +59 -0
- data/test/shard_template_spec.rb +103 -0
- data/test/spec.opts +7 -0
- data/test/spec_helper.rb +139 -0
- data/test/test_server/.gitignore +13 -0
- data/test/test_server/project/build.properties +8 -0
- data/test/test_server/project/build/Project.scala +13 -0
- data/test/test_server/project/plugins/Plugins.scala +6 -0
- data/test/test_server/src/main/scala/Main.scala +18 -0
- data/test/test_server/src/main/scala/TestServer.scala +247 -0
- data/test/test_server/src/main/thrift/TestServer.thrift +12 -0
- data/test/transformation_spec.rb +181 -0
- metadata +32 -5
- data/gizzmo.gemspec +0 -75
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Gizzard::Shard do
|
4
|
+
describe "parse_enumeration" do
|
5
|
+
it "parses correctly" do
|
6
|
+
Gizzard::Shard.parse_enumeration("edges_backwards_1_003_a").should == 3
|
7
|
+
Gizzard::Shard.parse_enumeration("status_0345").should == 345
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "canonical_shard_id_map" do
|
12
|
+
it "returns a map of canonical to actual shard table prefixes" do
|
13
|
+
s = Gizzard::Shard.new(info("localhost", "t0_001_replicating", "ReplicatingShard"),
|
14
|
+
[Gizzard::Shard.new(info("localhost", "shard_0001", "SqlShard"), [], 1)],
|
15
|
+
1)
|
16
|
+
s.canonical_shard_id_map.should == {
|
17
|
+
id("localhost", "shard_0001_replicating") => id("localhost", "t0_001_replicating"),
|
18
|
+
id("localhost", "shard_0001") => id("localhost", "shard_0001")
|
19
|
+
}
|
20
|
+
|
21
|
+
s.canonical_shard_id_map("edges", -2).should == {
|
22
|
+
id("localhost", "edges_n2_0001_replicating") => id("localhost", "t0_001_replicating"),
|
23
|
+
id("localhost", "edges_n2_0001") => id("localhost", "shard_0001")
|
24
|
+
}
|
25
|
+
|
26
|
+
s.canonical_shard_id_map("groups", 0, 3).should == {
|
27
|
+
id("localhost", "groups_0_0003_replicating") => id("localhost", "t0_001_replicating"),
|
28
|
+
id("localhost", "groups_0_0003") => id("localhost", "shard_0001")
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Gizzard::Nameserver do
|
35
|
+
before do
|
36
|
+
@client = Object.new
|
37
|
+
@second_client = Object.new
|
38
|
+
@nameserver = Gizzard::Nameserver.new("localhost:1234", "localhost:4567")
|
39
|
+
stub(@nameserver).create_client(anything) do |host|
|
40
|
+
{ "localhost:1234" => @client, "localhost:4567" => @second_client }[host]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "initialize" do
|
45
|
+
it "takes a list of hosts and options" do
|
46
|
+
n = Gizzard::Nameserver.new("localhost:1234")
|
47
|
+
n.hosts.should == ["localhost:1234"]
|
48
|
+
|
49
|
+
n = Gizzard::Nameserver.new("localhost:1234", "localhost:4567", :dry_run => true)
|
50
|
+
n.hosts.should == ["localhost:1234", "localhost:4567"]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "takes a :dry_run option that defaults to false" do
|
54
|
+
n = Gizzard::Nameserver.new("localhost:1234", :dry_run => true)
|
55
|
+
n.dryrun.should == true
|
56
|
+
|
57
|
+
n = Gizzard::Nameserver.new("localhost:1234")
|
58
|
+
n.dryrun.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "takes a :log option that defaults to '/tmp/gizzmo.log'" do
|
62
|
+
n = Gizzard::Nameserver.new("localhost:1234", :log => "/path/to/logfile")
|
63
|
+
n.logfile.should == "/path/to/logfile"
|
64
|
+
|
65
|
+
n = Gizzard::Nameserver.new("localhost:1234")
|
66
|
+
n.logfile.should == "/tmp/gizzmo.log"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "get_all_links" do
|
71
|
+
it "works..."
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "get_all_shards" do
|
75
|
+
it "works..."
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "reload_config" do
|
79
|
+
it "reloads config on every app server" do
|
80
|
+
mock(@client).reload_config
|
81
|
+
mock(@second_client).reload_config
|
82
|
+
@nameserver.reload_config
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe Gizzard::Nameserver::Manifest do
|
88
|
+
before do
|
89
|
+
@shardinfos = [info("localhost", "tbl_001_rep", "ReplicatingShard", "", "", 0),
|
90
|
+
info("sqlhost", "tbl_001", "SqlShard", "int", "int", 0)]
|
91
|
+
|
92
|
+
@links = [link(id("localhost", "tbl_001_rep"), id("sqlhost", "tbl_001"), 1)]
|
93
|
+
|
94
|
+
@forwardings = [forwarding(0, 0, id("localhost", "tbl_001_rep"))]
|
95
|
+
|
96
|
+
@nameserver = Gizzard::Nameserver.new("localhost:1234")
|
97
|
+
@state = Object.new
|
98
|
+
|
99
|
+
mock(@nameserver).dump_nameserver(0) { @state }
|
100
|
+
mock(@state).forwardings { @forwardings }
|
101
|
+
mock(@state).links { @links }
|
102
|
+
mock(@state).shards { @shardinfos }
|
103
|
+
end
|
104
|
+
|
105
|
+
it "memoizes the forwardings list" do
|
106
|
+
@nameserver.manifest(0).forwardings.should == @forwardings
|
107
|
+
end
|
108
|
+
|
109
|
+
it "creates a links hash in the form of up_id => [[down_id, weight]]" do
|
110
|
+
@nameserver.manifest(0).links.should == {
|
111
|
+
id("localhost", "tbl_001_rep") => [[id("sqlhost", "tbl_001"), 1]]
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
it "creates a shard_infos hash in the form of shard_id => shard_info" do
|
116
|
+
@nameserver.manifest(0).shard_infos.should == {
|
117
|
+
id("localhost", "tbl_001_rep") => info("localhost", "tbl_001_rep", "ReplicatingShard", "", "", 0),
|
118
|
+
id("sqlhost", "tbl_001") => info("sqlhost", "tbl_001", "SqlShard", "int", "int", 0)
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "creates a trees hash in the form of forwarding => shard tree" do
|
123
|
+
child = Gizzard::Shard.new(info("sqlhost", "tbl_001", "SqlShard", "int", "int", 0), [], 1)
|
124
|
+
parent = Gizzard::Shard.new(info("localhost", "tbl_001_rep", "ReplicatingShard", "", "", 0), [child], 1)
|
125
|
+
|
126
|
+
@nameserver.manifest(0).trees.should == {
|
127
|
+
forwarding(0, 0, id("localhost", "tbl_001_rep")) => parent
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
it "creates a templates hash om the form of template => [forwarding]" do
|
132
|
+
child = Gizzard::ShardTemplate.new("SqlShard", "sqlhost", 1, "int", "int", [])
|
133
|
+
parent = Gizzard::ShardTemplate.new("ReplicatingShard", "localhost", 1, "", "", [child])
|
134
|
+
|
135
|
+
@nameserver.manifest(0).templates.should == {
|
136
|
+
parent => [forwarding(0, 0, id("localhost", "tbl_001_rep"))]
|
137
|
+
}
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Gizzard::Transformation::Scheduler do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@nameserver = stub!.subject
|
7
|
+
stub(@nameserver).dryrun? { false }
|
8
|
+
|
9
|
+
@transformations = {}
|
10
|
+
@scheduler = Gizzard::Transformation::Scheduler.new(@nameserver, 't', @transformations)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "busy_shards" do
|
14
|
+
it "memoizes" do
|
15
|
+
shards = [info('127.0.0.1', 't_0_0001', 'TestShard')]
|
16
|
+
mock(@nameserver).get_busy_shards { shards }
|
17
|
+
|
18
|
+
@scheduler.busy_shards.should == shards.map {|s| s.id }
|
19
|
+
@scheduler.busy_shards.should == shards.map {|s| s.id }
|
20
|
+
end
|
21
|
+
|
22
|
+
it "resets after calling reload_busy_shards" do
|
23
|
+
shards = [info('127.0.0.1', 't_0_0001', 'TestShard')]
|
24
|
+
mock(@nameserver).get_busy_shards { shards }.twice
|
25
|
+
|
26
|
+
@scheduler.busy_shards.should == shards.map {|s| s.id }
|
27
|
+
@scheduler.reload_busy_shards
|
28
|
+
@scheduler.busy_shards.should == shards.map {|s| s.id }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "busy_hosts" do
|
33
|
+
it "returns a list of hosts over the threshold of copies per host" do
|
34
|
+
shards = []
|
35
|
+
stub(@nameserver).get_busy_shards { shards }
|
36
|
+
@scheduler = Gizzard::Transformation::Scheduler.new(@nameserver, 't', @transformations, :copies_per_host => 2)
|
37
|
+
|
38
|
+
@scheduler.busy_hosts.should == []
|
39
|
+
|
40
|
+
shards = [info('127.0.0.1', 't_0_0001', 'TestShard')]
|
41
|
+
@scheduler.reload_busy_shards
|
42
|
+
@scheduler.busy_hosts.should == []
|
43
|
+
|
44
|
+
shards = [info('127.0.0.1', 't_0_0001', 'TestShard'), info('127.0.0.1', 't_0_0002', 'TestShard')]
|
45
|
+
@scheduler.reload_busy_shards
|
46
|
+
@scheduler.busy_hosts.should == ['127.0.0.1']
|
47
|
+
end
|
48
|
+
|
49
|
+
it "respects passed in extra hosts" do
|
50
|
+
shards = []
|
51
|
+
stub(@nameserver).get_busy_shards { shards }
|
52
|
+
@scheduler = Gizzard::Transformation::Scheduler.new(@nameserver, 't', @transformations, :copies_per_host => 2)
|
53
|
+
|
54
|
+
@scheduler.busy_hosts.should == []
|
55
|
+
@scheduler.busy_hosts(["127.0.0.1"]).should == []
|
56
|
+
@scheduler.busy_hosts(["127.0.0.1", "127.0.0.1"]).should == ["127.0.0.1"]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Gizzard::ShardTemplate do
|
4
|
+
before do
|
5
|
+
@sql = Gizzard::ShardTemplate.new("SqlShard", "sqlhost", 1, "", "", [])
|
6
|
+
@sql2 = Gizzard::ShardTemplate.new("SqlShard", "sqlhost2", 1, "", "", [])
|
7
|
+
@blocked = Gizzard::ShardTemplate.new("BlockedShard", "", 1, "", "", [@sql])
|
8
|
+
@replicating = Gizzard::ShardTemplate.new("ReplicatingShard", "", 1, "", "", [@blocked, @sql2])
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "concrete?" do
|
12
|
+
it "is false when a virtual shard type" do
|
13
|
+
Gizzard::Shard::VIRTUAL_SHARD_TYPES.each do |type|
|
14
|
+
t = Gizzard::ShardTemplate.new(type, "localhost", 1, "", "", [])
|
15
|
+
t.should_not be_concrete
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is true when not a virtual shard type" do
|
20
|
+
@sql.should be_concrete
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "host" do
|
25
|
+
it "is the template's shard if concrete" do
|
26
|
+
@sql.host.should == "sqlhost"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is the childs host if virtual and one child" do
|
30
|
+
@blocked.host.should == "sqlhost"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "is the abstract host if virtual with more than one child" do
|
34
|
+
@replicating.host.should == Gizzard::ShardTemplate::ABSTRACT_HOST
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "children" do
|
39
|
+
it "returns a sorted list" do
|
40
|
+
@replicating.children.should == [@blocked, @sql2].sort {|a, b| b <=> a }
|
41
|
+
@replicating.instance_variable_get("@children").reverse!
|
42
|
+
@replicating.children.should == [@blocked, @sql2].sort {|a, b| b <=> a }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "comparison methods" do
|
47
|
+
describe "shared_host?" do
|
48
|
+
it "is true if self and the other template share a descendant concrete identifier" do
|
49
|
+
other = Gizzard::ShardTemplate.new("FailingOverShard", "", 1, "", "", [@sql2])
|
50
|
+
|
51
|
+
@sql2.shared_host?(other).should be_true
|
52
|
+
@replicating.shared_host?(other).should be_true
|
53
|
+
@blocked.shared_host?(other).should be_false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "<=>" do
|
58
|
+
it "raises if other is not a ShardTemplate" do
|
59
|
+
lambda { @sql <=> "foo" }.should raise_error(ArgumentError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "eql?" do
|
64
|
+
it "returns false if other is not a ShardTemplate" do
|
65
|
+
@sql.eql?("foo").should be_false
|
66
|
+
(@sql == "foo").should be_false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "is structural equality" do
|
70
|
+
other_replicating = Marshal.load(Marshal.dump(@replicating))
|
71
|
+
@replicating.eql?(other_replicating).should be_true
|
72
|
+
(@replicating == other_replicating).should be_true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "config methods" do
|
78
|
+
describe "to_config" do
|
79
|
+
it "returns a human-readable string" do
|
80
|
+
@sql.to_config.should == "SqlShard(sqlhost,1)"
|
81
|
+
@blocked.to_config.should == 'BlockedShard(1) -> SqlShard(sqlhost,1)'
|
82
|
+
@replicating.to_config.should ==
|
83
|
+
'ReplicatingShard(1) -> (SqlShard(sqlhost2,1), BlockedShard(1) -> SqlShard(sqlhost,1))'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "config class methods" do
|
89
|
+
describe "parse" do
|
90
|
+
it "builds a shard template tree" do
|
91
|
+
Gizzard::ShardTemplate.parse("SqlShard(sqlhost,2)").should ==
|
92
|
+
Gizzard::ShardTemplate.new("SqlShard", "sqlhost", 2, "", "", [])
|
93
|
+
|
94
|
+
Gizzard::ShardTemplate.parse("SqlShard(sqlhost,1,int,int)").should ==
|
95
|
+
Gizzard::ShardTemplate.new("SqlShard", "sqlhost", 1, "int", "int", [])
|
96
|
+
|
97
|
+
Gizzard::ShardTemplate.parse(
|
98
|
+
'ReplicatingShard -> (SqlShard(sqlhost2,1), BlockedShard -> SqlShard(sqlhost,1))'
|
99
|
+
).should == @replicating
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/test/spec.opts
ADDED
data/test/spec_helper.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
ROOT_DIR = File.expand_path("../..", __FILE__)
|
2
|
+
TEST_ROOT = File.expand_path("test", ROOT_DIR)
|
3
|
+
SERVER_ROOT = File.expand_path('test_server', TEST_ROOT)
|
4
|
+
|
5
|
+
SERVER_VERSION = '0.1'
|
6
|
+
SERVER_JAR = File.expand_path("dist/gizzmotestserver/gizzmotestserver-#{SERVER_VERSION}.jar", SERVER_ROOT)
|
7
|
+
|
8
|
+
SERVICE_PORT = 7919
|
9
|
+
MANAGER_PORT = 7920
|
10
|
+
JOB_PORT = 7921
|
11
|
+
SERVICE_DATABASE = 'gizzard_test_integration'
|
12
|
+
NAMESERVER_DATABASE = 'gizzard_test_integration_ns'
|
13
|
+
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'spec'
|
17
|
+
require 'mysql'
|
18
|
+
|
19
|
+
$:.unshift File.expand_path('lib', ROOT_DIR)
|
20
|
+
require 'gizzard'
|
21
|
+
|
22
|
+
Spec::Runner.configure do |c|
|
23
|
+
c.mock_with :rr
|
24
|
+
end
|
25
|
+
|
26
|
+
def id(h,p); Gizzard::ShardId.new(h,p) end
|
27
|
+
def info(h,p,c,s = "",d = "",b = 0); Gizzard::ShardInfo.new(id(h,p),c,s,d,b) end
|
28
|
+
def link(p,c,w); Gizzard::LinkInfo.new(p,c,w) end
|
29
|
+
def forwarding(t,b,s); Gizzard::Forwarding.new(t,b,s) end
|
30
|
+
def host(h,p,c,s = 0); Gizzard::Host.new(h,p,c,s) end
|
31
|
+
|
32
|
+
def mk_template(conf_tree)
|
33
|
+
Gizzard::ShardTemplate.parse(conf_tree)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_server_pid
|
37
|
+
if pid = `ps axo pid,command`.split("\n").find {|l| l[SERVER_JAR] }
|
38
|
+
pid.split.first.to_i
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def start_test_server!(manager_p = MANAGER_PORT, job_p = JOB_PORT, service_p = SERVICE_PORT)
|
43
|
+
unless test_server_pid
|
44
|
+
compile_test_server!
|
45
|
+
|
46
|
+
fork do
|
47
|
+
exec "cd #{SERVER_ROOT} && exec java -jar #{SERVER_JAR} #{service_p} #{job_p} #{manager_p} > /dev/null 2>&1"
|
48
|
+
end
|
49
|
+
|
50
|
+
sleep 3
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def stop_test_server!
|
55
|
+
if pid = test_server_pid
|
56
|
+
Process.kill("KILL", pid)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def compile_test_server!
|
61
|
+
system "cd #{SERVER_ROOT} && sbt update package-dist" unless File.exist? SERVER_JAR
|
62
|
+
end
|
63
|
+
|
64
|
+
def mysql_connect!(host, user, pass)
|
65
|
+
$mysql = Mysql.new(host, user, pass)
|
66
|
+
end
|
67
|
+
|
68
|
+
def drop_database(*ds)
|
69
|
+
ds.each {|d| $mysql.query("drop database if exists `#{d}`") }
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_database(*ds)
|
73
|
+
ds.each {|d| $mysql.query("create database if not exists `#{d}`") }
|
74
|
+
end
|
75
|
+
|
76
|
+
def reset_nameserver(db = NAMESERVER_DATABASE)
|
77
|
+
$mysql.query("delete from `#{db}`.shards")
|
78
|
+
$mysql.query("delete from `#{db}`.shard_children")
|
79
|
+
$mysql.query("delete from `#{db}`.forwardings")
|
80
|
+
$mysql.query("delete from `#{db}`.hosts")
|
81
|
+
end
|
82
|
+
|
83
|
+
def reset_databases!
|
84
|
+
drop_database SERVICE_DATABASE
|
85
|
+
create_database NAMESERVER_DATABASE, SERVICE_DATABASE
|
86
|
+
|
87
|
+
begin
|
88
|
+
reset_nameserver
|
89
|
+
rescue MysqlError
|
90
|
+
|
91
|
+
begin
|
92
|
+
m = Gizzard::Manager.new("localhost", MANAGER_PORT, '/dev/null', false)
|
93
|
+
m.rebuild_schema
|
94
|
+
rescue Errno::ECONNREFUSED
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def read_nameserver_db(db = NAMESERVER_DATABASE)
|
100
|
+
{ :shards => map_rs($mysql.query("select * from `#{db}`.shards"), &method(:as_shard)),
|
101
|
+
:links => map_rs($mysql.query("select * from `#{db}`.shard_children"), &method(:as_link)),
|
102
|
+
:forwardings => map_rs($mysql.query("select * from `#{db}`.forwardings"), &method(:as_forwarding)),
|
103
|
+
:hosts => map_rs($mysql.query("select * from `#{db}`.hosts"), &method(:as_host)) }
|
104
|
+
end
|
105
|
+
|
106
|
+
def map_rs(rs)
|
107
|
+
a = []; rs.each_hash {|r| a << yield(r) }; a
|
108
|
+
end
|
109
|
+
|
110
|
+
def as_shard_id(h, prefix = nil)
|
111
|
+
attrs = ['hostname', 'table_prefix'].map {|a| prefix ? [prefix, a].join('_') : a }
|
112
|
+
Gizzard::ShardId.new(*h.values_at(*attrs))
|
113
|
+
end
|
114
|
+
|
115
|
+
def as_shard(h)
|
116
|
+
attrs = h.values_at('class_name', 'source_type', 'destination_type') << h['busy'].to_i
|
117
|
+
Gizzard::ShardInfo.new(as_shard_id(h), *attrs)
|
118
|
+
end
|
119
|
+
|
120
|
+
def as_link(h)
|
121
|
+
Gizzard::LinkInfo.new(as_shard_id(h, 'parent'), as_shard_id(h, 'child'), h['weight'].to_i)
|
122
|
+
end
|
123
|
+
|
124
|
+
def as_forwarding(h)
|
125
|
+
Gizzard::Forwarding.new(h['table_id'].to_i, h['base_id'].to_i, as_shard_id(h, 'shard'))
|
126
|
+
end
|
127
|
+
|
128
|
+
def as_host(h)
|
129
|
+
Gizzard::Host.new(h['hostname'], h['port'].to_i, h['cluster'], h['status'].to_i)
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
# setup
|
134
|
+
|
135
|
+
mysql_connect!("localhost", '', '')
|
136
|
+
reset_databases!
|
137
|
+
start_test_server!
|
138
|
+
|
139
|
+
at_exit { stop_test_server! }
|