droonga-engine 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.dir-locals.el +3 -0
- data/.gitignore +6 -0
- data/.travis.yml +15 -0
- data/.yardopts +7 -0
- data/Gemfile +66 -0
- data/LICENSE.txt +14 -0
- data/README.md +17 -0
- data/Rakefile +64 -0
- data/benchmark/benchmark.rb +123 -0
- data/benchmark/utils.rb +246 -0
- data/benchmark/watch/benchmark-notify.rb +143 -0
- data/benchmark/watch/benchmark-notify.sh +20 -0
- data/benchmark/watch/benchmark-publish.rb +120 -0
- data/benchmark/watch/benchmark-scan.rb +213 -0
- data/bin/droonga-catalog-generate +103 -0
- data/bin/droonga-engine +20 -0
- data/bin/droonga-engine-service +20 -0
- data/doc/text/news.md +106 -0
- data/droonga-engine.gemspec +52 -0
- data/lib/droonga/adapter.rb +48 -0
- data/lib/droonga/adapter_runner.rb +104 -0
- data/lib/droonga/catalog/base.rb +41 -0
- data/lib/droonga/catalog/collection_volume.rb +106 -0
- data/lib/droonga/catalog/dataset.rb +69 -0
- data/lib/droonga/catalog/errors.rb +113 -0
- data/lib/droonga/catalog/schema.rb +186 -0
- data/lib/droonga/catalog/single_volume.rb +28 -0
- data/lib/droonga/catalog/slice.rb +41 -0
- data/lib/droonga/catalog/version1.rb +427 -0
- data/lib/droonga/catalog/version2.rb +96 -0
- data/lib/droonga/catalog/version2_validator.rb +63 -0
- data/lib/droonga/catalog/volume.rb +33 -0
- data/lib/droonga/catalog/volume_collection.rb +56 -0
- data/lib/droonga/catalog_generator.rb +156 -0
- data/lib/droonga/catalog_loader.rb +56 -0
- data/lib/droonga/catalog_observer.rb +83 -0
- data/lib/droonga/collector.rb +38 -0
- data/lib/droonga/collector_message.rb +71 -0
- data/lib/droonga/collector_runner.rb +64 -0
- data/lib/droonga/collectors/and.rb +26 -0
- data/lib/droonga/collectors/or.rb +26 -0
- data/lib/droonga/collectors/sum.rb +26 -0
- data/lib/droonga/collectors.rb +18 -0
- data/lib/droonga/dispatcher.rb +326 -0
- data/lib/droonga/distributed_command_planner.rb +179 -0
- data/lib/droonga/distributor.rb +87 -0
- data/lib/droonga/engine/command/droonga_engine.rb +441 -0
- data/lib/droonga/engine/version.rb +20 -0
- data/lib/droonga/engine.rb +80 -0
- data/lib/droonga/engine_state.rb +79 -0
- data/lib/droonga/error.rb +73 -0
- data/lib/droonga/error_messages.rb +33 -0
- data/lib/droonga/event_loop.rb +46 -0
- data/lib/droonga/farm.rb +58 -0
- data/lib/droonga/fluent_message_receiver.rb +191 -0
- data/lib/droonga/fluent_message_sender.rb +140 -0
- data/lib/droonga/forwarder.rb +119 -0
- data/lib/droonga/handler.rb +49 -0
- data/lib/droonga/handler_message.rb +61 -0
- data/lib/droonga/handler_messenger.rb +119 -0
- data/lib/droonga/handler_runner.rb +125 -0
- data/lib/droonga/input_message.rb +51 -0
- data/lib/droonga/job_protocol.rb +20 -0
- data/lib/droonga/job_pusher.rb +179 -0
- data/lib/droonga/job_receiver.rb +70 -0
- data/lib/droonga/loggable.rb +29 -0
- data/lib/droonga/logger.rb +142 -0
- data/lib/droonga/message_matcher.rb +109 -0
- data/lib/droonga/output_message.rb +55 -0
- data/lib/droonga/planner.rb +47 -0
- data/lib/droonga/pluggable.rb +31 -0
- data/lib/droonga/plugin/metadata/adapter_input_message.rb +39 -0
- data/lib/droonga/plugin/metadata/adapter_output_message.rb +39 -0
- data/lib/droonga/plugin/metadata/collector_message.rb +39 -0
- data/lib/droonga/plugin/metadata/handler_action.rb +39 -0
- data/lib/droonga/plugin/metadata/input_message.rb +54 -0
- data/lib/droonga/plugin.rb +43 -0
- data/lib/droonga/plugin_loader.rb +63 -0
- data/lib/droonga/plugin_registry.rb +66 -0
- data/lib/droonga/plugins/basic.rb +54 -0
- data/lib/droonga/plugins/crud.rb +145 -0
- data/lib/droonga/plugins/dump.rb +97 -0
- data/lib/droonga/plugins/error.rb +51 -0
- data/lib/droonga/plugins/groonga/column_create.rb +123 -0
- data/lib/droonga/plugins/groonga/column_list.rb +124 -0
- data/lib/droonga/plugins/groonga/column_remove.rb +65 -0
- data/lib/droonga/plugins/groonga/column_rename.rb +67 -0
- data/lib/droonga/plugins/groonga/delete.rb +117 -0
- data/lib/droonga/plugins/groonga/generic_command.rb +105 -0
- data/lib/droonga/plugins/groonga/generic_response.rb +43 -0
- data/lib/droonga/plugins/groonga/select.rb +236 -0
- data/lib/droonga/plugins/groonga/table_create.rb +111 -0
- data/lib/droonga/plugins/groonga/table_list.rb +120 -0
- data/lib/droonga/plugins/groonga/table_remove.rb +57 -0
- data/lib/droonga/plugins/groonga.rb +37 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +407 -0
- data/lib/droonga/plugins/search.rb +146 -0
- data/lib/droonga/plugins/watch.rb +178 -0
- data/lib/droonga/processor.rb +63 -0
- data/lib/droonga/reducer.rb +169 -0
- data/lib/droonga/replier.rb +49 -0
- data/lib/droonga/schema_applier.rb +167 -0
- data/lib/droonga/searcher/mecab_filter.rb +67 -0
- data/lib/droonga/searcher.rb +733 -0
- data/lib/droonga/server.rb +45 -0
- data/lib/droonga/session.rb +99 -0
- data/lib/droonga/single_step.rb +68 -0
- data/lib/droonga/single_step_definition.rb +54 -0
- data/lib/droonga/slice.rb +122 -0
- data/lib/droonga/status_code.rb +25 -0
- data/lib/droonga/step_runner.rb +64 -0
- data/lib/droonga/sweeper.rb +42 -0
- data/lib/droonga/test/stub_handler.rb +37 -0
- data/lib/droonga/test/stub_handler_message.rb +35 -0
- data/lib/droonga/test/stub_handler_messenger.rb +34 -0
- data/lib/droonga/test/stub_planner.rb +31 -0
- data/lib/droonga/test.rb +21 -0
- data/lib/droonga/watch_schema.rb +92 -0
- data/lib/droonga/watcher.rb +257 -0
- data/lib/droonga/worker.rb +61 -0
- data/sample/cluster/catalog.json +42 -0
- data/sample/mecab_filter/data.grn +7 -0
- data/sample/mecab_filter/ddl.grn +7 -0
- data/sample/mecab_filter/search_with_mecab_filter.json +21 -0
- data/sample/mecab_filter/search_without_mecab_filter.json +21 -0
- data/test/command/config/default/catalog.json +85 -0
- data/test/command/config/default/fluentd.conf +11 -0
- data/test/command/config/version1/catalog.json +68 -0
- data/test/command/config/version1/fluentd.conf +11 -0
- data/test/command/fixture/documents.jsons +208 -0
- data/test/command/fixture/event.jsons +41 -0
- data/test/command/fixture/user-table-array.jsons +38 -0
- data/test/command/fixture/user-table.jsons +47 -0
- data/test/command/run-test.rb +34 -0
- data/test/command/suite/add/dimension/column.catalog.json +28 -0
- data/test/command/suite/add/dimension/column.expected +41 -0
- data/test/command/suite/add/dimension/column.test +51 -0
- data/test/command/suite/add/dimension/integer.catalog.json +19 -0
- data/test/command/suite/add/dimension/integer.expected +41 -0
- data/test/command/suite/add/dimension/integer.test +51 -0
- data/test/command/suite/add/error/invalid-integer.expected +46 -0
- data/test/command/suite/add/error/invalid-integer.test +12 -0
- data/test/command/suite/add/error/invalid-time.expected +46 -0
- data/test/command/suite/add/error/invalid-time.test +12 -0
- data/test/command/suite/add/error/missing-key.expected +25 -0
- data/test/command/suite/add/error/missing-key.test +16 -0
- data/test/command/suite/add/error/missing-table.expected +25 -0
- data/test/command/suite/add/error/missing-table.test +16 -0
- data/test/command/suite/add/error/unknown-column.expected +46 -0
- data/test/command/suite/add/error/unknown-column.test +12 -0
- data/test/command/suite/add/error/unknown-table.expected +25 -0
- data/test/command/suite/add/error/unknown-table.test +17 -0
- data/test/command/suite/add/minimum.expected +6 -0
- data/test/command/suite/add/minimum.test +11 -0
- data/test/command/suite/add/with-values.expected +6 -0
- data/test/command/suite/add/with-values.test +17 -0
- data/test/command/suite/add/without-key.expected +6 -0
- data/test/command/suite/add/without-key.test +16 -0
- data/test/command/suite/groonga/column_create/scalar.expected +26 -0
- data/test/command/suite/groonga/column_create/scalar.test +17 -0
- data/test/command/suite/groonga/column_create/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_create/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_create/vector.expected +26 -0
- data/test/command/suite/groonga/column_create/vector.test +18 -0
- data/test/command/suite/groonga/column_list/success.expected +86 -0
- data/test/command/suite/groonga/column_list/success.test +24 -0
- data/test/command/suite/groonga/column_list/unknown-table.expected +13 -0
- data/test/command/suite/groonga/column_list/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_remove/success.expected +39 -0
- data/test/command/suite/groonga/column_remove/success.test +25 -0
- data/test/command/suite/groonga/column_remove/unknown-column.expected +27 -0
- data/test/command/suite/groonga/column_remove/unknown-column.test +16 -0
- data/test/command/suite/groonga/column_remove/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_remove/unknown-table.test +7 -0
- data/test/command/suite/groonga/column_rename/success.expected +39 -0
- data/test/command/suite/groonga/column_rename/success.test +26 -0
- data/test/command/suite/groonga/column_rename/unknown-column.expected +27 -0
- data/test/command/suite/groonga/column_rename/unknown-column.test +16 -0
- data/test/command/suite/groonga/column_rename/unknown-table.expected +14 -0
- data/test/command/suite/groonga/column_rename/unknown-table.test +7 -0
- data/test/command/suite/groonga/delete/duplicated-identifiers.expected +27 -0
- data/test/command/suite/groonga/delete/duplicated-identifiers.test +17 -0
- data/test/command/suite/groonga/delete/filter.expected +19 -0
- data/test/command/suite/groonga/delete/filter.test +19 -0
- data/test/command/suite/groonga/delete/invalid-filter.expected +14 -0
- data/test/command/suite/groonga/delete/invalid-filter.test +9 -0
- data/test/command/suite/groonga/delete/no-identifier.expected +27 -0
- data/test/command/suite/groonga/delete/no-identifier.test +15 -0
- data/test/command/suite/groonga/delete/success.expected +19 -0
- data/test/command/suite/groonga/delete/success.test +19 -0
- data/test/command/suite/groonga/delete/unknown-table.expected +14 -0
- data/test/command/suite/groonga/delete/unknown-table.test +7 -0
- data/test/command/suite/groonga/select/minimum.expected +22 -0
- data/test/command/suite/groonga/select/minimum.test +8 -0
- data/test/command/suite/groonga/table_create/array.expected +14 -0
- data/test/command/suite/groonga/table_create/array.test +8 -0
- data/test/command/suite/groonga/table_create/hash.expected +13 -0
- data/test/command/suite/groonga/table_create/hash.test +8 -0
- data/test/command/suite/groonga/table_list/success.expected +71 -0
- data/test/command/suite/groonga/table_list/success.test +15 -0
- data/test/command/suite/groonga/table_remove/success.expected +13 -0
- data/test/command/suite/groonga/table_remove/success.test +8 -0
- data/test/command/suite/groonga/table_remove/unknown-table.expected +14 -0
- data/test/command/suite/groonga/table_remove/unknown-table.test +7 -0
- data/test/command/suite/message/error/missing-dataset.expected +9 -0
- data/test/command/suite/message/error/missing-dataset.test +5 -0
- data/test/command/suite/message/error/unknown-dataset.expected +9 -0
- data/test/command/suite/message/error/unknown-dataset.test +6 -0
- data/test/command/suite/message/error/unknown-type.expected +9 -0
- data/test/command/suite/message/error/unknown-type.test +6 -0
- data/test/command/suite/search/adjusters/multiple.catalog.json +38 -0
- data/test/command/suite/search/adjusters/multiple.expected +19 -0
- data/test/command/suite/search/adjusters/multiple.test +75 -0
- data/test/command/suite/search/adjusters/one.catalog.json +38 -0
- data/test/command/suite/search/adjusters/one.expected +19 -0
- data/test/command/suite/search/adjusters/one.test +66 -0
- data/test/command/suite/search/attributes/array.expected +21 -0
- data/test/command/suite/search/attributes/array.test +28 -0
- data/test/command/suite/search/attributes/hash.expected +30 -0
- data/test/command/suite/search/attributes/hash.test +36 -0
- data/test/command/suite/search/complex.expected +48 -0
- data/test/command/suite/search/complex.test +23 -0
- data/test/command/suite/search/condition/nested.expected +15 -0
- data/test/command/suite/search/condition/nested.test +27 -0
- data/test/command/suite/search/condition/query/nonexistent_column.catalog.json +37 -0
- data/test/command/suite/search/condition/query/nonexistent_column.expected +48 -0
- data/test/command/suite/search/condition/query/nonexistent_column.test +33 -0
- data/test/command/suite/search/condition/query/syntax_error.catalog.json +36 -0
- data/test/command/suite/search/condition/query/syntax_error.expected +48 -0
- data/test/command/suite/search/condition/query/syntax_error.test +33 -0
- data/test/command/suite/search/condition/query.expected +24 -0
- data/test/command/suite/search/condition/query.test +23 -0
- data/test/command/suite/search/condition/script.expected +24 -0
- data/test/command/suite/search/condition/script.test +26 -0
- data/test/command/suite/search/error/cyclic-source.expected +14 -0
- data/test/command/suite/search/error/cyclic-source.test +12 -0
- data/test/command/suite/search/error/deeply-cyclic-source.expected +17 -0
- data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
- data/test/command/suite/search/error/missing-source-parameter.expected +13 -0
- data/test/command/suite/search/error/missing-source-parameter.test +11 -0
- data/test/command/suite/search/error/no-query.expected +9 -0
- data/test/command/suite/search/error/no-query.test +7 -0
- data/test/command/suite/search/error/unknown-source.expected +52 -0
- data/test/command/suite/search/error/unknown-source.test +12 -0
- data/test/command/suite/search/group/count.expected +10 -0
- data/test/command/suite/search/group/count.test +18 -0
- data/test/command/suite/search/group/limit.expected +15 -0
- data/test/command/suite/search/group/limit.test +20 -0
- data/test/command/suite/search/group/string.expected +32 -0
- data/test/command/suite/search/group/string.test +40 -0
- data/test/command/suite/search/group/subrecord/with-sort.catalog.json +33 -0
- data/test/command/suite/search/group/subrecord/with-sort.expected +30 -0
- data/test/command/suite/search/group/subrecord/with-sort.test +81 -0
- data/test/command/suite/search/multiple/chained.expected +41 -0
- data/test/command/suite/search/multiple/chained.test +39 -0
- data/test/command/suite/search/multiple/parallel.expected +35 -0
- data/test/command/suite/search/multiple/parallel.test +35 -0
- data/test/command/suite/search/output/attributes/invalid.catalog.json +13 -0
- data/test/command/suite/search/output/attributes/invalid.expected +44 -0
- data/test/command/suite/search/output/attributes/invalid.test +28 -0
- data/test/command/suite/search/range/only-output.expected +24 -0
- data/test/command/suite/search/range/only-output.test +23 -0
- data/test/command/suite/search/range/only-sort.expected +24 -0
- data/test/command/suite/search/range/only-sort.test +26 -0
- data/test/command/suite/search/range/sort-and-output.expected +21 -0
- data/test/command/suite/search/range/sort-and-output.test +27 -0
- data/test/command/suite/search/range/too-large-output-offset.expected +12 -0
- data/test/command/suite/search/range/too-large-output-offset.test +23 -0
- data/test/command/suite/search/range/too-large-sort-offset.expected +12 -0
- data/test/command/suite/search/range/too-large-sort-offset.test +26 -0
- data/test/command/suite/search/response/elapsed_time.catalog.json +13 -0
- data/test/command/suite/search/response/elapsed_time.expected +11 -0
- data/test/command/suite/search/response/elapsed_time.test +26 -0
- data/test/command/suite/search/response/records/value/time.expected +20 -0
- data/test/command/suite/search/response/records/value/time.test +22 -0
- data/test/command/suite/search/simple.expected +48 -0
- data/test/command/suite/search/simple.test +22 -0
- data/test/command/suite/search/sort/default-offset-limit.expected +39 -0
- data/test/command/suite/search/sort/default-offset-limit.test +24 -0
- data/test/command/suite/search/sort/invisible-column.expected +24 -0
- data/test/command/suite/search/sort/invisible-column.test +26 -0
- data/test/command/suite/watch/subscribe.expected +6 -0
- data/test/command/suite/watch/subscribe.test +9 -0
- data/test/command/suite/watch/unsubscribe.expected +6 -0
- data/test/command/suite/watch/unsubscribe.test +9 -0
- data/test/performance/run-test.rb +56 -0
- data/test/performance/watch/catalog.json +33 -0
- data/test/performance/watch/feed.json +9 -0
- data/test/performance/watch/fluentd.conf +11 -0
- data/test/performance/watch/subscribe.json +3 -0
- data/test/unit/catalog/test_collection_volume.rb +103 -0
- data/test/unit/catalog/test_dataset.rb +104 -0
- data/test/unit/catalog/test_schema.rb +226 -0
- data/test/unit/catalog/test_single_volume.rb +31 -0
- data/test/unit/catalog/test_slice.rb +92 -0
- data/test/unit/catalog/test_version1.rb +361 -0
- data/test/unit/catalog/test_version2.rb +124 -0
- data/test/unit/catalog/test_version2_validator.rb +66 -0
- data/test/unit/catalog/test_volume_collection.rb +50 -0
- data/test/unit/fixtures/array.grn +18 -0
- data/test/unit/fixtures/catalog/version1.json +40 -0
- data/test/unit/fixtures/catalog/version2.json +62 -0
- data/test/unit/fixtures/document.grn +34 -0
- data/test/unit/fixtures/reference/array.grn +11 -0
- data/test/unit/fixtures/reference/hash.grn +7 -0
- data/test/unit/helper/distributed_search_planner_helper.rb +83 -0
- data/test/unit/helper/fixture.rb +28 -0
- data/test/unit/helper/plugin_helper.rb +38 -0
- data/test/unit/helper/sandbox.rb +86 -0
- data/test/unit/helper/stub_worker.rb +27 -0
- data/test/unit/helper/watch_helper.rb +23 -0
- data/test/unit/helper.rb +28 -0
- data/test/unit/plugins/crud/test_add.rb +190 -0
- data/test/unit/plugins/groonga/select/test_adapter_input.rb +510 -0
- data/test/unit/plugins/groonga/select/test_adapter_output.rb +201 -0
- data/test/unit/plugins/groonga/test_column_create.rb +171 -0
- data/test/unit/plugins/groonga/test_column_list.rb +170 -0
- data/test/unit/plugins/groonga/test_column_remove.rb +98 -0
- data/test/unit/plugins/groonga/test_column_rename.rb +105 -0
- data/test/unit/plugins/groonga/test_delete.rb +127 -0
- data/test/unit/plugins/groonga/test_table_create.rb +147 -0
- data/test/unit/plugins/groonga/test_table_list.rb +184 -0
- data/test/unit/plugins/groonga/test_table_remove.rb +61 -0
- data/test/unit/plugins/search/planner/test_basic.rb +120 -0
- data/test/unit/plugins/search/planner/test_group_by.rb +573 -0
- data/test/unit/plugins/search/planner/test_output.rb +388 -0
- data/test/unit/plugins/search/planner/test_sort_by.rb +938 -0
- data/test/unit/plugins/search/test_collector.rb +806 -0
- data/test/unit/plugins/search/test_handler.rb +930 -0
- data/test/unit/plugins/search/test_planner.rb +174 -0
- data/test/unit/plugins/test_basic.rb +510 -0
- data/test/unit/plugins/test_groonga.rb +70 -0
- data/test/unit/plugins/test_watch.rb +211 -0
- data/test/unit/run-test.rb +56 -0
- data/test/unit/test_catalog_generator.rb +93 -0
- data/test/unit/test_message_matcher.rb +160 -0
- data/test/unit/test_schema_applier.rb +59 -0
- data/test/unit/test_sweeper.rb +95 -0
- data/test/unit/test_watch_schema.rb +57 -0
- data/test/unit/test_watcher.rb +336 -0
- metadata +759 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2013 Droonga Project
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
|
|
18
|
+
require "tsort"
|
|
19
|
+
|
|
20
|
+
module Droonga
|
|
21
|
+
class Distributor
|
|
22
|
+
class UndefinedInputError < StandardError
|
|
23
|
+
attr_reader :input
|
|
24
|
+
def initialize(input)
|
|
25
|
+
@input = input
|
|
26
|
+
super("undefined input assigned: <#{input}>")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class CyclicStepsError < StandardError
|
|
31
|
+
attr_reader :steps
|
|
32
|
+
def initialize(steps)
|
|
33
|
+
@steps = steps
|
|
34
|
+
super("cyclic steps found: <#{steps}>")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
include TSort
|
|
39
|
+
|
|
40
|
+
def initialize(dispatcher, plan)
|
|
41
|
+
@dispatcher = dispatcher
|
|
42
|
+
@plan = plan
|
|
43
|
+
build_dependencies
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def distribute
|
|
47
|
+
steps = []
|
|
48
|
+
each_strongly_connected_component do |nodes|
|
|
49
|
+
raise CyclicStepsError.new(nodes) if nodes.size > 1
|
|
50
|
+
nodes.each do |node|
|
|
51
|
+
steps << @step_maps[node] if node.is_a?(Integer)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
@dispatcher.dispatch_steps(steps)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
def build_dependencies
|
|
59
|
+
@dependencies = {}
|
|
60
|
+
@step_maps = {}
|
|
61
|
+
step_id = 0
|
|
62
|
+
@plan.each do |step|
|
|
63
|
+
step_id += 1
|
|
64
|
+
# Integer#hash (step_id.hash) is very faster than Hash#hash (step.hash).
|
|
65
|
+
@step_maps[step_id] = step
|
|
66
|
+
@dependencies[step_id] = step["inputs"]
|
|
67
|
+
next unless step["outputs"]
|
|
68
|
+
step["outputs"].each do |output|
|
|
69
|
+
@dependencies[output] = [step_id]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def tsort_each_node(&block)
|
|
75
|
+
@dependencies.each_key(&block)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def tsort_each_child(node, &block)
|
|
79
|
+
if node.is_a? String and @dependencies[node].nil?
|
|
80
|
+
raise UndefinedInputError.new(node)
|
|
81
|
+
end
|
|
82
|
+
if @dependencies[node]
|
|
83
|
+
@dependencies[node].each(&block)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "optparse"
|
|
17
|
+
require "socket"
|
|
18
|
+
require "ipaddr"
|
|
19
|
+
require "fileutils"
|
|
20
|
+
|
|
21
|
+
require "droonga/engine"
|
|
22
|
+
require "droonga/event_loop"
|
|
23
|
+
require "droonga/fluent_message_receiver"
|
|
24
|
+
require "droonga/plugin_loader"
|
|
25
|
+
|
|
26
|
+
module Droonga
|
|
27
|
+
class Engine
|
|
28
|
+
module Command
|
|
29
|
+
module DroongaEngine
|
|
30
|
+
module Signals
|
|
31
|
+
include ServerEngine::Daemon::Signals
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class Configuration
|
|
35
|
+
DEFAULT_HOST = Socket.gethostname
|
|
36
|
+
DEFAULT_PORT = 10031
|
|
37
|
+
|
|
38
|
+
attr_reader :host, :port, :tag, :log_file, :pid_file
|
|
39
|
+
def initialize
|
|
40
|
+
@host = DEFAULT_HOST
|
|
41
|
+
@port = DEFAULT_PORT
|
|
42
|
+
@tag = "droonga"
|
|
43
|
+
@log_file = nil
|
|
44
|
+
@daemon = false
|
|
45
|
+
@pid_file = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def engine_name
|
|
49
|
+
"#{@host}:#{@port}/#{@tag}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def address_family
|
|
53
|
+
ip_address = IPAddr.new(IPSocket.getaddress(@host))
|
|
54
|
+
ip_address.family
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def log_level
|
|
58
|
+
ENV["DROONGA_LOG_LEVEL"] || Logger::Level.default_label
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def daemon?
|
|
62
|
+
@daemon
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def to_command_line
|
|
66
|
+
[
|
|
67
|
+
"--host", @host,
|
|
68
|
+
"--port", @port.to_s,
|
|
69
|
+
"--tag", @tag,
|
|
70
|
+
"--log-level", log_level,
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def add_command_line_options(parser)
|
|
75
|
+
add_connection_options(parser)
|
|
76
|
+
add_log_options(parser)
|
|
77
|
+
add_process_options(parser)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
def add_connection_options(parser)
|
|
82
|
+
parser.separator("")
|
|
83
|
+
parser.separator("Connection:")
|
|
84
|
+
parser.on("--host=HOST",
|
|
85
|
+
"The host name of the Droonga engine",
|
|
86
|
+
"(#{@host})") do |host|
|
|
87
|
+
@host = host
|
|
88
|
+
end
|
|
89
|
+
parser.on("--port=PORT", Integer,
|
|
90
|
+
"The port number of the Droonga engine",
|
|
91
|
+
"(#{@port})") do |port|
|
|
92
|
+
@port = port
|
|
93
|
+
end
|
|
94
|
+
parser.on("--tag=TAG",
|
|
95
|
+
"The tag of the Droonga engine",
|
|
96
|
+
"(#{@tag})") do |tag|
|
|
97
|
+
@tag = tag
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def add_log_options(parser)
|
|
102
|
+
parser.separator("")
|
|
103
|
+
parser.separator("Log:")
|
|
104
|
+
levels = Logger::Level::LABELS
|
|
105
|
+
levels_label = levels.join(",")
|
|
106
|
+
parser.on("--log-level=LEVEL", levels,
|
|
107
|
+
"The log level of the Droonga engine",
|
|
108
|
+
"[#{levels_label}]",
|
|
109
|
+
"(#{log_level})") do |level|
|
|
110
|
+
ENV["DROONGA_LOG_LEVEL"] = level
|
|
111
|
+
end
|
|
112
|
+
parser.on("--log-file=FILE",
|
|
113
|
+
"Output logs to FILE") do |file|
|
|
114
|
+
@log_file = file
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def add_process_options(parser)
|
|
119
|
+
parser.separator("")
|
|
120
|
+
parser.separator("Process:")
|
|
121
|
+
parser.on("--daemon",
|
|
122
|
+
"Run as a daemon") do
|
|
123
|
+
@daemon = true
|
|
124
|
+
end
|
|
125
|
+
parser.on("--pid-file=FILE",
|
|
126
|
+
"Put PID to the FILE") do |file|
|
|
127
|
+
@pid_file = file
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class Supervisor
|
|
133
|
+
class << self
|
|
134
|
+
def run(command_line_arguments)
|
|
135
|
+
new.run(command_line_arguments)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def initialize
|
|
140
|
+
@configuration = Configuration.new
|
|
141
|
+
@log_output = nil
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def run(command_line_arguments)
|
|
145
|
+
parse_command_line_arguments!(command_line_arguments)
|
|
146
|
+
|
|
147
|
+
@listen_socket = TCPServer.new(@configuration.host,
|
|
148
|
+
@configuration.port)
|
|
149
|
+
@heartbeat_socket = UDPSocket.new(@configuration.address_family)
|
|
150
|
+
@heartbeat_socket.bind(@configuration.host,
|
|
151
|
+
@configuration.port)
|
|
152
|
+
|
|
153
|
+
if @configuration.daemon?
|
|
154
|
+
ENV["DROONGA_CATALOG"] ||= "catalog.json"
|
|
155
|
+
ENV["DROONGA_CATALOG"] = File.expand_path(ENV["DROONGA_CATALOG"])
|
|
156
|
+
Process.daemon
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
open_log_file do
|
|
160
|
+
write_pid_file do
|
|
161
|
+
run_main_loop
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
def parse_command_line_arguments!(command_line_arguments)
|
|
168
|
+
parser = OptionParser.new
|
|
169
|
+
@configuration.add_command_line_options(parser)
|
|
170
|
+
parser.parse!(command_line_arguments)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def run_service(ready_notify_fd=nil)
|
|
174
|
+
listen_fd = @listen_socket.fileno
|
|
175
|
+
heartbeat_fd = @heartbeat_socket.fileno
|
|
176
|
+
env = {}
|
|
177
|
+
command_line = [
|
|
178
|
+
RbConfig.ruby,
|
|
179
|
+
"-S",
|
|
180
|
+
"#{$0}-service",
|
|
181
|
+
"--listen-fd", listen_fd.to_s,
|
|
182
|
+
"--heartbeat-fd", heartbeat_fd.to_s,
|
|
183
|
+
*@configuration.to_command_line
|
|
184
|
+
]
|
|
185
|
+
options = {
|
|
186
|
+
listen_fd => listen_fd,
|
|
187
|
+
heartbeat_fd => heartbeat_fd,
|
|
188
|
+
}
|
|
189
|
+
if ready_notify_fd
|
|
190
|
+
command_line.push("--ready-notify-fd", ready_notify_fd.to_s)
|
|
191
|
+
options[ready_notify_fd] = ready_notify_fd
|
|
192
|
+
end
|
|
193
|
+
if @log_output
|
|
194
|
+
options[:out] = @log_output
|
|
195
|
+
options[:err] = @log_output
|
|
196
|
+
end
|
|
197
|
+
spawn(env, *command_line, options)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def run_main_loop
|
|
201
|
+
service_pid = nil
|
|
202
|
+
running = true
|
|
203
|
+
|
|
204
|
+
trap(:INT) do
|
|
205
|
+
Process.kill(:INT, service_pid)
|
|
206
|
+
running = false
|
|
207
|
+
end
|
|
208
|
+
trap(Signals::GRACEFUL_STOP) do
|
|
209
|
+
Process.kill(Signals::GRACEFUL_STOP, service_pid)
|
|
210
|
+
running = false
|
|
211
|
+
end
|
|
212
|
+
trap(Signals::IMMEDIATE_STOP) do
|
|
213
|
+
Process.kill(Signals::IMMEDIATE_STOP, service_pid)
|
|
214
|
+
running = false
|
|
215
|
+
end
|
|
216
|
+
trap(Signals::GRACEFUL_RESTART) do
|
|
217
|
+
old_service_pid = service_pid
|
|
218
|
+
IO.pipe do |ready_notify_read_io, ready_notify_write_io|
|
|
219
|
+
service_pid = run_service(ready_notify_write_io.fileno)
|
|
220
|
+
ready_notify_write_io.close
|
|
221
|
+
IO.select([ready_notify_read_io])
|
|
222
|
+
Process.kill(Signals::GRACEFUL_STOP, old_service_pid)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
trap(Signals::IMMEDIATE_RESTART) do
|
|
226
|
+
old_service_pid = service_pid
|
|
227
|
+
service_pid = run_service
|
|
228
|
+
Process.kill(Signals::IMMEDIATE_STOP, old_service_pid)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
succeeded = true
|
|
232
|
+
while running
|
|
233
|
+
service_pid ||= run_service
|
|
234
|
+
finished_pid, status = Process.waitpid2(service_pid)
|
|
235
|
+
service_pid = nil if service_pid == finished_pid
|
|
236
|
+
if status.nil?
|
|
237
|
+
succeeded = false
|
|
238
|
+
break
|
|
239
|
+
end
|
|
240
|
+
unless status.success?
|
|
241
|
+
succeeded = false
|
|
242
|
+
break
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
succeeded
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def open_log_file
|
|
250
|
+
if @configuration.log_file
|
|
251
|
+
File.open(@configuration.log_file, "a") do |file|
|
|
252
|
+
@log_output = file
|
|
253
|
+
yield
|
|
254
|
+
end
|
|
255
|
+
else
|
|
256
|
+
yield
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def write_pid_file
|
|
261
|
+
if @configuration.pid_file
|
|
262
|
+
File.open(@configuration.pid_file, "w") do |file|
|
|
263
|
+
file.puts(Process.pid)
|
|
264
|
+
end
|
|
265
|
+
begin
|
|
266
|
+
yield
|
|
267
|
+
ensure
|
|
268
|
+
FileUtils.rm_f(@configuration.pid_file)
|
|
269
|
+
end
|
|
270
|
+
else
|
|
271
|
+
yield
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
class Service
|
|
277
|
+
class << self
|
|
278
|
+
def run(command_line_arguments)
|
|
279
|
+
new.run(command_line_arguments)
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def initialize
|
|
284
|
+
@configuration = Configuration.new
|
|
285
|
+
@listen_fd = nil
|
|
286
|
+
@heartbeat_fd = nil
|
|
287
|
+
@ready_notiofy_fd = nil
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def run(command_line_arguments)
|
|
291
|
+
parse_command_line_arguments!(command_line_arguments)
|
|
292
|
+
PluginLoader.load_all
|
|
293
|
+
|
|
294
|
+
begin
|
|
295
|
+
run_services
|
|
296
|
+
ensure
|
|
297
|
+
shutdown_services
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
true
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
private
|
|
304
|
+
def parse_command_line_arguments!(command_line_arguments)
|
|
305
|
+
parser = OptionParser.new
|
|
306
|
+
@configuration.add_command_line_options(parser)
|
|
307
|
+
add_internal_options(parser)
|
|
308
|
+
parser.parse!(command_line_arguments)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def add_internal_options(parser)
|
|
312
|
+
parser.separator("")
|
|
313
|
+
parser.separator("Internal:")
|
|
314
|
+
parser.on("--listen-fd=FD", Integer,
|
|
315
|
+
"Use FD as the listen file descriptor") do |fd|
|
|
316
|
+
@listen_fd = fd
|
|
317
|
+
end
|
|
318
|
+
parser.on("--heartbeat-fd=FD", Integer,
|
|
319
|
+
"Use FD as the heartbeat file descriptor") do |fd|
|
|
320
|
+
@heartbeat_fd = fd
|
|
321
|
+
end
|
|
322
|
+
parser.on("--ready-notify-fd=FD", Integer,
|
|
323
|
+
"Use FD for notifying the service ready") do |fd|
|
|
324
|
+
@ready_notify_fd = fd
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def run_services
|
|
329
|
+
@engine = nil
|
|
330
|
+
@receiver = nil
|
|
331
|
+
raw_loop = Coolio::Loop.default
|
|
332
|
+
@loop = EventLoop.new(raw_loop)
|
|
333
|
+
|
|
334
|
+
run_engine
|
|
335
|
+
run_receiver
|
|
336
|
+
setup_signals
|
|
337
|
+
notify_ready
|
|
338
|
+
@loop.run
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def shutdown_services
|
|
342
|
+
shutdown_receiver
|
|
343
|
+
shutdown_engine
|
|
344
|
+
@loop = nil
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def run_engine
|
|
348
|
+
@engine = Engine.new(@loop, @configuration.engine_name)
|
|
349
|
+
@engine.start
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def shutdown_engine
|
|
353
|
+
return if @engine.nil?
|
|
354
|
+
@engine.shutdown
|
|
355
|
+
@engine = nil
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def run_receiver
|
|
359
|
+
@receiver = create_receiver
|
|
360
|
+
@receiver.start
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def shutdown_receiver
|
|
364
|
+
return if @receiver.nil?
|
|
365
|
+
@receiver.shutdown
|
|
366
|
+
@receiver = nil
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def create_receiver
|
|
370
|
+
options = {
|
|
371
|
+
:host => @host,
|
|
372
|
+
:port => @port,
|
|
373
|
+
:listen_fd => @listen_fd,
|
|
374
|
+
:heartbeat_fd => @heartbeat_fd,
|
|
375
|
+
}
|
|
376
|
+
FluentMessageReceiver.new(@loop, options) do |tag, time, record|
|
|
377
|
+
on_message(tag, time, record)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def on_message(tag, time, record)
|
|
382
|
+
prefix, type, *arguments = tag.split(/\./)
|
|
383
|
+
if type.nil? or type.empty? or type == "message"
|
|
384
|
+
message = record
|
|
385
|
+
else
|
|
386
|
+
message = {
|
|
387
|
+
"type" => type,
|
|
388
|
+
"arguments" => arguments,
|
|
389
|
+
"body" => record
|
|
390
|
+
}
|
|
391
|
+
end
|
|
392
|
+
reply_to = message["replyTo"]
|
|
393
|
+
if reply_to.is_a? String
|
|
394
|
+
message["replyTo"] = {
|
|
395
|
+
"type" => "#{message["type"]}.result",
|
|
396
|
+
"to" => reply_to
|
|
397
|
+
}
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
@engine.process(message)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def setup_signals
|
|
404
|
+
trap(Signals::GRACEFUL_STOP) do
|
|
405
|
+
stop_graceful
|
|
406
|
+
end
|
|
407
|
+
trap(Signals::IMMEDIATE_STOP) do
|
|
408
|
+
stop_immediate
|
|
409
|
+
end
|
|
410
|
+
trap(:INT) do
|
|
411
|
+
stop_immediate
|
|
412
|
+
trap(:INT, "DEFAULT")
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def stop_graceful
|
|
417
|
+
@loop.stop if @loop
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def stop_immediate
|
|
421
|
+
stop_graceful
|
|
422
|
+
shutdown_services
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def notify_ready
|
|
426
|
+
return if @ready_notify_fd.nil?
|
|
427
|
+
ready_notify_io = IO.new(@ready_notify_fd)
|
|
428
|
+
@ready_notify_fd = nil
|
|
429
|
+
watcher = Coolio::IOWatcher.new(ready_notify_io, "w")
|
|
430
|
+
@loop.attach(watcher)
|
|
431
|
+
watcher.on_writable do
|
|
432
|
+
ready_notify_io.write("ready\n")
|
|
433
|
+
ready_notify_io.close
|
|
434
|
+
detach
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
module Droonga
|
|
17
|
+
class Engine
|
|
18
|
+
VERSION = "1.0.1"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2013-2014 Droonga Project
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License version 2.1 as published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This library is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
+
# Lesser General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
17
|
+
|
|
18
|
+
require "droonga/engine/version"
|
|
19
|
+
require "droonga/loggable"
|
|
20
|
+
require "droonga/engine_state"
|
|
21
|
+
require "droonga/catalog_observer"
|
|
22
|
+
require "droonga/dispatcher"
|
|
23
|
+
|
|
24
|
+
module Droonga
|
|
25
|
+
class Engine
|
|
26
|
+
include Loggable
|
|
27
|
+
|
|
28
|
+
def initialize(loop, name)
|
|
29
|
+
@state = EngineState.new(loop, name)
|
|
30
|
+
@catalog_observer = Droonga::CatalogObserver.new(@state.loop)
|
|
31
|
+
@catalog_observer.on_reload = lambda do |catalog|
|
|
32
|
+
graceful_restart(catalog)
|
|
33
|
+
logger.info("restarted")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def start
|
|
38
|
+
logger.trace("start: start")
|
|
39
|
+
@state.start
|
|
40
|
+
@catalog_observer.start
|
|
41
|
+
catalog = @catalog_observer.catalog
|
|
42
|
+
@dispatcher = create_dispatcher(catalog)
|
|
43
|
+
@dispatcher.start
|
|
44
|
+
logger.trace("start: done")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def shutdown
|
|
48
|
+
logger.trace("shutdown: start")
|
|
49
|
+
@catalog_observer.stop
|
|
50
|
+
@dispatcher.shutdown
|
|
51
|
+
@state.shutdown
|
|
52
|
+
logger.trace("shutdown: done")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def process(message)
|
|
56
|
+
@dispatcher.process_message(message)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
def create_dispatcher(catalog)
|
|
61
|
+
Dispatcher.new(@state, catalog)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def graceful_restart(catalog)
|
|
65
|
+
logger.trace("graceful_restart: start")
|
|
66
|
+
old_dispatcher = @dispatcher
|
|
67
|
+
logger.trace("graceful_restart: creating new dispatcher")
|
|
68
|
+
new_dispatcher = create_dispatcher(catalog)
|
|
69
|
+
new_dispatcher.start
|
|
70
|
+
@dispatcher = new_dispatcher
|
|
71
|
+
logger.trace("graceful_restart: shutdown old dispatcher")
|
|
72
|
+
old_dispatcher.shutdown
|
|
73
|
+
logger.trace("graceful_restart: done")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def log_tag
|
|
77
|
+
"engine"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "coolio"
|
|
17
|
+
|
|
18
|
+
require "droonga/loggable"
|
|
19
|
+
require "droonga/event_loop"
|
|
20
|
+
require "droonga/forwarder"
|
|
21
|
+
require "droonga/replier"
|
|
22
|
+
|
|
23
|
+
module Droonga
|
|
24
|
+
class EngineState
|
|
25
|
+
include Loggable
|
|
26
|
+
|
|
27
|
+
attr_reader :loop
|
|
28
|
+
attr_reader :name
|
|
29
|
+
attr_reader :forwarder
|
|
30
|
+
attr_reader :replier
|
|
31
|
+
def initialize(loop, name)
|
|
32
|
+
@loop = loop
|
|
33
|
+
@name = name
|
|
34
|
+
@sessions = {}
|
|
35
|
+
@current_id = 0
|
|
36
|
+
@forwarder = Forwarder.new(@loop)
|
|
37
|
+
@replier = Replier.new(@forwarder)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def start
|
|
41
|
+
logger.trace("start start")
|
|
42
|
+
@forwarder.start
|
|
43
|
+
logger.trace("start done")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def shutdown
|
|
47
|
+
logger.trace("shutdown: start")
|
|
48
|
+
@forwarder.shutdown
|
|
49
|
+
logger.trace("shutdown: done")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def local_route?(route)
|
|
53
|
+
route.start_with?(@name)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def generate_id
|
|
57
|
+
id = @current_id
|
|
58
|
+
@current_id = id.succ
|
|
59
|
+
return [@name, id].join(".#")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def find_session(id)
|
|
63
|
+
@sessions[id]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def register_session(id, session)
|
|
67
|
+
@sessions[id] = session
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def unregister_session(id)
|
|
71
|
+
@sessions.delete(id)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
def log_tag
|
|
76
|
+
"engine_state"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|