droonga-engine 1.0.9 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/benchmark/timer-watcher/benchmark.rb +44 -0
- data/bin/droonga-engine-absorb-data +246 -187
- data/bin/droonga-engine-catalog-generate +12 -12
- data/bin/droonga-engine-catalog-modify +4 -4
- data/bin/droonga-engine-join +352 -171
- data/bin/droonga-engine-set-role +54 -0
- data/bin/droonga-engine-unjoin +107 -112
- data/droonga-engine.gemspec +3 -3
- data/install.sh +55 -36
- data/install/centos/functions.sh +2 -2
- data/install/debian/functions.sh +2 -2
- data/lib/droonga/address.rb +26 -24
- data/lib/droonga/buffered_tcp_socket.rb +65 -10
- data/lib/droonga/catalog/base.rb +9 -6
- data/lib/droonga/catalog/dataset.rb +17 -41
- data/lib/droonga/catalog/fetcher.rb +64 -0
- data/lib/droonga/catalog/generator.rb +245 -0
- data/lib/droonga/catalog/loader.rb +66 -0
- data/lib/droonga/{catalog_modifier.rb → catalog/modifier.rb} +11 -18
- data/lib/droonga/catalog/replicas_volume.rb +123 -0
- data/lib/droonga/catalog/schema.rb +37 -37
- data/lib/droonga/catalog/single_volume.rb +11 -3
- data/lib/droonga/catalog/slice.rb +10 -6
- data/lib/droonga/catalog/{collection_volume.rb → slices_volume.rb} +47 -11
- data/lib/droonga/catalog/version1.rb +47 -19
- data/lib/droonga/catalog/version2.rb +11 -10
- data/lib/droonga/catalog/version2_validator.rb +4 -4
- data/lib/droonga/catalog/volume.rb +17 -5
- data/lib/droonga/changable.rb +25 -0
- data/lib/droonga/cluster.rb +237 -0
- data/lib/droonga/collector_runner.rb +4 -0
- data/lib/droonga/collectors.rb +2 -1
- data/lib/droonga/collectors/recursive_sum.rb +26 -0
- data/lib/droonga/command/droonga_engine.rb +404 -127
- data/lib/droonga/command/droonga_engine_service.rb +47 -11
- data/lib/droonga/command/droonga_engine_worker.rb +21 -1
- data/lib/droonga/command/remote_command_base.rb +78 -0
- data/lib/droonga/command/serf_event_handler.rb +29 -20
- data/lib/droonga/data_absorber_client.rb +222 -0
- data/lib/droonga/database_scanner.rb +106 -0
- data/lib/droonga/{live_nodes_list_loader.rb → deferrable.rb} +11 -24
- data/lib/droonga/differ.rb +58 -0
- data/lib/droonga/dispatcher.rb +155 -32
- data/lib/droonga/distributed_command_planner.rb +9 -11
- data/lib/droonga/engine.rb +83 -78
- data/lib/droonga/engine/version.rb +1 -1
- data/lib/droonga/engine_node.rb +301 -0
- data/lib/droonga/engine_state.rb +62 -40
- data/lib/droonga/farm.rb +44 -5
- data/lib/droonga/file_observer.rb +16 -12
- data/lib/droonga/fluent_message_receiver.rb +98 -29
- data/lib/droonga/fluent_message_sender.rb +30 -23
- data/lib/droonga/forward_buffer.rb +160 -0
- data/lib/droonga/forwarder.rb +73 -40
- data/lib/droonga/handler.rb +7 -6
- data/lib/droonga/handler_messenger.rb +15 -6
- data/lib/droonga/handler_runner.rb +6 -1
- data/lib/droonga/internal_fluent_message_receiver.rb +28 -8
- data/lib/droonga/job_pusher.rb +10 -7
- data/lib/droonga/job_receiver.rb +6 -4
- data/lib/droonga/logger.rb +7 -1
- data/lib/droonga/node_name.rb +90 -0
- data/lib/droonga/node_role.rb +72 -0
- data/lib/droonga/path.rb +34 -9
- data/lib/droonga/planner.rb +73 -7
- data/lib/droonga/plugin/async_command.rb +154 -0
- data/lib/droonga/plugins/catalog.rb +1 -0
- data/lib/droonga/plugins/crud.rb +22 -6
- data/lib/droonga/plugins/dump.rb +66 -135
- data/lib/droonga/plugins/groonga/delete.rb +13 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +4 -4
- data/lib/droonga/plugins/system.rb +5 -26
- data/lib/droonga/plugins/system/absorb_data.rb +405 -0
- data/lib/droonga/plugins/system/statistics.rb +71 -0
- data/lib/droonga/plugins/system/status.rb +53 -0
- data/lib/droonga/process_control_protocol.rb +3 -1
- data/lib/droonga/process_supervisor.rb +32 -15
- data/lib/droonga/reducer.rb +69 -0
- data/lib/droonga/safe_file_writer.rb +1 -1
- data/lib/droonga/serf.rb +207 -276
- data/lib/droonga/serf/agent.rb +228 -0
- data/lib/droonga/serf/command.rb +94 -0
- data/lib/droonga/serf/downloader.rb +120 -0
- data/lib/droonga/serf/remote_command.rb +348 -0
- data/lib/droonga/serf/tag.rb +56 -0
- data/lib/droonga/service_installation.rb +2 -2
- data/lib/droonga/session.rb +49 -1
- data/lib/droonga/single_step.rb +6 -11
- data/lib/droonga/single_step_definition.rb +32 -1
- data/lib/droonga/slice.rb +14 -9
- data/lib/droonga/supervisor.rb +27 -20
- data/lib/droonga/test/stub_handler_messenger.rb +2 -1
- data/lib/droonga/timestamp.rb +69 -0
- data/lib/droonga/worker_process_agent.rb +33 -15
- data/sample/cluster-state.json +8 -0
- data/sample/cluster/Rakefile +30 -6
- data/test/command/fixture/integer-key-table.jsons +11 -0
- data/test/command/fixture/string-key-table.jsons +11 -0
- data/test/command/run-test.rb +4 -0
- data/test/command/suite/add/error/invalid-integer.expected +3 -3
- data/test/command/suite/add/error/invalid-time.expected +3 -3
- data/test/command/suite/add/{minimum.expected → key-integer.expected} +0 -0
- data/test/command/suite/add/{minimum.test → key-integer.test} +0 -0
- data/test/command/suite/add/key-string.expected +6 -0
- data/test/command/suite/add/key-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.test +9 -0
- data/test/command/suite/add/without-values.expected +6 -0
- data/test/command/suite/add/without-values.test +11 -0
- data/test/command/suite/dump/column/index.expected +33 -1
- data/test/command/suite/dump/column/index.test +1 -0
- data/test/command/suite/dump/column/scalar.expected +29 -1
- data/test/command/suite/dump/column/scalar.test +1 -0
- data/test/command/suite/dump/column/vector.expected +29 -1
- data/test/command/suite/dump/column/vector.test +1 -0
- data/test/command/suite/dump/record/scalar.catalog.json +12 -0
- data/test/command/suite/dump/record/scalar.expected +84 -0
- data/test/command/suite/dump/record/scalar.test +16 -0
- data/test/command/suite/dump/record/vector/reference.expected +83 -1
- data/test/command/suite/dump/record/vector/reference.test +1 -0
- data/test/command/suite/dump/table/array.expected +27 -1
- data/test/command/suite/dump/table/array.test +1 -0
- data/test/command/suite/dump/table/double_array_trie.expected +27 -1
- data/test/command/suite/dump/table/double_array_trie.test +1 -0
- data/test/command/suite/dump/table/hash.expected +27 -1
- data/test/command/suite/dump/table/hash.test +1 -0
- data/test/command/suite/dump/table/patricia_trie.expected +27 -1
- data/test/command/suite/dump/table/patricia_trie.test +1 -0
- data/test/command/suite/groonga/delete/{success.expected → key-integer.expected} +0 -0
- data/test/command/suite/groonga/delete/key-integer.test +17 -0
- data/test/command/suite/groonga/delete/key-string.expected +19 -0
- data/test/command/suite/groonga/delete/{success.test → key-string.test} +4 -6
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.test +17 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.test +17 -0
- data/test/command/suite/message/error/missing-dataset.test +1 -0
- data/test/command/suite/system/absorb-data/records.catalog.json +58 -0
- data/test/command/suite/system/absorb-data/records.expected +32 -0
- data/test/command/suite/system/absorb-data/records.test +24 -0
- data/test/command/suite/system/statistics/object/count/empty.expected +11 -0
- data/test/command/suite/system/statistics/object/count/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.catalog.json +36 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.test +13 -0
- data/test/command/suite/system/statistics/object/count/record.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/record.expected +11 -0
- data/test/command/suite/system/statistics/object/count/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/schema.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/schema.expected +11 -0
- data/test/command/suite/system/statistics/object/count/schema.test +13 -0
- data/test/command/suite/system/status.expected +3 -2
- data/test/unit/catalog/test_dataset.rb +4 -1
- data/test/unit/{test_catalog_generator.rb → catalog/test_generator.rb} +2 -2
- data/test/unit/catalog/test_replicas_volume.rb +79 -0
- data/test/unit/catalog/test_single_volume.rb +2 -2
- data/test/unit/catalog/test_slice.rb +33 -1
- data/test/unit/catalog/{test_collection_volume.rb → test_slices_volume.rb} +72 -11
- data/test/unit/catalog/test_version2.rb +3 -0
- data/test/unit/helper/distributed_search_planner_helper.rb +2 -2
- data/test/unit/plugins/catalog/test_fetch.rb +4 -4
- data/test/unit/plugins/crud/test_add.rb +44 -4
- data/test/unit/plugins/groonga/test_column_create.rb +4 -4
- data/test/unit/plugins/groonga/test_column_list.rb +4 -4
- data/test/unit/plugins/groonga/test_column_remove.rb +4 -4
- data/test/unit/plugins/groonga/test_column_rename.rb +4 -4
- data/test/unit/plugins/groonga/test_delete.rb +73 -10
- data/test/unit/plugins/groonga/test_table_create.rb +4 -4
- data/test/unit/plugins/groonga/test_table_list.rb +4 -4
- data/test/unit/plugins/groonga/test_table_remove.rb +4 -4
- data/test/unit/plugins/search/test_handler.rb +4 -4
- data/test/unit/plugins/search/test_planner.rb +4 -2
- data/test/unit/plugins/system/test_status.rb +31 -15
- data/test/unit/plugins/test_watch.rb +16 -16
- data/test/unit/test_address.rb +4 -4
- metadata +134 -35
- data/lib/droonga/catalog/volume_collection.rb +0 -79
- data/lib/droonga/catalog_fetcher.rb +0 -53
- data/lib/droonga/catalog_generator.rb +0 -243
- data/lib/droonga/catalog_loader.rb +0 -56
- data/lib/droonga/command/remote.rb +0 -404
- data/lib/droonga/data_absorber.rb +0 -264
- data/lib/droonga/node_status.rb +0 -71
- data/lib/droonga/serf_downloader.rb +0 -115
- data/test/unit/catalog/test_volume_collection.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd5aad47933f58aee93072477c535d458556b183
|
4
|
+
data.tar.gz: fc6e82289c99cc3ef4cdc269d0153ca6588dec7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 08909575ab516f97f404396904a53a0920bdc7a6ad7ab8673e7065d681698dee2f7029c71cb74731824892df0eeb87b8de4383d4aa9d0107823e7a00f363a7dc
|
7
|
+
data.tar.gz: fc2acfa0c8c133bc70ebad99f7d326e96fcc316fdedfb45347431e5ec3a96a751d4f00db03b9c21c4c44d03d26b8da5b0263615926e9321d50f44c60277f0cf9
|
data/.travis.yml
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require "coolio"
|
2
|
+
|
3
|
+
$times = 100000
|
4
|
+
|
5
|
+
def add_timeout_timer(loop)
|
6
|
+
timeout_timer = Coolio::TimerWatcher.new(60)
|
7
|
+
timeout_timer.on_timer do
|
8
|
+
timeout_timer.detach
|
9
|
+
timeout_timer = nil
|
10
|
+
end
|
11
|
+
loop.attach(timeout_timer)
|
12
|
+
timeout_timer
|
13
|
+
end
|
14
|
+
|
15
|
+
puts "start."
|
16
|
+
|
17
|
+
$start = Time.now
|
18
|
+
$timers = []
|
19
|
+
$loop = Cool.io::Loop.default
|
20
|
+
$times.times do
|
21
|
+
$timers << add_timeout_timer($loop)
|
22
|
+
end
|
23
|
+
|
24
|
+
$timeout_before = Time.now
|
25
|
+
timeout_timer = Coolio::TimerWatcher.new(1)
|
26
|
+
timeout_timer.on_timer do
|
27
|
+
$timeout_after = Time.now
|
28
|
+
|
29
|
+
timeout_timer.detach
|
30
|
+
$timers.each do |timer|
|
31
|
+
timer.detach
|
32
|
+
end
|
33
|
+
|
34
|
+
$finish = Time.now
|
35
|
+
delta = $finish - $start
|
36
|
+
delta -= $timeout_after - $timeout_before
|
37
|
+
puts "done."
|
38
|
+
puts "overhead: #{delta} seconds for #{$times} timers."
|
39
|
+
end
|
40
|
+
$loop.attach(timeout_timer)
|
41
|
+
|
42
|
+
$loop.run
|
43
|
+
|
44
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
# Copyright (C) 2014 Droonga Project
|
3
|
+
# Copyright (C) 2014-2015 Droonga Project
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -17,230 +17,289 @@
|
|
17
17
|
|
18
18
|
require "ostruct"
|
19
19
|
require "optparse"
|
20
|
-
require "open3"
|
21
20
|
require "socket"
|
21
|
+
require "coolio"
|
22
22
|
|
23
23
|
require "droonga/engine/version"
|
24
|
-
require "droonga/catalog_generator"
|
25
24
|
require "droonga/path"
|
26
|
-
require "droonga/
|
25
|
+
require "droonga/node_name"
|
26
|
+
require "droonga/data_absorber_client"
|
27
27
|
require "droonga/serf"
|
28
28
|
require "droonga/client"
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
puts "Start to absorb data from #{@options.source_host}"
|
37
|
-
puts " to #{@options.destination_host}"
|
38
|
-
puts " via #{@options.receiver_host} (this host)"
|
39
|
-
puts " dataset = #{@options.dataset}"
|
40
|
-
puts " port = #{@options.port}"
|
41
|
-
puts " tag = #{@options.tag}"
|
42
|
-
puts ""
|
43
|
-
puts "Absorbing..."
|
44
|
-
|
45
|
-
if @options.remote
|
46
|
-
absorb_on_remote
|
47
|
-
else
|
48
|
-
absorb_on_local
|
49
|
-
end
|
30
|
+
module Droonga
|
31
|
+
module Command
|
32
|
+
class AbsorbData
|
33
|
+
def run
|
34
|
+
@loop = Coolio::Loop.default
|
50
35
|
|
51
|
-
|
52
|
-
|
53
|
-
|
36
|
+
parse_options
|
37
|
+
assert_valid_options
|
38
|
+
trap_signals
|
54
39
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
"Host name of this cluster to be connected.") do |host|
|
75
|
-
options.destination_host = host
|
76
|
-
end
|
77
|
-
parser.on("--receiver-host=HOST",
|
78
|
-
"Host name of this computer.",
|
79
|
-
"(#{options.receiver_host})") do |host|
|
80
|
-
options.receiver_host = host
|
81
|
-
end
|
82
|
-
parser.on("--port=PORT", Integer,
|
83
|
-
"Port number of the source cluster to be connected.",
|
84
|
-
"(#{options.port})") do |port|
|
85
|
-
options.port = port
|
40
|
+
puts "Start to absorb data from #{@options.source_dataset} at #{source_node.to_s}"
|
41
|
+
puts " to #{@options.dataset} at #{destination_node.to_s}"
|
42
|
+
puts " via #{@options.receiver_host} (this host)"
|
43
|
+
puts ""
|
44
|
+
puts "Absorbing..."
|
45
|
+
|
46
|
+
#XXX If any command is received by the source node after changing of its role,
|
47
|
+
# the timestamp of last processed mesasge is unexpectedly updated by them.
|
48
|
+
# Be careful to not send any command to the source node on this timing!!
|
49
|
+
update_accept_messages_newer_than_timestamp
|
50
|
+
|
51
|
+
succeeded = absorb
|
52
|
+
|
53
|
+
if succeeded
|
54
|
+
puts "Done."
|
55
|
+
else
|
56
|
+
do_cancel
|
57
|
+
end
|
58
|
+
succeeded
|
86
59
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
options
|
60
|
+
|
61
|
+
private
|
62
|
+
def parse_options
|
63
|
+
options = OpenStruct.new
|
64
|
+
|
65
|
+
options.host = Socket.gethostname
|
66
|
+
options.port = DataAbsorberClient::DEFAULT_PORT
|
67
|
+
options.tag = DataAbsorberClient::DEFAULT_TAG
|
68
|
+
options.dataset = DataAbsorberClient::DEFAULT_DATASET
|
69
|
+
|
70
|
+
options.source_host = DataAbsorberClient::DEFAULT_HOST
|
71
|
+
options.source_port = DataAbsorberClient::DEFAULT_PORT
|
72
|
+
options.source_tag = DataAbsorberClient::DEFAULT_TAG
|
73
|
+
options.source_dataset = DataAbsorberClient::DEFAULT_DATASET
|
74
|
+
|
75
|
+
options.receiver_host = Socket.gethostname
|
76
|
+
|
77
|
+
options.messages_per_second = DataAbsorberClient::DEFAULT_MESSAGES_PER_SECOND
|
78
|
+
options.progress_interval_seconds = DataAbsorberClient::DEFAULT_PROGRESS_INTERVAL_SECONDS
|
79
|
+
|
80
|
+
options.verbose = false
|
81
|
+
|
82
|
+
parser = OptionParser.new
|
83
|
+
parser.version = Engine::VERSION
|
84
|
+
|
85
|
+
parser.separator("")
|
86
|
+
parser.separator("Destination node:")
|
87
|
+
parser.on("--host=HOST",
|
88
|
+
"Host name of the destination node.") do |host|
|
89
|
+
options.host = host
|
90
|
+
end
|
91
|
+
parser.on("--port=PORT", Integer,
|
92
|
+
"Port number of the destination node.",
|
93
|
+
"(#{options.port})") do |port|
|
94
|
+
options.port = port
|
95
|
+
end
|
96
|
+
parser.on("--tag=TAG", Integer,
|
97
|
+
"Tag name of the destination node.",
|
98
|
+
"(#{options.tag})") do |tag|
|
99
|
+
options.tag = tag
|
100
|
+
end
|
101
|
+
parser.on("--dataset=DATASET",
|
102
|
+
"Name of the destination dataset.",
|
103
|
+
"(#{options.dataset})") do |dataset|
|
104
|
+
options.dataset = dataset
|
105
|
+
end
|
106
|
+
|
107
|
+
parser.separator("")
|
108
|
+
parser.separator("Source node:")
|
109
|
+
parser.on("--source-host=HOST",
|
110
|
+
"Host name of the source node.",
|
111
|
+
"(#{options.source_host})") do |host|
|
112
|
+
options.source_host = host
|
113
|
+
end
|
114
|
+
parser.on("--source-port=PORT", Integer,
|
115
|
+
"Port number of the source node.",
|
116
|
+
"(#{options.source_port})") do |host|
|
117
|
+
options.source_host = host
|
118
|
+
end
|
119
|
+
parser.on("--source-tag=TAG",
|
120
|
+
"Tag name of the source node.",
|
121
|
+
"(#{options.source_tag})") do |tag|
|
122
|
+
options.source_tag = tag
|
123
|
+
end
|
124
|
+
parser.on("--source-dataset=DATASET",
|
125
|
+
"Name of the source dataset.",
|
126
|
+
"(#{options.source_dataset})") do |dataset|
|
127
|
+
options.source_dataset = dataset
|
128
|
+
end
|
129
|
+
|
130
|
+
parser.separator("")
|
131
|
+
parser.separator("Connection:")
|
132
|
+
parser.on("--receiver-host=HOST",
|
133
|
+
"Host name of this computer.",
|
134
|
+
"(#{options.receiver_host})") do |host|
|
135
|
+
options.receiver_host = host
|
136
|
+
end
|
137
|
+
|
138
|
+
parser.separator("")
|
139
|
+
parser.separator("Miscellaneous:")
|
140
|
+
parser.on("--records-per-second=N", Integer,
|
141
|
+
"Maximum number of records per second to be absorbed.",
|
142
|
+
"'#{Client::RateLimiter::NO_LIMIT}' means no limit.",
|
143
|
+
"(#{options.messages_per_second})") do |n|
|
144
|
+
options.messages_per_second = n
|
145
|
+
end
|
146
|
+
parser.on("--progress-interval-seconds=N", Integer,
|
147
|
+
"Interval seconds to report progress.",
|
148
|
+
"(#{options.progress_interval_seconds})") do |n|
|
149
|
+
options.progress_interval_seconds = n
|
150
|
+
end
|
151
|
+
parser.on("--[no-]verbose",
|
152
|
+
"Output details for internal operations.",
|
153
|
+
"(#{options.verbose})") do |verbose|
|
154
|
+
options.verbose = verbose
|
155
|
+
end
|
156
|
+
|
157
|
+
parser.separator("")
|
158
|
+
parser.separator("For backward compatibility:")
|
159
|
+
parser.on("--destination-host=HOST",
|
160
|
+
"Alias to \"--host\".") do |host|
|
161
|
+
options.host = host
|
162
|
+
end
|
163
|
+
|
164
|
+
parser.parse!(ARGV)
|
165
|
+
@options = options
|
91
166
|
end
|
92
167
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
168
|
+
def assert_valid_options
|
169
|
+
unless @options.source_host
|
170
|
+
raise "You must specify the source host via --source-host option."
|
171
|
+
end
|
172
|
+
unless @options.host
|
173
|
+
raise "You must specify the destination host via --host option."
|
174
|
+
end
|
99
175
|
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
176
|
+
|
177
|
+
def source_node
|
178
|
+
@source_node ||= NodeName.new(:host => @options.source_host,
|
179
|
+
:port => @options.source_port,
|
180
|
+
:tag => @options.source_tag)
|
104
181
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
182
|
+
|
183
|
+
def destination_node
|
184
|
+
@destination_node ||= NodeName.new(:host => @options.host,
|
185
|
+
:port => @options.port,
|
186
|
+
:tag => @options.tag)
|
110
187
|
end
|
111
188
|
|
112
|
-
|
113
|
-
|
114
|
-
|
189
|
+
def source_node_serf
|
190
|
+
@source_node_serf ||= Serf.new(source_node.to_s,
|
191
|
+
:verbose => @options.verbose)
|
192
|
+
end
|
115
193
|
|
116
|
-
|
117
|
-
|
118
|
-
|
194
|
+
def destination_node_serf
|
195
|
+
@destination_node_serf ||= Serf.new(destination_node.to_s,
|
196
|
+
:verbose => @options.verbose)
|
119
197
|
end
|
120
|
-
|
121
|
-
|
198
|
+
|
199
|
+
def absorber
|
200
|
+
@absorber ||= prepare_absorber
|
122
201
|
end
|
123
|
-
end
|
124
202
|
|
125
|
-
|
126
|
-
|
127
|
-
|
203
|
+
def prepare_absorber
|
204
|
+
absorber_options = {
|
205
|
+
:host => @options.host,
|
206
|
+
:port => @options.port,
|
207
|
+
:tag => @options.tag,
|
208
|
+
:dataset => @options.dataset,
|
128
209
|
|
129
|
-
|
130
|
-
|
131
|
-
|
210
|
+
:source_host => @options.source_host,
|
211
|
+
:source_port => @options.source_port,
|
212
|
+
:source_tag => @options.source_tag,
|
213
|
+
:source_dataset => @options.source_dataset,
|
132
214
|
|
133
|
-
|
134
|
-
serf = Droonga::Serf.new(nil, target)
|
135
|
-
result = serf.send_query(command, options)
|
136
|
-
#puts result[:result]
|
137
|
-
puts result[:error] unless result[:error].empty?
|
138
|
-
result[:response]
|
139
|
-
end
|
215
|
+
:receiver_host => @options.receiver_host,
|
140
216
|
|
141
|
-
|
142
|
-
|
143
|
-
end
|
217
|
+
:messages_per_second => @options.messages_per_second,
|
218
|
+
:progress_interval_seconds => @options.progress_interval_seconds,
|
144
219
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
:tag => @options.tag,
|
153
|
-
:messages_per_second => @options.messages_per_second,
|
154
|
-
}
|
155
|
-
Droonga::DataAbsorber.new(absorber_options)
|
156
|
-
end
|
220
|
+
:client_options => {
|
221
|
+
:backend => :coolio,
|
222
|
+
:loop => @loop,
|
223
|
+
},
|
224
|
+
}
|
225
|
+
DataAbsorberClient.new(absorber_options)
|
226
|
+
end
|
157
227
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
"dataset" => @options.dataset,
|
166
|
-
"messages_per_second" => @options.messages_per_second)
|
167
|
-
last_progress = ""
|
168
|
-
while true
|
169
|
-
sleep(3)
|
170
|
-
response = run_remote_command(destination_node, "report_status",
|
171
|
-
"node" => destination_node,
|
172
|
-
"key" => "absorbing")
|
173
|
-
if response
|
174
|
-
absorbing = response["value"]
|
175
|
-
break unless absorbing
|
176
|
-
end
|
177
|
-
|
178
|
-
progress = absorber.report_progress(start_time_in_seconds)
|
179
|
-
if progress
|
180
|
-
printf("%s", "#{" " * last_progress.size}\r")
|
181
|
-
printf("%s", "#{progress}\r")
|
228
|
+
def absorb
|
229
|
+
last_progress = nil
|
230
|
+
absorber.run do |progress|
|
231
|
+
if last_progress
|
232
|
+
printf("%s", "#{" " * last_progress[:message].size}\r")
|
233
|
+
end
|
234
|
+
printf("%s", "#{progress[:message]}\r")
|
182
235
|
last_progress = progress
|
183
236
|
end
|
237
|
+
@loop.run
|
238
|
+
|
239
|
+
if absorber.error_message
|
240
|
+
puts(absorber.error_message)
|
241
|
+
return false
|
242
|
+
end
|
243
|
+
|
244
|
+
puts ""
|
245
|
+
true
|
184
246
|
end
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
247
|
+
|
248
|
+
GETTING_LAST_MESSAGE_TIMESTAMP_MAX_RETRY_COUNT = 10
|
249
|
+
GETTING_LAST_MESSAGE_TIMESTAMP_RETRY_INTERVAL_SECONDS = 10
|
250
|
+
|
251
|
+
def try_get_last_message_timestamp(retry_count=0)
|
252
|
+
puts "Getting the timestamp of the last processed message in the source node..."
|
253
|
+
timestamp = source_node_serf.last_message_timestamp
|
254
|
+
unless timestamp
|
255
|
+
if retry_count < GETTING_LAST_MESSAGE_TIMESTAMP_MAX_RETRY_COUNT
|
256
|
+
puts "Failed. Retrying..."
|
257
|
+
sleep(GETTING_LAST_MESSAGE_TIMESTAMP_RETRY_INTERVAL_SECONDS)
|
258
|
+
timestamp = try_get_last_message_timestamp(retry_count + 1)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
timestamp
|
198
262
|
end
|
199
|
-
end
|
200
263
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
264
|
+
def update_accept_messages_newer_than_timestamp
|
265
|
+
timestamp = try_get_last_message_timestamp
|
266
|
+
if timestamp and not timestamp.empty?
|
267
|
+
puts "The timestamp of the last processed message in the source node: #{timestamp}"
|
268
|
+
puts "Setting the destination node to ignore messages older than the timestamp..."
|
269
|
+
destination_node_serf.ensure_restarted do
|
270
|
+
destination_node_serf.send_query("accept_messages_newer_than",
|
271
|
+
"node" => destination_node.to_s,
|
272
|
+
"timestamp" => timestamp)
|
273
|
+
end
|
206
274
|
else
|
207
|
-
|
275
|
+
$stderr.puts("WARNING: Couldn't get the time stamp of " +
|
276
|
+
"the last processed message from the source node. " +
|
277
|
+
"Any message will be forwarded to the destination node.")
|
208
278
|
end
|
209
|
-
printf("%s", "#{" " * last_progress.size}\r")
|
210
|
-
printf("%s", "#{progress}\r")
|
211
|
-
last_progress = progress
|
212
279
|
end
|
213
|
-
response = run_remote_command(source_node, "report_status",
|
214
|
-
"node" => source_node,
|
215
|
-
"key" => "last_processed_message_timestamp")
|
216
|
-
timestamp = response["value"]
|
217
|
-
puts "The timestamp of the last processed message in the source node: #{timestamp}"
|
218
|
-
if timestamp and not timestamp.empty?
|
219
|
-
status = NodeStatus.new
|
220
|
-
status.set(:effective_message_timestamp, timestamp)
|
221
|
-
end
|
222
|
-
end
|
223
280
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
281
|
+
def trap_signals
|
282
|
+
trap(:TERM) do
|
283
|
+
trap(:TERM, "DEFAULT")
|
284
|
+
do_cancel
|
285
|
+
end
|
229
286
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
287
|
+
trap(:INT) do
|
288
|
+
trap(:INT, "DEFAULT")
|
289
|
+
do_cancel
|
290
|
+
end
|
234
291
|
|
235
|
-
|
236
|
-
|
237
|
-
|
292
|
+
trap(:QUIT) do
|
293
|
+
trap(:QUIT, "DEFAULT")
|
294
|
+
do_cancel
|
295
|
+
end
|
238
296
|
end
|
239
|
-
end
|
240
297
|
|
241
|
-
|
242
|
-
|
298
|
+
def do_cancel
|
299
|
+
#XXX we have to write more codes to cancel remote processes!
|
300
|
+
end
|
301
|
+
end
|
243
302
|
end
|
244
303
|
end
|
245
304
|
|
246
|
-
|
305
|
+
exit(Droonga::Command::AbsorbData.new.run)
|