droonga-engine 1.0.4 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/Rakefile +1 -1
- data/benchmark/benchmark.rb +1 -1
- data/benchmark/utils.rb +1 -1
- data/benchmark/watch/benchmark-notify.rb +1 -1
- data/benchmark/watch/benchmark-publish.rb +1 -1
- data/benchmark/watch/benchmark-scan.rb +1 -1
- data/bin/droonga-engine +1 -1
- data/bin/droonga-engine-absorb-data +48 -8
- data/bin/droonga-engine-catalog-generate +1 -1
- data/bin/droonga-engine-catalog-modify +1 -1
- data/bin/droonga-engine-data-publisher +66 -0
- data/bin/droonga-engine-join +72 -17
- data/bin/droonga-engine-serf-event-handler +1 -1
- data/bin/droonga-engine-service +1 -1
- data/bin/droonga-engine-unjoin +11 -4
- data/bin/droonga-engine-worker +20 -0
- data/doc/text/news.md +8 -0
- data/droonga-engine.gemspec +3 -3
- data/lib/droonga/adapter.rb +1 -1
- data/lib/droonga/adapter_runner.rb +1 -1
- data/lib/droonga/address.rb +69 -0
- data/lib/droonga/buffered_tcp_socket.rb +44 -22
- data/lib/droonga/catalog/base.rb +1 -1
- data/lib/droonga/catalog/collection_volume.rb +1 -1
- data/lib/droonga/catalog/dataset.rb +8 -8
- data/lib/droonga/catalog/errors.rb +1 -1
- data/lib/droonga/catalog/schema.rb +1 -1
- data/lib/droonga/catalog/single_volume.rb +6 -8
- data/lib/droonga/catalog/slice.rb +1 -1
- data/lib/droonga/catalog/version1.rb +2 -2
- data/lib/droonga/catalog/version2.rb +6 -6
- data/lib/droonga/catalog/version2_validator.rb +1 -1
- data/lib/droonga/catalog/volume.rb +1 -1
- data/lib/droonga/catalog/volume_collection.rb +2 -2
- data/lib/droonga/catalog_generator.rb +49 -53
- data/lib/droonga/catalog_loader.rb +1 -1
- data/lib/droonga/collector.rb +1 -1
- data/lib/droonga/collector_message.rb +1 -1
- data/lib/droonga/collector_runner.rb +1 -1
- data/lib/droonga/collectors/and.rb +1 -1
- data/lib/droonga/collectors/or.rb +1 -1
- data/lib/droonga/collectors/sum.rb +1 -1
- data/lib/droonga/collectors.rb +1 -1
- data/lib/droonga/command/droonga_engine.rb +103 -55
- data/lib/droonga/command/droonga_engine_service.rb +22 -67
- data/lib/droonga/command/droonga_engine_worker.rb +232 -0
- data/lib/droonga/command/serf_event_handler.rb +126 -46
- data/lib/droonga/data_absorber.rb +32 -14
- data/lib/droonga/dispatcher.rb +15 -11
- data/lib/droonga/distributed_command_planner.rb +1 -1
- data/lib/droonga/distributor.rb +1 -1
- data/lib/droonga/engine/version.rb +2 -2
- data/lib/droonga/engine.rb +8 -3
- data/lib/droonga/engine_state.rb +15 -6
- data/lib/droonga/error.rb +1 -1
- data/lib/droonga/error_messages.rb +1 -1
- data/lib/droonga/event_loop.rb +1 -1
- data/lib/droonga/farm.rb +9 -1
- data/lib/droonga/file_observer.rb +1 -1
- data/lib/droonga/fluent_message_receiver.rb +11 -5
- data/lib/droonga/fluent_message_sender.rb +14 -17
- data/lib/droonga/forwarder.rb +23 -13
- data/lib/droonga/handler.rb +1 -1
- data/lib/droonga/handler_message.rb +1 -1
- data/lib/droonga/handler_messenger.rb +2 -2
- data/lib/droonga/handler_runner.rb +2 -2
- data/lib/droonga/input_message.rb +1 -1
- data/lib/droonga/internal_fluent_message_receiver.rb +3 -2
- data/lib/droonga/job_protocol.rb +1 -1
- data/lib/droonga/job_pusher.rb +1 -1
- data/lib/droonga/job_receiver.rb +1 -1
- data/lib/droonga/line_buffer.rb +1 -1
- data/lib/droonga/live_nodes_list_loader.rb +1 -1
- data/lib/droonga/loggable.rb +1 -1
- data/lib/droonga/logger.rb +3 -3
- data/lib/droonga/message_matcher.rb +1 -1
- data/lib/droonga/output_message.rb +1 -1
- data/lib/droonga/path.rb +5 -1
- data/lib/droonga/planner.rb +1 -1
- data/lib/droonga/pluggable.rb +1 -1
- data/lib/droonga/plugin/metadata/adapter_input_message.rb +1 -1
- data/lib/droonga/plugin/metadata/adapter_output_message.rb +1 -1
- data/lib/droonga/plugin/metadata/collector_message.rb +1 -1
- data/lib/droonga/plugin/metadata/handler_action.rb +1 -1
- data/lib/droonga/plugin/metadata/input_message.rb +1 -1
- data/lib/droonga/plugin.rb +2 -1
- data/lib/droonga/plugin_loader.rb +1 -1
- data/lib/droonga/plugin_registry.rb +3 -1
- data/lib/droonga/plugins/basic.rb +1 -1
- data/lib/droonga/plugins/crud.rb +1 -1
- data/lib/droonga/plugins/dump.rb +13 -2
- data/lib/droonga/plugins/error.rb +1 -1
- data/lib/droonga/plugins/groonga/column_create.rb +1 -1
- data/lib/droonga/plugins/groonga/column_list.rb +1 -1
- data/lib/droonga/plugins/groonga/column_remove.rb +1 -1
- data/lib/droonga/plugins/groonga/column_rename.rb +1 -1
- data/lib/droonga/plugins/groonga/delete.rb +1 -1
- data/lib/droonga/plugins/groonga/generic_command.rb +1 -1
- data/lib/droonga/plugins/groonga/generic_response.rb +1 -1
- data/lib/droonga/plugins/groonga/select.rb +1 -1
- data/lib/droonga/plugins/groonga/table_create.rb +1 -1
- data/lib/droonga/plugins/groonga/table_list.rb +1 -1
- data/lib/droonga/plugins/groonga/table_remove.rb +1 -1
- data/lib/droonga/plugins/groonga.rb +1 -1
- data/lib/droonga/plugins/search/distributed_search_planner.rb +1 -1
- data/lib/droonga/plugins/search.rb +1 -1
- data/lib/droonga/plugins/system.rb +1 -1
- data/lib/droonga/plugins/watch.rb +1 -1
- data/lib/droonga/{service_control_protocol.rb → process_control_protocol.rb} +2 -2
- data/lib/droonga/process_supervisor.rb +91 -0
- data/lib/droonga/processor.rb +1 -1
- data/lib/droonga/reducer.rb +1 -1
- data/lib/droonga/replier.rb +2 -2
- data/lib/droonga/safe_file_writer.rb +1 -1
- data/lib/droonga/schema_applier.rb +1 -1
- data/lib/droonga/searcher/mecab_filter.rb +1 -1
- data/lib/droonga/searcher.rb +31 -19
- data/lib/droonga/serf.rb +81 -14
- data/lib/droonga/serf_downloader.rb +2 -2
- data/lib/droonga/session.rb +1 -1
- data/lib/droonga/single_step.rb +1 -1
- data/lib/droonga/single_step_definition.rb +1 -1
- data/lib/droonga/slice.rb +30 -28
- data/lib/droonga/status_code.rb +1 -1
- data/lib/droonga/step_runner.rb +1 -1
- data/lib/droonga/supervisor.rb +170 -0
- data/lib/droonga/sweeper.rb +1 -1
- data/lib/droonga/test/stub_handler.rb +1 -1
- data/lib/droonga/test/stub_handler_message.rb +1 -1
- data/lib/droonga/test/stub_handler_messenger.rb +1 -1
- data/lib/droonga/test/stub_planner.rb +1 -1
- data/lib/droonga/test.rb +1 -1
- data/lib/droonga/watch_schema.rb +2 -2
- data/lib/droonga/watcher.rb +1 -1
- data/lib/droonga/worker_process_agent.rb +111 -0
- data/sample/cluster/Rakefile +150 -0
- data/test/command/config/default/catalog.json +1 -34
- data/test/command/config/version1/catalog.json +3 -12
- data/test/command/run-test.rb +1 -1
- data/test/command/suite/dump/column/index.expected +19 -82
- data/test/command/suite/dump/column/scalar.expected +5 -36
- data/test/command/suite/dump/column/vector.expected +5 -39
- data/test/command/suite/dump/record/vector/reference.expected +24 -93
- data/test/command/suite/dump/table/array.expected +0 -19
- data/test/command/suite/dump/table/double_array_trie.expected +0 -20
- data/test/command/suite/dump/table/hash.expected +0 -20
- data/test/command/suite/dump/table/patricia_trie.expected +0 -20
- data/test/command/suite/search/condition/query/nonexistent_column.expected +0 -11
- data/test/command/suite/search/condition/query/syntax_error.expected +0 -11
- data/test/command/suite/search/error/unknown-source.expected +0 -12
- data/test/command/suite/search/output/attributes/invalid.expected +0 -10
- data/test/command/suite/search/output/attributes/reference_vector.catalog.json +27 -0
- data/test/command/suite/search/output/attributes/reference_vector.expected +30 -0
- data/test/command/suite/search/output/attributes/reference_vector.test +32 -0
- data/test/command/suite/watch/subscribe.catalog.json +23 -0
- data/test/command/suite/watch/subscribe.test +2 -0
- data/test/command/suite/watch/unsubscribe.catalog.json +23 -0
- data/test/command/suite/watch/unsubscribe.test +2 -0
- data/test/performance/run-test.rb +1 -1
- data/test/unit/catalog/test_collection_volume.rb +1 -1
- data/test/unit/catalog/test_dataset.rb +1 -1
- data/test/unit/catalog/test_schema.rb +1 -1
- data/test/unit/catalog/test_single_volume.rb +27 -19
- data/test/unit/catalog/test_slice.rb +2 -2
- data/test/unit/catalog/test_version1.rb +1 -1
- data/test/unit/catalog/test_version2.rb +1 -1
- data/test/unit/catalog/test_version2_validator.rb +1 -1
- data/test/unit/catalog/test_volume_collection.rb +1 -1
- data/test/unit/helper/distributed_search_planner_helper.rb +1 -1
- data/test/unit/helper/fixture.rb +1 -1
- data/test/unit/helper/plugin_helper.rb +1 -1
- data/test/unit/helper/sandbox.rb +1 -1
- data/test/unit/helper/stub_worker.rb +1 -1
- data/test/unit/helper/watch_helper.rb +1 -1
- data/test/unit/helper.rb +1 -1
- data/test/unit/plugins/crud/test_add.rb +1 -1
- data/test/unit/plugins/groonga/select/test_adapter_input.rb +1 -1
- data/test/unit/plugins/groonga/select/test_adapter_output.rb +1 -1
- data/test/unit/plugins/groonga/test_column_create.rb +1 -1
- data/test/unit/plugins/groonga/test_column_list.rb +1 -1
- data/test/unit/plugins/groonga/test_column_remove.rb +1 -1
- data/test/unit/plugins/groonga/test_column_rename.rb +1 -1
- data/test/unit/plugins/groonga/test_delete.rb +1 -1
- data/test/unit/plugins/groonga/test_table_create.rb +1 -1
- data/test/unit/plugins/groonga/test_table_list.rb +1 -1
- data/test/unit/plugins/groonga/test_table_remove.rb +1 -1
- data/test/unit/plugins/search/planner/test_basic.rb +1 -1
- data/test/unit/plugins/search/planner/test_group_by.rb +1 -1
- data/test/unit/plugins/search/planner/test_output.rb +1 -1
- data/test/unit/plugins/search/planner/test_sort_by.rb +1 -1
- data/test/unit/plugins/search/test_collector.rb +1 -1
- data/test/unit/plugins/search/test_handler.rb +1 -1
- data/test/unit/plugins/search/test_planner.rb +1 -1
- data/test/unit/plugins/system/test_status.rb +1 -1
- data/test/unit/plugins/test_basic.rb +1 -1
- data/test/unit/plugins/test_groonga.rb +1 -1
- data/test/unit/plugins/test_watch.rb +1 -1
- data/test/unit/run-test.rb +1 -1
- data/test/unit/test_address.rb +53 -0
- data/test/unit/test_catalog_generator.rb +59 -1
- data/test/unit/test_line_buffer.rb +1 -1
- data/test/unit/test_message_matcher.rb +1 -1
- data/test/unit/test_schema_applier.rb +1 -1
- data/test/unit/test_sweeper.rb +1 -1
- data/test/unit/test_watch_schema.rb +1 -1
- data/test/unit/test_watcher.rb +1 -1
- metadata +39 -24
- data/lib/droonga/server.rb +0 -45
- data/lib/droonga/worker.rb +0 -66
- data/sample/cluster/catalog.json +0 -42
- data/test/command/config/default/fluentd.conf +0 -11
- data/test/command/config/version1/fluentd.conf +0 -11
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
require "json"
|
17
17
|
|
@@ -34,14 +34,22 @@ module Droonga
|
|
34
34
|
@serf = ENV["SERF"] || Serf.path
|
35
35
|
@serf_rpc_address = ENV["SERF_RPC_ADDRESS"] || "127.0.0.1:7373"
|
36
36
|
@serf_name = ENV["SERF_SELF_NAME"]
|
37
|
+
@response = {
|
38
|
+
"log" => []
|
39
|
+
}
|
37
40
|
end
|
38
41
|
|
39
42
|
def run
|
40
43
|
parse_event
|
41
|
-
|
44
|
+
unless event_for_me?
|
45
|
+
log(" => ignoring event not for me")
|
46
|
+
output_response
|
47
|
+
return true
|
48
|
+
end
|
42
49
|
|
43
50
|
process_event
|
44
51
|
output_live_nodes
|
52
|
+
output_response
|
45
53
|
true
|
46
54
|
end
|
47
55
|
|
@@ -53,11 +61,13 @@ module Droonga
|
|
53
61
|
when "user"
|
54
62
|
@event_sub_name = ENV["SERF_USER_EVENT"]
|
55
63
|
@payload = JSON.parse($stdin.gets)
|
56
|
-
|
64
|
+
log("event sub name = #{@event_sub_name}")
|
57
65
|
when "query"
|
58
66
|
@event_sub_name = ENV["SERF_QUERY_NAME"]
|
59
67
|
@payload = JSON.parse($stdin.gets)
|
60
|
-
|
68
|
+
log("event sub name = #{@event_sub_name}")
|
69
|
+
when "member-join", "member-leave", "member-update", "member-reap"
|
70
|
+
output_live_nodes
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
@@ -72,6 +82,8 @@ module Droonga
|
|
72
82
|
case @event_sub_name
|
73
83
|
when "change_role"
|
74
84
|
save_status(:role, @payload["role"])
|
85
|
+
when "report_status"
|
86
|
+
report_status
|
75
87
|
when "join"
|
76
88
|
join
|
77
89
|
when "set_replicas"
|
@@ -82,9 +94,17 @@ module Droonga
|
|
82
94
|
remove_replicas
|
83
95
|
when "absorb_data"
|
84
96
|
absorb_data
|
97
|
+
when "publish_catalog"
|
98
|
+
publish_catalog
|
99
|
+
when "unpublish_catalog"
|
100
|
+
unpublish_catalog
|
85
101
|
end
|
86
102
|
end
|
87
103
|
|
104
|
+
def output_response
|
105
|
+
puts JSON.generate(@response)
|
106
|
+
end
|
107
|
+
|
88
108
|
def host
|
89
109
|
@serf_name.split(":").first
|
90
110
|
end
|
@@ -96,9 +116,13 @@ module Droonga
|
|
96
116
|
hosts
|
97
117
|
end
|
98
118
|
|
119
|
+
def report_status
|
120
|
+
@response["value"] = status(@payload["key"].to_sym)
|
121
|
+
end
|
122
|
+
|
99
123
|
def join
|
100
124
|
type = @payload["type"]
|
101
|
-
|
125
|
+
log("type = #{type}")
|
102
126
|
case type
|
103
127
|
when "replica"
|
104
128
|
join_as_replica
|
@@ -106,55 +130,106 @@ module Droonga
|
|
106
130
|
end
|
107
131
|
|
108
132
|
def join_as_replica
|
109
|
-
|
110
|
-
return unless
|
133
|
+
source_node = @payload["source"]
|
134
|
+
return unless source_node
|
111
135
|
|
112
|
-
|
136
|
+
log("source_node = #{source_node}")
|
113
137
|
|
114
|
-
|
115
|
-
|
138
|
+
source_host = source_node.split(":").first
|
139
|
+
|
140
|
+
# fetch_port = @payload["fetch_port"]
|
141
|
+
# catalog = fetch_catalog(source_node, fetch_port)
|
142
|
+
catalog = JSON.parse(Path.catalog.read) #XXX workaround until "fetch" become available
|
143
|
+
|
144
|
+
generator = create_current_catalog_generator(catalog)
|
145
|
+
dataset = generator.dataset_for_host(source_host) ||
|
116
146
|
generator.dataset_for_host(host)
|
117
147
|
return unless dataset
|
118
148
|
|
149
|
+
# restart self with the fetched catalog.
|
150
|
+
SafeFileWriter.write(Path.catalog, JSON.pretty_generate(catalog))
|
151
|
+
|
119
152
|
dataset_name = dataset.name
|
120
153
|
tag = dataset.replicas.tag
|
121
154
|
port = dataset.replicas.port
|
122
155
|
other_hosts = dataset.replicas.hosts
|
123
156
|
|
124
|
-
|
125
|
-
|
126
|
-
|
157
|
+
log("dataset = #{dataset_name}")
|
158
|
+
log("port = #{port}")
|
159
|
+
log("tag = #{tag}")
|
127
160
|
|
128
161
|
if @payload["copy"]
|
129
|
-
|
162
|
+
log("starting to copy data from #{source_host}")
|
130
163
|
|
131
164
|
modify_catalog do |modifier|
|
132
165
|
modifier.datasets[dataset_name].replicas.hosts = [host]
|
133
166
|
end
|
134
|
-
sleep(
|
167
|
+
sleep(5) #TODO: wait for restart. this should be done more safely, to avoid starting of absorbing with old catalog.json.
|
135
168
|
|
169
|
+
save_status(:absorbing, true)
|
136
170
|
DataAbsorber.absorb(:dataset => dataset_name,
|
137
|
-
:source_host =>
|
171
|
+
:source_host => source_host,
|
138
172
|
:destination_host => host,
|
139
173
|
:port => port,
|
140
174
|
:tag => tag)
|
175
|
+
delete_status(:absorbing)
|
141
176
|
sleep(1)
|
142
177
|
end
|
143
178
|
|
144
|
-
|
179
|
+
log("joining to the cluster: update myself")
|
145
180
|
|
146
181
|
modify_catalog do |modifier|
|
147
182
|
modifier.datasets[dataset_name].replicas.hosts += other_hosts
|
148
183
|
modifier.datasets[dataset_name].replicas.hosts.uniq!
|
149
184
|
end
|
150
|
-
|
185
|
+
end
|
186
|
+
|
187
|
+
def fetch_catalog(source_node, port)
|
188
|
+
source_host = source_node.split(":").first
|
189
|
+
|
190
|
+
url = "http://#{source_host}:#{port}"
|
191
|
+
connection = Faraday.new(url) do |builder|
|
192
|
+
builder.response(:follow_redirects)
|
193
|
+
builder.adapter(Faraday.default_adapter)
|
194
|
+
end
|
195
|
+
response = connection.get("/catalog.json")
|
196
|
+
catalog = response.body
|
197
|
+
|
198
|
+
JSON.parse(catalog)
|
199
|
+
end
|
200
|
+
|
201
|
+
def publish_catalog
|
202
|
+
port = @payload["port"]
|
203
|
+
return unless port
|
204
|
+
|
205
|
+
env = {}
|
206
|
+
publisher_command_line = [
|
207
|
+
"droonga-engine-data-publisher",
|
208
|
+
"--base-dir", Path.base.to_s,
|
209
|
+
"--port", port.to_s,
|
210
|
+
"--published-file", Path.catalog.to_s
|
211
|
+
]
|
212
|
+
pid = spawn(env, *publisher_command_line)
|
213
|
+
Process.detach(pid)
|
214
|
+
sleep(1) # wait until the directory is published
|
215
|
+
|
216
|
+
published_dir = Path.published(port)
|
217
|
+
pid_file = published_dir + ".pid"
|
218
|
+
|
219
|
+
File.open(pid_file.to_s, "w") do |file|
|
220
|
+
file.puts(pid)
|
221
|
+
end
|
222
|
+
end
|
151
223
|
|
152
|
-
|
224
|
+
def unpublish_catalog
|
225
|
+
port = @payload["port"]
|
226
|
+
return unless port
|
153
227
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
228
|
+
published_dir = Path.published(port)
|
229
|
+
pid_file = published_dir + ".pid"
|
230
|
+
pid = pid_file.read.to_i
|
231
|
+
|
232
|
+
Process.kill("INT", pid)
|
158
233
|
end
|
159
234
|
|
160
235
|
def set_replicas
|
@@ -164,7 +239,7 @@ module Droonga
|
|
164
239
|
hosts = given_hosts
|
165
240
|
return unless hosts
|
166
241
|
|
167
|
-
|
242
|
+
log("new replicas: #{hosts.join(",")}")
|
168
243
|
|
169
244
|
modify_catalog do |modifier|
|
170
245
|
modifier.datasets[dataset].replicas.hosts = hosts
|
@@ -181,7 +256,7 @@ module Droonga
|
|
181
256
|
hosts -= [host]
|
182
257
|
return if hosts.empty?
|
183
258
|
|
184
|
-
|
259
|
+
log("adding replicas: #{hosts.join(",")}")
|
185
260
|
|
186
261
|
modify_catalog do |modifier|
|
187
262
|
modifier.datasets[dataset].replicas.hosts += hosts
|
@@ -196,7 +271,7 @@ module Droonga
|
|
196
271
|
hosts = given_hosts
|
197
272
|
return unless hosts
|
198
273
|
|
199
|
-
|
274
|
+
log("removing replicas: #{hosts.join(",")}")
|
200
275
|
|
201
276
|
modify_catalog do |modifier|
|
202
277
|
modifier.datasets[dataset].replicas.hosts -= hosts
|
@@ -209,19 +284,17 @@ module Droonga
|
|
209
284
|
SafeFileWriter.write(Path.catalog, JSON.pretty_generate(generator.generate))
|
210
285
|
end
|
211
286
|
|
212
|
-
def create_current_catalog_generator
|
213
|
-
current_catalog
|
287
|
+
def create_current_catalog_generator(current_catalog=nil)
|
288
|
+
current_catalog ||= JSON.parse(Path.catalog.read)
|
214
289
|
generator = CatalogGenerator.new
|
215
290
|
generator.load(current_catalog)
|
216
291
|
end
|
217
292
|
|
218
293
|
def absorb_data
|
219
|
-
return unless event_for_me?
|
220
|
-
|
221
294
|
source = @payload["source"]
|
222
295
|
return unless source
|
223
296
|
|
224
|
-
|
297
|
+
log("start to absorb data from #{source}")
|
225
298
|
|
226
299
|
dataset_name = @payload["dataset"]
|
227
300
|
port = @payload["port"]
|
@@ -240,29 +313,22 @@ module Droonga
|
|
240
313
|
tag = dataset.replicas.tag
|
241
314
|
end
|
242
315
|
|
243
|
-
|
244
|
-
|
245
|
-
|
316
|
+
log("dataset = #{dataset_name}")
|
317
|
+
log("port = #{port}")
|
318
|
+
log("tag = #{tag}")
|
246
319
|
|
320
|
+
save_status(:absorbing, true)
|
247
321
|
DataAbsorber.absorb(:dataset => dataset_name,
|
248
322
|
:source_host => source,
|
249
323
|
:destination_host => host,
|
250
324
|
:port => port,
|
251
|
-
:tag => tag
|
325
|
+
:tag => tag,
|
326
|
+
:client => "droonga-send")
|
327
|
+
delete_status(:absorbing)
|
252
328
|
end
|
253
329
|
|
254
330
|
def live_nodes
|
255
|
-
|
256
|
-
members = `#{@serf} members -rpc-addr #{@serf_rpc_address}`
|
257
|
-
members.each_line do |member|
|
258
|
-
name, address, status, = member.strip.split(/\s+/)
|
259
|
-
if status == "alive"
|
260
|
-
nodes[name] = {
|
261
|
-
"serfAddress" => address,
|
262
|
-
}
|
263
|
-
end
|
264
|
-
end
|
265
|
-
nodes
|
331
|
+
Serf.live_nodes(@serf_name)
|
266
332
|
end
|
267
333
|
|
268
334
|
def output_live_nodes
|
@@ -272,11 +338,25 @@ module Droonga
|
|
272
338
|
SafeFileWriter.write(path, file_contents)
|
273
339
|
end
|
274
340
|
|
341
|
+
def status(key)
|
342
|
+
Serf.status(key)
|
343
|
+
end
|
344
|
+
|
275
345
|
def save_status(key, value)
|
276
346
|
status = Serf.load_status
|
277
347
|
status[key] = value
|
278
348
|
SafeFileWriter.write(Serf.status_file, JSON.pretty_generate(status))
|
279
349
|
end
|
350
|
+
|
351
|
+
def delete_status(key)
|
352
|
+
status = Serf.load_status
|
353
|
+
status.delete(key)
|
354
|
+
SafeFileWriter.write(Serf.status_file, JSON.pretty_generate(status))
|
355
|
+
end
|
356
|
+
|
357
|
+
def log(message)
|
358
|
+
@response["log"] << message
|
359
|
+
end
|
280
360
|
end
|
281
361
|
end
|
282
362
|
end
|
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
require "open3"
|
17
17
|
|
@@ -28,25 +28,43 @@ module Droonga
|
|
28
28
|
drndump_options += ["--receiver-host", params[:destination_host]]
|
29
29
|
drndump_options += ["--receiver-port", params[:receiver_port].to_s] if params[:receiver_port]
|
30
30
|
|
31
|
+
#TODO: We should use droonga-send instead of droonga-request,
|
32
|
+
# because droonga-request is too slow.
|
33
|
+
# However, to do it, we have to implement an API to know
|
34
|
+
# that all messages sent by droonga-send are completely
|
35
|
+
# processed.
|
31
36
|
client = params[:client] || "droonga-request"
|
32
37
|
client_options = []
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
if client.include?("droonga-request")
|
39
|
+
client_options += ["--host", params[:destination_host]]
|
40
|
+
client_options += ["--port", params[:port].to_s] if params[:port]
|
41
|
+
client_options += ["--tag", params[:tag]] if params[:tag]
|
42
|
+
client_options += ["--receiver-host", params[:destination_host]]
|
43
|
+
client_options += ["--receiver-port", params[:receiver_port].to_s] if params[:receiver_port]
|
44
|
+
elsif client.include?("droonga-send")
|
45
|
+
#XXX Don't use round-robin with multiple endpoints
|
46
|
+
# even if there are too much data.
|
47
|
+
# Schema and indexes must be sent to just one endpoint
|
48
|
+
# to keep their order, but currently there is no way to
|
49
|
+
# extract only schema and indexes via drndump.
|
50
|
+
# So, we always use just one endpoint for now,
|
51
|
+
# even if there are too much data.
|
52
|
+
server = "droonga:#{params[:destination_host]}"
|
53
|
+
server = "#{server}:#{params[:port].to_s}" if params[:port]
|
54
|
+
server = "#{server}/#{params[:tag].to_s}" if params[:tag]
|
55
|
+
client_options += ["--server", server]
|
56
|
+
else
|
57
|
+
raise ArgumentError.new("Unknwon type client: #{client}")
|
58
|
+
end
|
38
59
|
|
39
60
|
drndump_command_line = [drndump] + drndump_options
|
40
61
|
client_command_line = [client] + client_options
|
41
62
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
yield dump if block_given?
|
48
|
-
client_in.puts(dump)
|
49
|
-
end
|
63
|
+
env = {}
|
64
|
+
Open3.pipeline_r([env, *drndump_command_line],
|
65
|
+
[env, *client_command_line]) do |last_stdout, thread|
|
66
|
+
last_stdout.each do |output|
|
67
|
+
yield output if block_given?
|
50
68
|
end
|
51
69
|
end
|
52
70
|
end
|
data/lib/droonga/dispatcher.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
require "tsort"
|
17
17
|
|
@@ -63,6 +63,9 @@ module Droonga
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def start
|
66
|
+
@farm.on_ready = lambda do
|
67
|
+
@engine_state.on_ready
|
68
|
+
end
|
66
69
|
@farm.start
|
67
70
|
end
|
68
71
|
|
@@ -143,10 +146,10 @@ module Droonga
|
|
143
146
|
else
|
144
147
|
steps = message["steps"]
|
145
148
|
if steps
|
146
|
-
session_planner = SessionPlanner.new(
|
149
|
+
session_planner = SessionPlanner.new(@engine_state, steps)
|
147
150
|
dataset = message["dataset"] || @message["dataset"]
|
148
151
|
collector_runner = @collector_runners[dataset]
|
149
|
-
session = session_planner.create_session(id, collector_runner)
|
152
|
+
session = session_planner.create_session(id, self, collector_runner)
|
150
153
|
@engine_state.register_session(id, session)
|
151
154
|
else
|
152
155
|
logger.error("no steps error: id=#{id}, message=#{message}")
|
@@ -175,7 +178,7 @@ module Droonga
|
|
175
178
|
steps.each do |step|
|
176
179
|
dataset = @catalog.dataset(step["dataset"])
|
177
180
|
if dataset
|
178
|
-
routes = dataset.
|
181
|
+
routes = dataset.compute_routes(step, @engine_state.live_nodes)
|
179
182
|
step["routes"] = routes
|
180
183
|
else
|
181
184
|
step["routes"] ||= [id]
|
@@ -279,24 +282,24 @@ module Droonga
|
|
279
282
|
end
|
280
283
|
|
281
284
|
def log_tag
|
282
|
-
"
|
285
|
+
"dispatcher"
|
283
286
|
end
|
284
287
|
|
285
288
|
class SessionPlanner
|
286
289
|
attr_reader :steps
|
287
290
|
|
288
|
-
def initialize(
|
289
|
-
@
|
291
|
+
def initialize(engine_state, steps)
|
292
|
+
@engine_state = engine_state
|
290
293
|
@steps = steps
|
291
294
|
end
|
292
295
|
|
293
|
-
def create_session(id, collector_runner)
|
296
|
+
def create_session(id, dispatcher, collector_runner)
|
294
297
|
resolve_descendants
|
295
298
|
tasks = []
|
296
299
|
inputs = {}
|
297
300
|
@steps.each do |step|
|
298
301
|
step["routes"].each do |route|
|
299
|
-
next unless @
|
302
|
+
next unless @engine_state.local_route?(route)
|
300
303
|
task = {
|
301
304
|
"route" => route,
|
302
305
|
"step" => step,
|
@@ -310,7 +313,7 @@ module Droonga
|
|
310
313
|
end
|
311
314
|
end
|
312
315
|
end
|
313
|
-
Session.new(id,
|
316
|
+
Session.new(id, dispatcher, collector_runner, tasks, inputs)
|
314
317
|
end
|
315
318
|
|
316
319
|
def resolve_descendants
|
@@ -328,7 +331,8 @@ module Droonga
|
|
328
331
|
(step["outputs"] || []).each do |output|
|
329
332
|
descendants[output] = []
|
330
333
|
@descendants[output].each do |index|
|
331
|
-
|
334
|
+
live_routes = @engine_state.remove_dead_routes(step["routes"])
|
335
|
+
@steps[index]["n_of_expects"] += live_routes.size
|
332
336
|
descendants[output].concat(@steps[index]["routes"])
|
333
337
|
end
|
334
338
|
end
|
@@ -13,7 +13,7 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU Lesser General Public
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc.,
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
module Droonga
|
19
19
|
class DistributedCommandPlanner
|
data/lib/droonga/distributor.rb
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU Lesser General Public
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc.,
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
require "tsort"
|
19
19
|
|
@@ -11,10 +11,10 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
module Droonga
|
17
17
|
class Engine
|
18
|
-
VERSION = "1.0.
|
18
|
+
VERSION = "1.0.5"
|
19
19
|
end
|
20
20
|
end
|
data/lib/droonga/engine.rb
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU Lesser General Public
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc.,
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
require "time"
|
19
19
|
require "fileutils"
|
@@ -29,6 +29,7 @@ module Droonga
|
|
29
29
|
class Engine
|
30
30
|
include Loggable
|
31
31
|
|
32
|
+
attr_writer :on_ready
|
32
33
|
def initialize(loop, name, internal_name)
|
33
34
|
@state = EngineState.new(loop, name, internal_name)
|
34
35
|
@catalog = load_catalog
|
@@ -38,10 +39,14 @@ module Droonga
|
|
38
39
|
@live_nodes_list_observer.on_change = lambda do
|
39
40
|
@state.live_nodes = load_live_nodes
|
40
41
|
end
|
42
|
+
@on_ready = nil
|
41
43
|
end
|
42
44
|
|
43
45
|
def start
|
44
46
|
logger.trace("start: start")
|
47
|
+
@state.on_ready = lambda do
|
48
|
+
@on_ready.call if @on_ready
|
49
|
+
end
|
45
50
|
@state.start
|
46
51
|
@live_nodes_list_observer.start
|
47
52
|
@dispatcher.start
|
@@ -87,7 +92,7 @@ module Droonga
|
|
87
92
|
loader = CatalogLoader.new(catalog_path.to_s)
|
88
93
|
catalog = loader.load
|
89
94
|
logger.info("catalog loaded",
|
90
|
-
:path => catalog_path,
|
95
|
+
:path => catalog_path.to_s,
|
91
96
|
:mtime => catalog_path.mtime)
|
92
97
|
catalog
|
93
98
|
end
|
@@ -97,7 +102,7 @@ module Droonga
|
|
97
102
|
loader = LiveNodesListLoader.new(path)
|
98
103
|
live_nodes = loader.load
|
99
104
|
logger.info("live-nodes loaded",
|
100
|
-
:path => path,
|
105
|
+
:path => path.to_s,
|
101
106
|
:mtime => path.mtime)
|
102
107
|
live_nodes
|
103
108
|
end
|
data/lib/droonga/engine_state.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
require "English"
|
17
17
|
|
@@ -31,21 +31,22 @@ module Droonga
|
|
31
31
|
attr_reader :internal_name
|
32
32
|
attr_reader :forwarder
|
33
33
|
attr_reader :replier
|
34
|
+
attr_writer :on_ready
|
34
35
|
attr_accessor :on_finish
|
35
36
|
attr_accessor :catalog
|
36
|
-
attr_writer :dead_nodes
|
37
37
|
def initialize(loop, name, internal_name)
|
38
38
|
@loop = loop
|
39
39
|
@name = name
|
40
40
|
@internal_name = internal_name
|
41
41
|
@sessions = {}
|
42
42
|
@current_id = 0
|
43
|
-
@forwarder = Forwarder.new(@loop)
|
44
|
-
@forwarder.resume
|
43
|
+
@forwarder = Forwarder.new(@loop, :buffering => true)
|
45
44
|
@replier = Replier.new(@forwarder)
|
45
|
+
@on_ready = nil
|
46
46
|
@on_finish = nil
|
47
47
|
@catalog = nil
|
48
48
|
@live_nodes = nil
|
49
|
+
@dead_nodes = []
|
49
50
|
end
|
50
51
|
|
51
52
|
def start
|
@@ -111,13 +112,21 @@ module Droonga
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def live_nodes=(nodes)
|
115
|
+
old_live_nodes = @live_nodes
|
114
116
|
@live_nodes = nodes
|
115
117
|
@dead_nodes = all_nodes - @live_nodes
|
118
|
+
@forwarder.resume if old_live_nodes != @live_nodes
|
116
119
|
@live_nodes
|
117
120
|
end
|
118
121
|
|
119
|
-
def
|
120
|
-
|
122
|
+
def remove_dead_routes(routes)
|
123
|
+
routes.reject do |route|
|
124
|
+
@dead_nodes.include?(farm_path(route))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def on_ready
|
129
|
+
@on_ready.call if @on_ready
|
121
130
|
end
|
122
131
|
|
123
132
|
private
|
data/lib/droonga/error.rb
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU Lesser General Public
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc.,
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
module Droonga
|
19
19
|
class Error < StandardError
|
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# You should have received a copy of the GNU Lesser General Public
|
13
13
|
# License along with this library; if not, write to the Free Software
|
14
|
-
# Foundation, Inc.,
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
15
|
|
16
16
|
require "droonga/error"
|
17
17
|
require "droonga/status_code"
|
data/lib/droonga/event_loop.rb
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
#
|
14
14
|
# You should have received a copy of the GNU Lesser General Public
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
|
-
# Foundation, Inc.,
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
17
17
|
|
18
18
|
require "coolio"
|
19
19
|
|