flare-tools 0.1.4 → 0.4.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/Flare-tools.txt +0 -0
- data/History.txt +114 -2
- data/LICENSE +21 -0
- data/Manifest.txt +65 -8
- data/README.txt +356 -0
- data/Rakefile +90 -25
- data/Tutorial.txt +370 -0
- data/bin/flare-admin +6 -0
- data/bin/flare-argv0 +6 -0
- data/bin/flare-deploy +6 -0
- data/bin/flare-keychecker +6 -0
- data/bin/flare-part +6 -0
- data/bin/flare-ping +6 -0
- data/bin/flare-stats +4 -10
- data/bin/flare-zkadmin +6 -0
- data/lib/flare/net/connection.rb +98 -0
- data/lib/flare/test/cluster.rb +140 -0
- data/lib/flare/test/daemon.rb +144 -0
- data/lib/flare/test/node.rb +62 -0
- data/lib/flare/tools.rb +18 -16
- data/lib/flare/tools/cli.rb +32 -0
- data/lib/flare/tools/cli/activate.rb +106 -0
- data/lib/flare/tools/cli/balance.rb +83 -0
- data/lib/flare/tools/cli/cli_util.rb +77 -0
- data/lib/flare/tools/cli/deploy.rb +170 -0
- data/lib/flare/tools/cli/down.rb +85 -0
- data/lib/flare/tools/cli/dump.rb +219 -0
- data/lib/flare/tools/cli/dumpkey.rb +117 -0
- data/lib/flare/tools/cli/flare_admin.rb +81 -0
- data/lib/flare/tools/cli/flare_argv0.rb +60 -0
- data/lib/flare/tools/cli/flare_keychecker.rb +106 -0
- data/lib/flare/tools/cli/flare_zkadmin.rb +226 -0
- data/lib/flare/tools/cli/index.rb +54 -0
- data/lib/flare/tools/cli/list.rb +93 -0
- data/lib/flare/tools/cli/master.rb +143 -0
- data/lib/flare/tools/cli/part.rb +100 -0
- data/lib/flare/tools/cli/ping.rb +81 -0
- data/lib/flare/tools/cli/reconstruct.rb +164 -0
- data/lib/flare/tools/cli/remove.rb +119 -0
- data/lib/flare/tools/cli/restore.rb +180 -0
- data/lib/flare/tools/cli/slave.rb +125 -0
- data/lib/flare/tools/cli/stats.rb +229 -122
- data/lib/flare/tools/cli/sub_command.rb +73 -0
- data/lib/flare/tools/cli/summary.rb +97 -0
- data/lib/flare/tools/cli/threads.rb +78 -0
- data/lib/flare/tools/cli/verify.rb +202 -0
- data/lib/flare/tools/client.rb +267 -0
- data/lib/flare/tools/cluster.rb +319 -0
- data/lib/flare/tools/common.rb +196 -0
- data/lib/flare/tools/index_server.rb +51 -0
- data/lib/flare/tools/node.rb +162 -0
- data/lib/flare/tools/stats.rb +75 -0
- data/lib/flare/tools/zk_util.rb +28 -0
- data/lib/flare/util.rb +34 -0
- data/lib/flare/util/bwlimit.rb +132 -0
- data/lib/flare/util/command_line.rb +79 -0
- data/lib/flare/util/conf.rb +71 -0
- data/lib/flare/util/constant.rb +25 -0
- data/lib/flare/util/conversion.rb +26 -0
- data/lib/flare/util/default_logger.rb +52 -0
- data/lib/flare/util/exception.rb +19 -0
- data/lib/flare/util/filesystem.rb +30 -0
- data/lib/flare/util/flared_conf.rb +33 -0
- data/lib/flare/util/flarei_conf.rb +32 -0
- data/lib/flare/util/hash_function.rb +32 -0
- data/lib/flare/util/interruption.rb +70 -0
- data/lib/flare/util/key_resolver.rb +67 -0
- data/lib/flare/util/log4r_logger.rb +79 -0
- data/lib/flare/util/logger.rb +40 -0
- data/lib/flare/util/logging.rb +84 -0
- data/lib/flare/util/result.rb +53 -0
- data/test/test/experimental/cache_test.rb +113 -0
- data/test/test/experimental/key_distribution_test.rb +38 -0
- data/test/test/experimental/keychecker_test.rb +60 -0
- data/test/test/experimental/list_test.rb +108 -0
- data/test/test/extra/replication_test.rb +184 -0
- data/test/test/integration/cli_test.rb +348 -0
- data/test/test/integration/dump_expired_test.rb +103 -0
- data/test/test/integration/dump_test.rb +128 -0
- data/test/test/integration/index_server_test.rb +35 -0
- data/test/test/integration/node_test.rb +78 -0
- data/test/test/integration/partition_test.rb +235 -0
- data/test/test/integration/proxy_test.rb +54 -0
- data/test/test/integration/stats_test.rb +79 -0
- data/test/test/system/flare_admin_test.rb +191 -0
- data/test/test/unit/bwlimit_test.rb +52 -0
- data/test/test/unit/cluster_test.rb +96 -0
- data/test/test/unit/daemon_test.rb +30 -0
- data/test/test/unit/logger_test.rb +46 -0
- data/test/test/unit/tools_test.rb +25 -0
- data/test/test/unit/util_test.rb +70 -0
- metadata +239 -84
- data/README.rdoc +0 -83
- data/bin/flare-partition-setting +0 -12
- data/lib/flare/tools/cli/partition_setting.rb +0 -86
- data/lib/flare/tools/core.rb +0 -189
- data/lib/flare/tools/logger.rb +0 -31
- data/test/test_flare-tools.rb +0 -11
- data/test/test_helper.rb +0 -3
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- coding: utf-8; -*-
|
2
|
+
# Authors:: Kiyoshi Ikehara <kiyoshi.ikehara@gree.net>
|
3
|
+
# Copyright:: Copyright (C) GREE, Inc. 2011.
|
4
|
+
# License:: MIT-style
|
5
|
+
|
6
|
+
#
|
7
|
+
module Flare
|
8
|
+
module Util
|
9
|
+
|
10
|
+
# == Description
|
11
|
+
# Result is a class for handling result code.
|
12
|
+
module Result
|
13
|
+
None = nil
|
14
|
+
Ok = :OK
|
15
|
+
End = :END
|
16
|
+
Stored = :STORED
|
17
|
+
NotStored = :NOT_STORED
|
18
|
+
Exists = :EXISTS
|
19
|
+
NotFound= :NOT_FOUND
|
20
|
+
Deleted = :DELETED
|
21
|
+
Found = :FOUND
|
22
|
+
Error = :ERROR
|
23
|
+
ClientError = :CLIENT_ERROR
|
24
|
+
ServerError = :SERVER_ERROR
|
25
|
+
|
26
|
+
# Converts a result code to its string representation.
|
27
|
+
def self.string_of_result(result)
|
28
|
+
case result
|
29
|
+
when None
|
30
|
+
""
|
31
|
+
when Ok,End,Stored,NotStored,Exists,NotFound,Deleted,Found,Error,ClientError,ServerError
|
32
|
+
result.to_s
|
33
|
+
else
|
34
|
+
raise "Invalid argument '"+result.to_s+"'"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Converts a string representation of a request result to its result code.
|
39
|
+
def self.result_of_string(string)
|
40
|
+
case string
|
41
|
+
when ""
|
42
|
+
None
|
43
|
+
else
|
44
|
+
[Ok,End,Stored,NotStored,Exists,NotFound,Deleted,Found,Error,ClientError,ServerError].each do |x|
|
45
|
+
return x if x.to_s == string
|
46
|
+
end
|
47
|
+
raise "Invalid arugument '"+string.to_s+"'"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- coding: utf-8; -*-
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__)+"/../lib")
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'flare/tools'
|
8
|
+
require 'flare/tools/cli'
|
9
|
+
require 'flare/test/cluster'
|
10
|
+
require 'subcommands'
|
11
|
+
|
12
|
+
class CacheTest < Test::Unit::TestCase
|
13
|
+
include Flare::Tools::Common
|
14
|
+
include Subcommands
|
15
|
+
|
16
|
+
S_OK = 0
|
17
|
+
S_NG = 1
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@flare_cluster = Flare::Test::Cluster.new('test')
|
21
|
+
sleep 1 # XXX
|
22
|
+
@node_servers = ['localmaster1', 'localproxy1', 'remoteproxy1'].map {|name|
|
23
|
+
@flare_cluster.create_node(name, { 'proxy-cache-size' => 1000, 'proxy-cache-expire' => 60 }, "/usr/local/proxy_cache/bin/flared")
|
24
|
+
}
|
25
|
+
sleep 1 # XXX
|
26
|
+
@flare_cluster.wait_for_ready
|
27
|
+
@config = {
|
28
|
+
:command => 'dummy',
|
29
|
+
:index_server_hostname => @flare_cluster.indexname,
|
30
|
+
:index_server_port => @flare_cluster.indexport,
|
31
|
+
:dry_run => false,
|
32
|
+
:timeout => 10
|
33
|
+
}
|
34
|
+
@nodes = @node_servers.map do |node|
|
35
|
+
Flare::Tools::Node.open(node.hostname, node.port, 10)
|
36
|
+
end
|
37
|
+
@localmaster1, @localproxy1, @remoteproxy1 = @nodes
|
38
|
+
end
|
39
|
+
|
40
|
+
def teardown
|
41
|
+
@nodes.map {|n| n.close}
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_proxy_gets_from_various_routes
|
45
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers[0..0])
|
46
|
+
key = "hoge"
|
47
|
+
@localmaster1.set(key, "v1")
|
48
|
+
value, version = @localmaster1.gets(key)
|
49
|
+
assert_equal(1, version);
|
50
|
+
assert_equal("v1", value);
|
51
|
+
@localproxy1.set(key, "v2")
|
52
|
+
value, version = @localmaster1.gets(key)
|
53
|
+
assert_equal(2, version);
|
54
|
+
assert_equal("v2", value);
|
55
|
+
@remoteproxy1.set(key, "v3")
|
56
|
+
value, version = @localmaster1.gets(key)
|
57
|
+
assert_equal(3, version);
|
58
|
+
assert_equal("v3", value);
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_proxy_cas_to_master
|
62
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers[0..0])
|
63
|
+
key = "hoge"
|
64
|
+
@localmaster1.set(key, "v1")
|
65
|
+
value, version = @localmaster1.gets(key)
|
66
|
+
assert_equal(1, version);
|
67
|
+
@localmaster1.cas(key, "v2", version)
|
68
|
+
value, version = @localmaster1.gets(key)
|
69
|
+
assert_equal(2, version);
|
70
|
+
@localproxy1.cas(key, "v3", version)
|
71
|
+
value, version = @localproxy1.gets(key)
|
72
|
+
assert_equal(3, version);
|
73
|
+
end
|
74
|
+
|
75
|
+
class Client
|
76
|
+
def initialize(node)
|
77
|
+
@node = node
|
78
|
+
end
|
79
|
+
|
80
|
+
def gets(*keys)
|
81
|
+
@node.gets(*keys)
|
82
|
+
end
|
83
|
+
|
84
|
+
def cas(*keys)
|
85
|
+
@node.cas(*keys)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_proxy_gets_and_cas
|
90
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers[0..0])
|
91
|
+
key = "hoge"
|
92
|
+
|
93
|
+
@localmaster1.set(key, "initial")
|
94
|
+
|
95
|
+
c0 = Client.new(@localmaster1)
|
96
|
+
c1 = Client.new(@remoteproxy1)
|
97
|
+
c2 = Client.new(@remoteproxy1)
|
98
|
+
|
99
|
+
v1,v1version = c1.gets(key)
|
100
|
+
v0,v0version = c0.gets(key)
|
101
|
+
v2,v2version = c2.gets(key)
|
102
|
+
|
103
|
+
r0 = c0.cas(key, "client0", v0version)
|
104
|
+
r1 = c1.cas(key, "client1", v1version)
|
105
|
+
r2 = c2.cas(key, "client2", v2version)
|
106
|
+
|
107
|
+
assert_equal(true, r0)
|
108
|
+
assert_equal(false, r1)
|
109
|
+
assert_equal(false, r2)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- coding: utf-8; -*-
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)+"/../lib"
|
5
|
+
|
6
|
+
require 'flare/util/key_resolver'
|
7
|
+
require 'flare/util/hash_function'
|
8
|
+
require 'shell'
|
9
|
+
require 'test/unit'
|
10
|
+
|
11
|
+
class KeyDistributionTest < Test::Unit::TestCase
|
12
|
+
include Flare::Util::HashFunction
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@resolver = Flare::Util::KeyResolver.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_key_distribution1
|
19
|
+
proxy_concurrency = 8
|
20
|
+
partition_size = 4
|
21
|
+
prefix = "test::key::distribution"
|
22
|
+
bin = []
|
23
|
+
(0...proxy_concurrency).each do |i|
|
24
|
+
bin[i] = 0
|
25
|
+
end
|
26
|
+
(1..10000).each do |i|
|
27
|
+
key = "#{prefix}::#{i}"
|
28
|
+
hash_of_key = get_key_hash_value(key, :bitshift, 32)
|
29
|
+
target_thread = hash_of_key % proxy_concurrency
|
30
|
+
target_partition = @resolver.resolve(get_key_hash_value(key, :simple, 32), partition_size)
|
31
|
+
if target_partition == 0
|
32
|
+
bin[target_thread] += 1
|
33
|
+
end
|
34
|
+
end
|
35
|
+
p bin
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- coding: utf-8; -*-
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)+"/../lib"
|
5
|
+
|
6
|
+
require 'shell'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
Shell.verbose = false
|
10
|
+
Shell.def_system_command "kc", "../../bin/flare-keychecker"
|
11
|
+
|
12
|
+
class KeycheckerTest < Test::Unit::TestCase
|
13
|
+
KeyTxt = "keychecker_test.key.txt"
|
14
|
+
ResultCsv = "keychecker_test.result.csv"
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@basedir = File.dirname(__FILE__)+"/work"
|
18
|
+
@sh = Shell.new
|
19
|
+
@sh.cd(@basedir)
|
20
|
+
@sh.transact {
|
21
|
+
unless exist? KeyTxt
|
22
|
+
keys = (0...1000).inject([]) {|r,v| r << "prefix::#{v}"}
|
23
|
+
echo(*keys) >> KeyTxt
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_help1
|
29
|
+
@sh.transact {
|
30
|
+
kc("--help")
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def hash(type)
|
35
|
+
@sh.transact {
|
36
|
+
(cat(KeyTxt) | kc("--hash=#{type}")) > ResultCsv
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_hash1
|
41
|
+
hash("simple")
|
42
|
+
hash("bitshift")
|
43
|
+
hash("crc32")
|
44
|
+
end
|
45
|
+
|
46
|
+
def delimiter(delimiter)
|
47
|
+
@sh.transact {
|
48
|
+
echo(*@keys) >> KeyTxt
|
49
|
+
(cat(KeyTxt) | kc("--delimiter=#{delimiter}")) > ResultCsv
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_delimiter1
|
54
|
+
delimiter("::")
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- coding: utf-8; -*-
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__)+"/../lib")
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'flare/tools'
|
8
|
+
require 'flare/tools/cli'
|
9
|
+
require 'flare/test/cluster'
|
10
|
+
require 'subcommands'
|
11
|
+
|
12
|
+
class ListTest < Test::Unit::TestCase
|
13
|
+
include Flare::Tools::Common
|
14
|
+
include Subcommands
|
15
|
+
|
16
|
+
S_OK = 0
|
17
|
+
S_NG = 1
|
18
|
+
|
19
|
+
def setup
|
20
|
+
@flare_cluster = Flare::Test::Cluster.new('test')
|
21
|
+
sleep 1 # XXX
|
22
|
+
@node_servers = ['node1', 'node2', 'node3'].map {|name| @flare_cluster.create_node(name)}
|
23
|
+
sleep 1 # XXX
|
24
|
+
@flare_cluster.wait_for_ready
|
25
|
+
@config = {
|
26
|
+
:command => 'dummy',
|
27
|
+
:index_server_hostname => @flare_cluster.indexname,
|
28
|
+
:index_server_port => @flare_cluster.indexport,
|
29
|
+
:dry_run => false,
|
30
|
+
:timeout => 10
|
31
|
+
}
|
32
|
+
@nodes = @node_servers.map do |node|
|
33
|
+
Flare::Tools::Node.open(node.hostname, node.port, 10)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
@nodes.map {|n| n.close}
|
39
|
+
end
|
40
|
+
|
41
|
+
def push_and_get(npush, nget)
|
42
|
+
list if defined? DEBUG
|
43
|
+
key = "k"
|
44
|
+
(0...100).each do |i|
|
45
|
+
value = "v#{i}"
|
46
|
+
npush.x_list_push(key, value)
|
47
|
+
sleep 0.001
|
48
|
+
count = 0
|
49
|
+
nget.x_list_get(key, i, i+1) do |v, k, rel, abs, flag, len, version, expire|
|
50
|
+
assert_equal(key, k)
|
51
|
+
assert_equal(value, v)
|
52
|
+
count += 1
|
53
|
+
end
|
54
|
+
assert_equal(1, count)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def push_and_range_get(npush, nget)
|
59
|
+
list if defined? DEBUG
|
60
|
+
key = "k"
|
61
|
+
size = 100
|
62
|
+
range = (0...size)
|
63
|
+
expected = range.map {|i| "v#{i}"}
|
64
|
+
range.each do |i|
|
65
|
+
npush.x_list_push(key, expected[i])
|
66
|
+
end
|
67
|
+
count = 0
|
68
|
+
nget.x_list_get(key, 0, size) do |v, k, rel, abs, f|
|
69
|
+
value = "v#{count}"
|
70
|
+
assert_equal(key, k)
|
71
|
+
assert_equal(value, v)
|
72
|
+
count += 1
|
73
|
+
end
|
74
|
+
assert_equal(size, count)
|
75
|
+
end
|
76
|
+
|
77
|
+
def push_and_shift(npush, nshift)
|
78
|
+
list if defined? DEBUG
|
79
|
+
key = "k"
|
80
|
+
range = (0...100)
|
81
|
+
expected = range.map {|i| "v#{i}"}
|
82
|
+
range.each do |i|
|
83
|
+
npush.x_list_push(key, expected[i])
|
84
|
+
end
|
85
|
+
values = range.map {|i| nshift.x_list_shift(key)}
|
86
|
+
assert_equal(expected, values)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.deftest_allpair(name)
|
90
|
+
syms = ["m", "s", "p"]
|
91
|
+
for i in (0...syms.size)
|
92
|
+
for j in (0...syms.size)
|
93
|
+
self.class_eval %{
|
94
|
+
def test_#{name.to_s}_#{syms[i]}#{syms[j]}
|
95
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers[0..1])
|
96
|
+
#{name.to_s}(@nodes[#{i}], @nodes[#{j}])
|
97
|
+
end
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
deftest_allpair :push_and_get
|
104
|
+
deftest_allpair :push_and_range_get
|
105
|
+
deftest_allpair :push_and_shift
|
106
|
+
|
107
|
+
end
|
108
|
+
|
@@ -0,0 +1,184 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# -*- coding: utf-8; -*-
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)+"/../lib"
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'flare/tools'
|
8
|
+
require 'flare/test/cluster'
|
9
|
+
|
10
|
+
class ReplicationTest < Test::Unit::TestCase
|
11
|
+
include Flare::Tools::Common
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@flare_cluster = Flare::Test::Cluster.new('test')
|
15
|
+
sleep 1 # XXX
|
16
|
+
@node_servers = ['node1', 'node2', 'node3', 'node4', 'node5', 'node6'].map {|name| @flare_cluster.create_node(name)}
|
17
|
+
sleep 1 # XXX
|
18
|
+
@flare_cluster.wait_for_ready
|
19
|
+
@config = {
|
20
|
+
:command => 'dummy',
|
21
|
+
:index_server_hostname => @flare_cluster.indexname,
|
22
|
+
:index_server_port => @flare_cluster.indexport,
|
23
|
+
:dry_run => false,
|
24
|
+
:timeout => 10
|
25
|
+
}
|
26
|
+
@nodes = @node_servers.map do |node|
|
27
|
+
Flare::Tools::Node.open(node.hostname, node.port, 10)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown
|
32
|
+
@nodes.map {|n| n.close}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_replication
|
36
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers)
|
37
|
+
Flare::Tools::Node.open(@flare_cluster.indexname, @flare_cluster.indexport, 10) do |s|
|
38
|
+
puts string_of_nodelist(s.stats_nodes)
|
39
|
+
node = @node_servers[1]
|
40
|
+
puts "throwing requests to #{node.hostname}:#{node.port}."
|
41
|
+
Flare::Tools::Node.open(node.hostname, node.port, 10) do |n|
|
42
|
+
fmt = "key%010.10d"
|
43
|
+
(0...10).each do |i|
|
44
|
+
n.set(fmt % i, "All your base are belong to us.")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
puts string_of_nodelist(s.stats_nodes)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def parallel(*args, &block)
|
52
|
+
args.map do |arg|
|
53
|
+
Thread.new do
|
54
|
+
block.call(arg)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_replication_consistent
|
60
|
+
replication_consistent(false)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_replication_consistent_noreply
|
64
|
+
replication_consistent(true, 0.1)
|
65
|
+
end
|
66
|
+
|
67
|
+
def replication_consistent(noreply, wait = 0)
|
68
|
+
@flare_cluster.prepare_master_and_slaves(@node_servers)
|
69
|
+
|
70
|
+
Flare::Tools::Node.open(@flare_cluster.indexname, @flare_cluster.indexport, 10) do |s|
|
71
|
+
puts string_of_nodelist(s.stats_nodes)
|
72
|
+
ntry = 256
|
73
|
+
nparallel = 128
|
74
|
+
nloop = 32
|
75
|
+
entries = (0...nparallel).map { |i|
|
76
|
+
{
|
77
|
+
:index => i,
|
78
|
+
:command_queue => Queue.new,
|
79
|
+
:hostname => @node_servers[0].hostname,
|
80
|
+
:port => @node_servers[0].port,
|
81
|
+
:result_queue => Queue.new,
|
82
|
+
:backlog_queue => Queue.new
|
83
|
+
}
|
84
|
+
}
|
85
|
+
puts "creating threads..."
|
86
|
+
entries.each { |entry| entry[:command_queue].enq("start") }
|
87
|
+
threads = parallel(*entries) do |entry|
|
88
|
+
Flare::Tools::Node.open(entry[:hostname], entry[:port], 10) do |n|
|
89
|
+
while command = entry[:command_queue].deq
|
90
|
+
case command
|
91
|
+
when "start"
|
92
|
+
# puts "#{entry[:index]}:#{entry[:hostname]}:#{entry[:port]}: start"
|
93
|
+
n.set("key", "0")
|
94
|
+
# puts "#{entry[:index]}:#{entry[:hostname]}:#{entry[:port]}: start end"
|
95
|
+
when "end"
|
96
|
+
entry[:result_queue].enq("terminated")
|
97
|
+
break
|
98
|
+
when "execute"
|
99
|
+
# puts "#{entry[:index]}:#{entry[:hostname]}:#{entry[:port]}: begin"
|
100
|
+
(0...nloop).each do |i|
|
101
|
+
if i%10 == 0
|
102
|
+
print "."
|
103
|
+
n.delete("key")
|
104
|
+
n.set("key", "111")
|
105
|
+
elsif i%10 == 1
|
106
|
+
n.decr("key", "1")
|
107
|
+
else
|
108
|
+
n.incr("key", "1")
|
109
|
+
end
|
110
|
+
Thread.pass
|
111
|
+
end
|
112
|
+
# puts "#{entry[:index]}:#{entry[:hostname]}:#{entry[:port]}: end"
|
113
|
+
entry[:result_queue].enq("finished")
|
114
|
+
when "execute_noreply"
|
115
|
+
count = 0
|
116
|
+
(0...nloop).each do |i|
|
117
|
+
case rand(8)
|
118
|
+
when 0
|
119
|
+
n.delete_noreply("key")
|
120
|
+
when 1
|
121
|
+
n.set_noreply("key", count.to_s)
|
122
|
+
when 2
|
123
|
+
# n.decr_noreply("key", "1")
|
124
|
+
n.set_noreply("key", count.to_s)
|
125
|
+
else
|
126
|
+
n.incr_noreply("key", "1")
|
127
|
+
# n.set_noreply("key", count.to_s)
|
128
|
+
end
|
129
|
+
count = count+1
|
130
|
+
count = 0 if count > 1000
|
131
|
+
end
|
132
|
+
entry[:result_queue].enq("finished")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
(0...ntry).each do |n|
|
139
|
+
entries.each {|entry|
|
140
|
+
command = if noreply then "execute_noreply" else "execute" end
|
141
|
+
entry[:command_queue].enq(command)
|
142
|
+
}
|
143
|
+
print "waiting(#{n})..."
|
144
|
+
if noreply && wait > 0
|
145
|
+
while entries[0][:result_queue].empty?
|
146
|
+
@node_servers[0].stop
|
147
|
+
sleep wait
|
148
|
+
@node_servers[0].cont
|
149
|
+
sleep wait if entries[0][:result_queue].empty?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
entries.map {|entry| assert_equal("finished", entry[:result_queue].deq) }
|
153
|
+
for i in 1..5
|
154
|
+
failed = false
|
155
|
+
sleep wait
|
156
|
+
results = @nodes.map do |n|
|
157
|
+
n.get("key")
|
158
|
+
end
|
159
|
+
slave_results = results.dup
|
160
|
+
master_result = slave_results.shift
|
161
|
+
slave_results.each {|r| failed = true if master_result != r}
|
162
|
+
puts results.join(' ')
|
163
|
+
if failed
|
164
|
+
sleep 1
|
165
|
+
if i == 5
|
166
|
+
puts "inconsistent data: master=#{master_result}\n"
|
167
|
+
end
|
168
|
+
else
|
169
|
+
break
|
170
|
+
end
|
171
|
+
end
|
172
|
+
slave_results.each {|r| assert_equal(master_result, r)}
|
173
|
+
end
|
174
|
+
entries.each {|entry| entry[:command_queue].enq("end") }
|
175
|
+
entries.map {|entry| assert_equal("terminated", entry[:result_queue].deq)}
|
176
|
+
threads.each do |t|
|
177
|
+
t.join
|
178
|
+
end
|
179
|
+
puts string_of_nodelist(s.stats_nodes)
|
180
|
+
puts "done."
|
181
|
+
end
|
182
|
+
end # func
|
183
|
+
|
184
|
+
end
|