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 "optparse"
|
17
17
|
require "socket"
|
@@ -24,8 +24,7 @@ require "sigdump"
|
|
24
24
|
require "droonga/path"
|
25
25
|
require "droonga/serf"
|
26
26
|
require "droonga/file_observer"
|
27
|
-
require "droonga/
|
28
|
-
require "droonga/line_buffer"
|
27
|
+
require "droonga/process_supervisor"
|
29
28
|
|
30
29
|
module Droonga
|
31
30
|
module Command
|
@@ -94,14 +93,14 @@ module Droonga
|
|
94
93
|
end
|
95
94
|
|
96
95
|
def write_pid_file
|
97
|
-
if @configuration.
|
98
|
-
|
96
|
+
if @configuration.pid_file_path
|
97
|
+
@configuration.pid_file_path.open("w") do |file|
|
99
98
|
file.puts(Process.pid)
|
100
99
|
end
|
101
100
|
begin
|
102
101
|
yield
|
103
102
|
ensure
|
104
|
-
FileUtils.rm_f(@configuration.
|
103
|
+
FileUtils.rm_f(@configuration.pid_file_path.to_s)
|
105
104
|
end
|
106
105
|
else
|
107
106
|
yield
|
@@ -112,14 +111,16 @@ module Droonga
|
|
112
111
|
DEFAULT_HOST = Socket.gethostname
|
113
112
|
DEFAULT_PORT = 10031
|
114
113
|
|
115
|
-
attr_reader :host, :port, :tag, :log_file, :
|
114
|
+
attr_reader :host, :port, :tag, :log_file, :pid_file_path
|
115
|
+
attr_reader :ready_notify_fd
|
116
116
|
def initialize
|
117
117
|
@host = DEFAULT_HOST
|
118
118
|
@port = DEFAULT_PORT
|
119
119
|
@tag = "droonga"
|
120
120
|
@log_file = nil
|
121
121
|
@daemon = false
|
122
|
-
@
|
122
|
+
@pid_file_path = nil
|
123
|
+
@ready_notify_fd = nil
|
123
124
|
end
|
124
125
|
|
125
126
|
def engine_name
|
@@ -151,6 +152,7 @@ module Droonga
|
|
151
152
|
add_log_options(parser)
|
152
153
|
add_process_options(parser)
|
153
154
|
add_path_options(parser)
|
155
|
+
add_notification_options(parser)
|
154
156
|
end
|
155
157
|
|
156
158
|
def listen_socket
|
@@ -206,9 +208,9 @@ module Droonga
|
|
206
208
|
"Run as a daemon") do
|
207
209
|
@daemon = true
|
208
210
|
end
|
209
|
-
parser.on("--pid-file=
|
210
|
-
"Put PID to
|
211
|
-
@
|
211
|
+
parser.on("--pid-file=PATH",
|
212
|
+
"Put PID to PATH") do |path|
|
213
|
+
@pid_file_path = Pathname.new(path).expand_path
|
212
214
|
end
|
213
215
|
end
|
214
216
|
|
@@ -222,6 +224,15 @@ module Droonga
|
|
222
224
|
end
|
223
225
|
end
|
224
226
|
|
227
|
+
def add_notification_options(parser)
|
228
|
+
parser.separator("")
|
229
|
+
parser.separator("Notification:")
|
230
|
+
parser.on("--ready-notify-fd=FD", Integer,
|
231
|
+
"Send 'ready' message to FD on ready") do |fd|
|
232
|
+
@ready_notify_fd = fd
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
225
236
|
def bind_heartbeat_socket
|
226
237
|
socket = UDPSocket.new(address_family)
|
227
238
|
socket.bind(@host, @port)
|
@@ -239,36 +250,45 @@ module Droonga
|
|
239
250
|
@serf = run_serf
|
240
251
|
@serf_status_observer = run_serf_status_observer
|
241
252
|
@service_runner = run_service
|
253
|
+
setup_initial_on_ready
|
242
254
|
@catalog_observer = run_catalog_observer
|
243
|
-
@
|
244
|
-
@loop.attach(@loop_breaker)
|
255
|
+
@command_runner = run_command_runner
|
245
256
|
|
246
257
|
trap_signals
|
247
258
|
@loop.run
|
248
|
-
@serf.
|
259
|
+
@serf.stop if @serf.running?
|
249
260
|
|
250
261
|
@service_runner.success?
|
251
262
|
end
|
252
263
|
|
253
264
|
private
|
265
|
+
def setup_initial_on_ready
|
266
|
+
return if @configuration.ready_notify_fd.nil?
|
267
|
+
@service_runner.on_ready = lambda do
|
268
|
+
output = IO.new(@configuration.ready_notify_fd)
|
269
|
+
output.puts("ready")
|
270
|
+
output.close
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
254
274
|
def trap_signals
|
255
275
|
trap(:TERM) do
|
256
|
-
stop_gracefully
|
276
|
+
@command_runner.push_command(:stop_gracefully)
|
257
277
|
trap(:TERM, "DEFAULT")
|
258
278
|
end
|
259
279
|
trap(:INT) do
|
260
|
-
stop_immediately
|
280
|
+
@command_runner.push_command(:stop_immediately)
|
261
281
|
trap(:INT, "DEFAULT")
|
262
282
|
end
|
263
283
|
trap(:QUIT) do
|
264
|
-
stop_immediately
|
284
|
+
@command_runner.push_cmmand(:stop_immediately)
|
265
285
|
trap(:QUIT, "DEFAULT")
|
266
286
|
end
|
267
287
|
trap(:USR1) do
|
268
|
-
restart_graceful
|
288
|
+
@command_runner.push_command(:restart_graceful)
|
269
289
|
end
|
270
290
|
trap(:HUP) do
|
271
|
-
restart_immediately
|
291
|
+
@command_runner.push_command(:restart_immediately)
|
272
292
|
end
|
273
293
|
trap(:USR2) do
|
274
294
|
Sigdump.dump
|
@@ -276,25 +296,22 @@ module Droonga
|
|
276
296
|
end
|
277
297
|
|
278
298
|
def stop_gracefully
|
279
|
-
@
|
280
|
-
@
|
281
|
-
@serf.shutdown
|
299
|
+
@command_runner.stop
|
300
|
+
@serf.stop
|
282
301
|
@serf_status_observer.stop
|
283
302
|
@catalog_observer.stop
|
284
303
|
@service_runner.stop_gracefully
|
285
304
|
end
|
286
305
|
|
287
306
|
def stop_immediately
|
288
|
-
@
|
289
|
-
@
|
290
|
-
@serf.shutdown
|
307
|
+
@command_runner.stop
|
308
|
+
@serf.stop
|
291
309
|
@serf_status_observer.stop
|
292
310
|
@catalog_observer.stop
|
293
311
|
@service_runner.stop_immediately
|
294
312
|
end
|
295
313
|
|
296
314
|
def restart_graceful
|
297
|
-
@loop_breaker.signal
|
298
315
|
old_service_runner = @service_runner
|
299
316
|
@service_runner = run_service
|
300
317
|
@service_runner.on_ready = lambda do
|
@@ -308,7 +325,6 @@ module Droonga
|
|
308
325
|
end
|
309
326
|
|
310
327
|
def restart_immediately
|
311
|
-
@loop_breaker.signal
|
312
328
|
old_service_runner = @service_runner
|
313
329
|
@service_runner = run_service
|
314
330
|
old_service_runner.stop_immediately
|
@@ -327,7 +343,7 @@ module Droonga
|
|
327
343
|
end
|
328
344
|
|
329
345
|
def restart_serf
|
330
|
-
@serf.
|
346
|
+
@serf.stop if @serf
|
331
347
|
@serf = run_serf
|
332
348
|
end
|
333
349
|
|
@@ -348,11 +364,18 @@ module Droonga
|
|
348
364
|
catalog_observer.start
|
349
365
|
catalog_observer
|
350
366
|
end
|
367
|
+
|
368
|
+
def run_command_runner
|
369
|
+
command_runner = CommandRunner.new(@loop)
|
370
|
+
command_runner.on_command = lambda do |command|
|
371
|
+
__send__(command)
|
372
|
+
end
|
373
|
+
command_runner.start
|
374
|
+
command_runner
|
375
|
+
end
|
351
376
|
end
|
352
377
|
|
353
378
|
class ServiceRunner
|
354
|
-
include ServiceControlProtocol
|
355
|
-
|
356
379
|
def initialize(raw_loop, configuration)
|
357
380
|
@raw_loop = raw_loop
|
358
381
|
@configuration = configuration
|
@@ -394,16 +417,17 @@ module Droonga
|
|
394
417
|
@pid = spawn(env, *command_line, options)
|
395
418
|
control_write_in.close
|
396
419
|
control_read_out.close
|
397
|
-
|
398
|
-
|
420
|
+
@supervisor = create_process_supervisor(control_read_in,
|
421
|
+
control_write_out)
|
422
|
+
@supervisor.start
|
399
423
|
end
|
400
424
|
|
401
425
|
def stop_gracefully
|
402
|
-
@
|
426
|
+
@supervisor.stop_gracefully
|
403
427
|
end
|
404
428
|
|
405
429
|
def stop_immediately
|
406
|
-
@
|
430
|
+
@supervisor.stop_immediately
|
407
431
|
end
|
408
432
|
|
409
433
|
def success?
|
@@ -411,6 +435,17 @@ module Droonga
|
|
411
435
|
end
|
412
436
|
|
413
437
|
private
|
438
|
+
def create_process_supervisor(input, output)
|
439
|
+
supervisor = ProcessSupervisor.new(@raw_loop, input, output)
|
440
|
+
supervisor.on_ready = lambda do
|
441
|
+
on_ready
|
442
|
+
end
|
443
|
+
supervisor.on_finish = lambda do
|
444
|
+
on_finish
|
445
|
+
end
|
446
|
+
supervisor
|
447
|
+
end
|
448
|
+
|
414
449
|
def on_ready
|
415
450
|
@on_ready.call if @on_ready
|
416
451
|
end
|
@@ -422,33 +457,46 @@ module Droonga
|
|
422
457
|
def on_finish
|
423
458
|
_, status = Process.waitpid2(@pid)
|
424
459
|
@success = status.success?
|
425
|
-
@
|
426
|
-
@control_read_in.close
|
460
|
+
@supervisor.stop
|
427
461
|
on_failure unless success?
|
428
462
|
end
|
463
|
+
end
|
429
464
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
465
|
+
class CommandRunner
|
466
|
+
attr_writer :on_command
|
467
|
+
def initialize(loop)
|
468
|
+
@loop = loop
|
469
|
+
@commands = []
|
470
|
+
@on_command = nil
|
471
|
+
end
|
472
|
+
|
473
|
+
def start
|
474
|
+
@async_watcher = Coolio::AsyncWatcher.new
|
475
|
+
on_signal = lambda do
|
476
|
+
commands = @commands.uniq
|
477
|
+
@commands.clear
|
478
|
+
until commands.empty?
|
479
|
+
command = commands.shift
|
480
|
+
@on_command.call(command) if @on_command
|
446
481
|
end
|
447
482
|
end
|
448
|
-
@
|
449
|
-
|
483
|
+
@async_watcher.on_signal do
|
484
|
+
on_signal.call
|
450
485
|
end
|
451
|
-
@
|
486
|
+
@loop.attach(@async_watcher)
|
487
|
+
end
|
488
|
+
|
489
|
+
def stop
|
490
|
+
return if @async_watcher.nil?
|
491
|
+
@async_watcher.detach
|
492
|
+
@async_watcher = nil
|
493
|
+
end
|
494
|
+
|
495
|
+
def push_command(command)
|
496
|
+
return if @async_watcher.nil?
|
497
|
+
first_command_p = @commands.empty?
|
498
|
+
@commands << command
|
499
|
+
@async_watcher.signal if first_command_p
|
452
500
|
end
|
453
501
|
end
|
454
502
|
end
|
@@ -11,14 +11,13 @@
|
|
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 "optparse"
|
17
17
|
|
18
18
|
require "coolio"
|
19
19
|
|
20
|
-
require "droonga/
|
21
|
-
require "droonga/line_buffer"
|
20
|
+
require "droonga/worker_process_agent"
|
22
21
|
require "droonga/engine"
|
23
22
|
require "droonga/fluent_message_receiver"
|
24
23
|
require "droonga/internal_fluent_message_receiver"
|
@@ -34,7 +33,6 @@ module Droonga
|
|
34
33
|
end
|
35
34
|
|
36
35
|
include Loggable
|
37
|
-
include ServiceControlProtocol
|
38
36
|
|
39
37
|
def initialize
|
40
38
|
@engine_name = nil
|
@@ -59,10 +57,7 @@ module Droonga
|
|
59
57
|
logger.exception("failed to run services", $!)
|
60
58
|
success = false
|
61
59
|
ensure
|
62
|
-
|
63
|
-
control_write_io.write(Messages::FINISH)
|
64
|
-
control_write_io.close
|
65
|
-
end
|
60
|
+
shutdown_worker_process_agent
|
66
61
|
end
|
67
62
|
|
68
63
|
success
|
@@ -118,9 +113,9 @@ module Droonga
|
|
118
113
|
@loop = Coolio::Loop.default
|
119
114
|
|
120
115
|
run_internal_message_receiver
|
116
|
+
run_worker_process_agent
|
121
117
|
run_engine
|
122
118
|
run_receiver
|
123
|
-
run_control_io
|
124
119
|
@loop.run
|
125
120
|
end
|
126
121
|
|
@@ -145,6 +140,9 @@ module Droonga
|
|
145
140
|
|
146
141
|
def run_engine
|
147
142
|
@engine = Engine.new(@loop, @engine_name, @internal_engine_name)
|
143
|
+
@engine.on_ready = lambda do
|
144
|
+
@worker_process_agent.ready
|
145
|
+
end
|
148
146
|
@engine.start
|
149
147
|
end
|
150
148
|
|
@@ -153,66 +151,23 @@ module Droonga
|
|
153
151
|
@receiver.start
|
154
152
|
end
|
155
153
|
|
156
|
-
def
|
157
|
-
|
158
|
-
@receiver, receiver = nil, @receiver
|
159
|
-
receiver.shutdown
|
160
|
-
end
|
161
|
-
|
162
|
-
def run_control_io
|
163
|
-
@control_read = Coolio::IO.new(IO.new(@control_read_fd))
|
154
|
+
def run_worker_process_agent
|
155
|
+
input = IO.new(@control_read_fd)
|
164
156
|
@control_read_fd = nil
|
165
|
-
|
166
|
-
line_buffer = LineBuffer.new
|
167
|
-
line_buffer.feed(data) do |line|
|
168
|
-
case line
|
169
|
-
when Messages::STOP_GRACEFUL
|
170
|
-
stop_gracefully
|
171
|
-
when Messages::STOP_IMMEDIATELY
|
172
|
-
stop_immediately
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
@control_read.on_read do |data|
|
177
|
-
on_read.call(data)
|
178
|
-
end
|
179
|
-
read_on_close = lambda do
|
180
|
-
if @control_read
|
181
|
-
@control_read = nil
|
182
|
-
stop_immediately
|
183
|
-
end
|
184
|
-
end
|
185
|
-
@control_read.on_close do
|
186
|
-
read_on_close.call
|
187
|
-
end
|
188
|
-
@loop.attach(@control_read)
|
189
|
-
|
190
|
-
@control_write = Coolio::IO.new(IO.new(@control_write_fd))
|
157
|
+
output = IO.new(@control_write_fd)
|
191
158
|
@control_write_fd = nil
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
stop_immediately
|
196
|
-
end
|
197
|
-
@control_write_closed = true
|
159
|
+
@worker_process_agent = WorkerProcessAgent.new(@loop, input, output)
|
160
|
+
@worker_process_agent.on_stop_gracefully = lambda do
|
161
|
+
stop_gracefully
|
198
162
|
end
|
199
|
-
@
|
200
|
-
|
163
|
+
@worker_process_agent.on_stop_immediately = lambda do
|
164
|
+
stop_immediately
|
201
165
|
end
|
202
|
-
@
|
203
|
-
|
204
|
-
@control_write.write(Messages::READY)
|
166
|
+
@worker_process_agent.start
|
205
167
|
end
|
206
168
|
|
207
|
-
def
|
208
|
-
|
209
|
-
@control_write, control_write = nil, @control_write
|
210
|
-
control_write.detach
|
211
|
-
end
|
212
|
-
if @control_read
|
213
|
-
@control_read, control_read = nil, @control_read
|
214
|
-
control_read.close
|
215
|
-
end
|
169
|
+
def shutdown_worker_process_agent
|
170
|
+
@worker_process_agent.stop
|
216
171
|
end
|
217
172
|
|
218
173
|
def create_receiver
|
@@ -250,17 +205,17 @@ module Droonga
|
|
250
205
|
def stop_gracefully
|
251
206
|
return if @stopping
|
252
207
|
@stopping = true
|
253
|
-
|
208
|
+
@receiver.stop_gracefully
|
254
209
|
@engine.stop_gracefully do
|
255
|
-
|
210
|
+
shutdown_worker_process_agent
|
256
211
|
shutdown_internal_message_receiver
|
257
212
|
end
|
258
213
|
end
|
259
214
|
|
260
215
|
# It may be called after stop_gracefully.
|
261
216
|
def stop_immediately
|
262
|
-
|
263
|
-
|
217
|
+
shutdown_worker_process_agent
|
218
|
+
@receiver.stop_immediately
|
264
219
|
shutdown_internal_message_receiver
|
265
220
|
@engine.stop_immediately
|
266
221
|
@loop.stop
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# Copyright (C) 2013-2014 Droonga Project
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
6
|
+
#
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
10
|
+
# Lesser General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
13
|
+
# License along with this library; if not, write to the Free Software
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
15
|
+
|
16
|
+
require "optparse"
|
17
|
+
require "fileutils"
|
18
|
+
|
19
|
+
require "coolio"
|
20
|
+
|
21
|
+
require "droonga/job_receiver"
|
22
|
+
require "droonga/plugin_loader"
|
23
|
+
require "droonga/worker_process_agent"
|
24
|
+
require "droonga/handler_runner"
|
25
|
+
|
26
|
+
module Droonga
|
27
|
+
module Command
|
28
|
+
class DroongaEngineWorker
|
29
|
+
class << self
|
30
|
+
def run(command_line_arguments)
|
31
|
+
new.run(command_line_arguments)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
include Loggable
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@job_queue_socket_path = nil
|
39
|
+
@contrtol_read_fd = nil
|
40
|
+
@contrtol_write_fd = nil
|
41
|
+
@pid_file_path = nil
|
42
|
+
@dataset = nil
|
43
|
+
@database_path = nil
|
44
|
+
@plugins = []
|
45
|
+
@worker_process_agent = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def run(command_line_arguments)
|
49
|
+
create_new_process_group
|
50
|
+
|
51
|
+
parse_command_line_arguments!(command_line_arguments)
|
52
|
+
PluginLoader.load_all
|
53
|
+
|
54
|
+
write_pid_file do
|
55
|
+
run_main_loop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def create_new_process_group
|
61
|
+
begin
|
62
|
+
Process.setsid
|
63
|
+
rescue SystemCallError, NotImplementedError
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def parse_command_line_arguments!(command_line_arguments)
|
68
|
+
parser = OptionParser.new
|
69
|
+
add_internal_options(parser)
|
70
|
+
parser.parse!(command_line_arguments)
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_internal_options(parser)
|
74
|
+
parser.separator("")
|
75
|
+
parser.separator("Internal:")
|
76
|
+
parser.on("--job-queue-socket-path=PATH",
|
77
|
+
"Read jobs from PATH") do |path|
|
78
|
+
@job_queue_socket_path = Pathname.new(path)
|
79
|
+
end
|
80
|
+
parser.on("--control-read-fd=FD", Integer,
|
81
|
+
"Use FD to read control messages from the service") do |fd|
|
82
|
+
@control_read_fd = fd
|
83
|
+
end
|
84
|
+
parser.on("--control-write-fd=FD", Integer,
|
85
|
+
"Use FD to write control messages from the service") do |fd|
|
86
|
+
@control_write_fd = fd
|
87
|
+
end
|
88
|
+
parser.on("--pid-file=PATH",
|
89
|
+
"Put PID to PATH") do |path|
|
90
|
+
@pid_file_path = Pathname.new(path)
|
91
|
+
end
|
92
|
+
parser.on("--dataset=DATASET",
|
93
|
+
"Process DATASET") do |dataset|
|
94
|
+
@dataset = dataset
|
95
|
+
end
|
96
|
+
parser.on("--database-path=PATH",
|
97
|
+
"Use database at PATH") do |path|
|
98
|
+
@database_path = Pathname.new(path)
|
99
|
+
end
|
100
|
+
parser.on("--plugins=PLUGIN1,PLUGIN2,...", Array,
|
101
|
+
"Use PLUGINs") do |plugins|
|
102
|
+
@plugins = plugins
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def write_pid_file
|
107
|
+
if @pid_file_path
|
108
|
+
@pid_file_path.open("w") do |file|
|
109
|
+
file.puts(Process.pid)
|
110
|
+
end
|
111
|
+
begin
|
112
|
+
yield
|
113
|
+
ensure
|
114
|
+
FileUtils.rm_f(@pid_file_path.to_s)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
yield
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def run_main_loop
|
122
|
+
begin
|
123
|
+
start
|
124
|
+
true
|
125
|
+
rescue
|
126
|
+
logger.exception("failed while running", $!)
|
127
|
+
false
|
128
|
+
ensure
|
129
|
+
stop_worker_process_agent
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def start
|
134
|
+
@stopping = false
|
135
|
+
@loop = Coolio::Loop.default
|
136
|
+
|
137
|
+
start_forwarder
|
138
|
+
start_handler_runner
|
139
|
+
start_job_receiver
|
140
|
+
start_worker_process_agent
|
141
|
+
|
142
|
+
@loop.run
|
143
|
+
end
|
144
|
+
|
145
|
+
def stop_gracefully
|
146
|
+
return if @stopping
|
147
|
+
@stopping = true
|
148
|
+
|
149
|
+
stop_worker_process_agent
|
150
|
+
stop_job_receiver
|
151
|
+
stop_handler_runner
|
152
|
+
stop_forwarder
|
153
|
+
end
|
154
|
+
|
155
|
+
# It may be called after stop_gracefully.
|
156
|
+
def stop_immediately
|
157
|
+
stop_gracefully
|
158
|
+
@loop.stop
|
159
|
+
end
|
160
|
+
|
161
|
+
def start_forwarder
|
162
|
+
@forwarder = Forwarder.new(@loop)
|
163
|
+
@forwarder.start
|
164
|
+
end
|
165
|
+
|
166
|
+
def stop_forwarder
|
167
|
+
@forwarder.shutdown
|
168
|
+
end
|
169
|
+
|
170
|
+
def start_handler_runner
|
171
|
+
options = {
|
172
|
+
:forwarder => @forwarder,
|
173
|
+
:dataset => @dataset,
|
174
|
+
:database => @database_path.to_s,
|
175
|
+
:plugins => @plugins,
|
176
|
+
}
|
177
|
+
@handler_runner = HandlerRunner.new(@loop, options)
|
178
|
+
@handler_runner.start
|
179
|
+
end
|
180
|
+
|
181
|
+
def stop_handler_runner
|
182
|
+
@handler_runner.shutdown
|
183
|
+
end
|
184
|
+
|
185
|
+
def start_job_receiver
|
186
|
+
@job_receiver = create_job_receiver
|
187
|
+
@job_receiver.start
|
188
|
+
end
|
189
|
+
|
190
|
+
def create_job_receiver
|
191
|
+
JobReceiver.new(@loop, @job_queue_socket_path.to_s) do |message|
|
192
|
+
process(message)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def process(message)
|
197
|
+
logger.trace("process: start")
|
198
|
+
@handler_runner.process(message)
|
199
|
+
logger.trace("process: done")
|
200
|
+
end
|
201
|
+
|
202
|
+
def stop_job_receiver
|
203
|
+
@job_receiver.shutdown
|
204
|
+
end
|
205
|
+
|
206
|
+
def start_worker_process_agent
|
207
|
+
input = IO.new(@control_read_fd)
|
208
|
+
@control_read_fd = nil
|
209
|
+
output = IO.new(@control_write_fd)
|
210
|
+
@control_write_fd = nil
|
211
|
+
@worker_process_agent = WorkerProcessAgent.new(@loop, input, output)
|
212
|
+
@worker_process_agent.on_stop_gracefully = lambda do
|
213
|
+
stop_gracefully
|
214
|
+
end
|
215
|
+
@worker_process_agent.on_stop_immediately = lambda do
|
216
|
+
stop_immediately
|
217
|
+
end
|
218
|
+
@worker_process_agent.start
|
219
|
+
@worker_process_agent.ready
|
220
|
+
end
|
221
|
+
|
222
|
+
def stop_worker_process_agent
|
223
|
+
return if @worker_process_agent.nil?
|
224
|
+
@worker_process_agent.stop
|
225
|
+
end
|
226
|
+
|
227
|
+
def log_tag
|
228
|
+
"[#{Process.ppid}] worker"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|