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,64 @@
|
|
|
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 "droonga/loggable"
|
|
17
|
+
require "droonga/message_matcher"
|
|
18
|
+
require "droonga/collector"
|
|
19
|
+
require "droonga/collector_message"
|
|
20
|
+
|
|
21
|
+
module Droonga
|
|
22
|
+
class CollectorRunner
|
|
23
|
+
include Loggable
|
|
24
|
+
|
|
25
|
+
def initialize(plugins)
|
|
26
|
+
default_plugins = ["basic"]
|
|
27
|
+
plugins += (default_plugins - plugins)
|
|
28
|
+
@collector_classes = Collector.find_sub_classes(plugins)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def shutdown
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def collect(message)
|
|
35
|
+
collector_message = CollectorMessage.new(message)
|
|
36
|
+
logger.trace("collect: start",
|
|
37
|
+
:type => collector_message.type)
|
|
38
|
+
collector_class = find_collector_class(message)
|
|
39
|
+
if collector_class.nil?
|
|
40
|
+
raise UnsupportedMessageError.new(:collector, message)
|
|
41
|
+
end
|
|
42
|
+
collector = collector_class.new
|
|
43
|
+
collector.collect(collector_message)
|
|
44
|
+
logger.trace("collector: done")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
def find_collector_class(message)
|
|
49
|
+
@collector_classes.find do |collector_class|
|
|
50
|
+
pattern = collector_class.message.pattern
|
|
51
|
+
if pattern
|
|
52
|
+
matcher = MessageMatcher.new(pattern)
|
|
53
|
+
matcher.match?(message)
|
|
54
|
+
else
|
|
55
|
+
false
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def log_tag
|
|
61
|
+
"collector-runner"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
module Collectors
|
|
18
|
+
class And
|
|
19
|
+
class << self
|
|
20
|
+
def operator
|
|
21
|
+
"and"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
module Collectors
|
|
18
|
+
class Or
|
|
19
|
+
class << self
|
|
20
|
+
def operator
|
|
21
|
+
"or"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
module Collectors
|
|
18
|
+
class Sum
|
|
19
|
+
class << self
|
|
20
|
+
def operator
|
|
21
|
+
"sum"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
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 "droonga/collectors/and"
|
|
17
|
+
require "droonga/collectors/or"
|
|
18
|
+
require "droonga/collectors/sum"
|
|
@@ -0,0 +1,326 @@
|
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
15
|
+
|
|
16
|
+
require "English"
|
|
17
|
+
require "tsort"
|
|
18
|
+
|
|
19
|
+
require "droonga/loggable"
|
|
20
|
+
require "droonga/adapter_runner"
|
|
21
|
+
require "droonga/collector_runner"
|
|
22
|
+
require "droonga/step_runner"
|
|
23
|
+
require "droonga/farm"
|
|
24
|
+
require "droonga/session"
|
|
25
|
+
require "droonga/error_messages"
|
|
26
|
+
require "droonga/distributor"
|
|
27
|
+
|
|
28
|
+
module Droonga
|
|
29
|
+
class Dispatcher
|
|
30
|
+
include Loggable
|
|
31
|
+
|
|
32
|
+
class MissingDatasetParameter < ErrorMessages::BadRequest
|
|
33
|
+
def initialize
|
|
34
|
+
super("Missing required parameter: <dataset>")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class UnknownDataset < ErrorMessages::NotFound
|
|
39
|
+
def initialize(dataset)
|
|
40
|
+
super("Unknown dataset: <#{dataset}>")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class UnknownType < ErrorMessages::BadRequest
|
|
45
|
+
def initialize(type, dataset)
|
|
46
|
+
super("[#{dataset}] Handler not found for the type: <#{type}>")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def initialize(engine_state, catalog)
|
|
51
|
+
@engine_state = engine_state
|
|
52
|
+
@catalog = catalog
|
|
53
|
+
@adapter_runners = create_adapter_runners
|
|
54
|
+
@farm = Farm.new(@engine_state.name, @catalog, @engine_state.loop,
|
|
55
|
+
:dispatcher => self)
|
|
56
|
+
@collector_runners = create_collector_runners
|
|
57
|
+
@step_runners = create_step_runners
|
|
58
|
+
@forwarder = @engine_state.forwarder
|
|
59
|
+
@replier = @engine_state.replier
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def start
|
|
63
|
+
@farm.start
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def shutdown
|
|
67
|
+
@collector_runners.each_value do |collector_runner|
|
|
68
|
+
collector_runner.shutdown
|
|
69
|
+
end
|
|
70
|
+
@adapter_runners.each_value do |adapter_runner|
|
|
71
|
+
adapter_runner.shutdown
|
|
72
|
+
end
|
|
73
|
+
@farm.shutdown
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def process_message(message)
|
|
77
|
+
@message = message
|
|
78
|
+
if message["type"] == "dispatcher"
|
|
79
|
+
process_internal_message(message["body"])
|
|
80
|
+
else
|
|
81
|
+
begin
|
|
82
|
+
assert_valid_message(message)
|
|
83
|
+
process_input_message(message)
|
|
84
|
+
rescue ErrorMessage => error
|
|
85
|
+
reply("statusCode" => error.status_code,
|
|
86
|
+
"body" => error.response_body)
|
|
87
|
+
rescue StandardError, LoadError, SyntaxError => error
|
|
88
|
+
logger.exception("failed to process input message", error)
|
|
89
|
+
formatted_error = ErrorMessages::InternalServerError.new("Unknown internal error")
|
|
90
|
+
reply("statusCode" => formatted_error.status_code,
|
|
91
|
+
"body" => formatted_error.response_body)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def forward(message, destination)
|
|
97
|
+
logger.trace("forward start")
|
|
98
|
+
@forwarder.forward(message, destination)
|
|
99
|
+
logger.trace("forward done")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Replies response to replyTo.
|
|
103
|
+
#
|
|
104
|
+
# @param [Hash] message
|
|
105
|
+
# The message to be replied. See {Replier#reply} for available keys.
|
|
106
|
+
#
|
|
107
|
+
# The key-value pairs in request message are used as the default
|
|
108
|
+
# key-value pairs. For example, if the passed message doesn't
|
|
109
|
+
# include `id` key, `id` key's value is used in request message.
|
|
110
|
+
#
|
|
111
|
+
# @return [void]
|
|
112
|
+
#
|
|
113
|
+
# @see Replier#reply
|
|
114
|
+
def reply(message)
|
|
115
|
+
adapted_message = @message.merge(message)
|
|
116
|
+
adapter_runner = @adapter_runners[adapted_message["dataset"]]
|
|
117
|
+
if adapter_runner
|
|
118
|
+
adapted_message = adapter_runner.adapt_output(adapted_message)
|
|
119
|
+
end
|
|
120
|
+
if adapted_message["replyTo"].nil?
|
|
121
|
+
status_code = adapted_message["statusCode"] || 200
|
|
122
|
+
if status_code != 200
|
|
123
|
+
dataset = adapted_message["dataset"]
|
|
124
|
+
body = adapted_message["body"] || {}
|
|
125
|
+
name = body["name"] || "Unknown"
|
|
126
|
+
message = body["message"] || "unknown error"
|
|
127
|
+
logger.error("orphan error: " +
|
|
128
|
+
"<#{dataset}>[#{name}](#{status_code}): #{message}")
|
|
129
|
+
end
|
|
130
|
+
else
|
|
131
|
+
@replier.reply(adapted_message)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def process_internal_message(message)
|
|
136
|
+
id = message["id"]
|
|
137
|
+
session = @engine_state.find_session(id)
|
|
138
|
+
if session
|
|
139
|
+
session.receive(message["input"], message["value"])
|
|
140
|
+
else
|
|
141
|
+
steps = message["steps"]
|
|
142
|
+
if steps
|
|
143
|
+
session_planner = SessionPlanner.new(self, steps)
|
|
144
|
+
dataset = message["dataset"] || @message["dataset"]
|
|
145
|
+
collector_runner = @collector_runners[dataset]
|
|
146
|
+
session = session_planner.create_session(id, collector_runner)
|
|
147
|
+
@engine_state.register_session(id, session)
|
|
148
|
+
else
|
|
149
|
+
#todo: take cases receiving result before its query into account
|
|
150
|
+
end
|
|
151
|
+
session.start
|
|
152
|
+
end
|
|
153
|
+
@engine_state.unregister_session(id) if session.done?
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def dispatch(message, destination)
|
|
157
|
+
if local?(destination)
|
|
158
|
+
process_internal_message(message)
|
|
159
|
+
else
|
|
160
|
+
@forwarder.forward(@message.merge("body" => message),
|
|
161
|
+
"type" => "dispatcher",
|
|
162
|
+
"to" => destination)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def dispatch_steps(steps)
|
|
167
|
+
id = @engine_state.generate_id
|
|
168
|
+
destinations = {}
|
|
169
|
+
steps.each do |step|
|
|
170
|
+
dataset = step["dataset"]
|
|
171
|
+
if dataset
|
|
172
|
+
routes = @catalog.get_routes(dataset, step)
|
|
173
|
+
step["routes"] = routes
|
|
174
|
+
else
|
|
175
|
+
step["routes"] ||= [id]
|
|
176
|
+
end
|
|
177
|
+
routes = step["routes"]
|
|
178
|
+
routes.each do |route|
|
|
179
|
+
destinations[farm_path(route)] = true
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
dispatch_message = { "id" => id, "steps" => steps }
|
|
183
|
+
destinations.each_key do |destination|
|
|
184
|
+
dispatch(dispatch_message, destination)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def process_local_message(local_message)
|
|
189
|
+
task = local_message["task"]
|
|
190
|
+
slice_name = task["route"]
|
|
191
|
+
step = task["step"]
|
|
192
|
+
command = step["command"]
|
|
193
|
+
descendants = {}
|
|
194
|
+
step["descendants"].each do |name, routes|
|
|
195
|
+
descendants[name] = routes.collect do |route|
|
|
196
|
+
farm_path(route)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
local_message["descendants"] = descendants
|
|
200
|
+
farm_message = @message.merge("body" => local_message,
|
|
201
|
+
"type" => command)
|
|
202
|
+
@farm.process(slice_name, farm_message)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def local?(route)
|
|
206
|
+
@engine_state.local_route?(route)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
def farm_path(route)
|
|
211
|
+
if route =~ /\A.*:\d+\/[^\.]+/
|
|
212
|
+
$MATCH
|
|
213
|
+
else
|
|
214
|
+
route
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def process_input_message(message)
|
|
219
|
+
dataset = message["dataset"]
|
|
220
|
+
adapter_runner = @adapter_runners[dataset]
|
|
221
|
+
adapted_message = adapter_runner.adapt_input(message)
|
|
222
|
+
step_runner = @step_runners[dataset]
|
|
223
|
+
plan = step_runner.plan(adapted_message)
|
|
224
|
+
distributor = Distributor.new(self, plan)
|
|
225
|
+
distributor.distribute
|
|
226
|
+
rescue Droonga::UnsupportedMessageError => error
|
|
227
|
+
target_message = error.message
|
|
228
|
+
raise UnknownType.new(target_message["type"], target_message["dataset"])
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def assert_valid_message(message)
|
|
232
|
+
unless message.key?("dataset")
|
|
233
|
+
raise MissingDatasetParameter.new
|
|
234
|
+
end
|
|
235
|
+
dataset = message["dataset"]
|
|
236
|
+
unless @catalog.have_dataset?(dataset)
|
|
237
|
+
raise UnknownDataset.new(dataset)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def create_runners
|
|
242
|
+
runners = {}
|
|
243
|
+
@catalog.datasets.each do |name, dataset|
|
|
244
|
+
runners[name] = yield(dataset)
|
|
245
|
+
end
|
|
246
|
+
runners
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def create_adapter_runners
|
|
250
|
+
create_runners do |dataset|
|
|
251
|
+
AdapterRunner.new(self, dataset.plugins)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def create_collector_runners
|
|
256
|
+
create_runners do |dataset|
|
|
257
|
+
CollectorRunner.new(dataset.plugins)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def create_step_runners
|
|
262
|
+
create_runners do |dataset|
|
|
263
|
+
StepRunner.new(dataset, dataset.plugins)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def log_tag
|
|
268
|
+
"[#{Process.ppid}][#{Process.pid}] dispatcher"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
class SessionPlanner
|
|
272
|
+
attr_reader :steps
|
|
273
|
+
|
|
274
|
+
def initialize(dispatcher, steps)
|
|
275
|
+
@dispatcher = dispatcher
|
|
276
|
+
@steps = steps
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def create_session(id, collector_runner)
|
|
280
|
+
resolve_descendants
|
|
281
|
+
tasks = []
|
|
282
|
+
inputs = {}
|
|
283
|
+
@steps.each do |step|
|
|
284
|
+
step["routes"].each do |route|
|
|
285
|
+
next unless @dispatcher.local?(route)
|
|
286
|
+
task = {
|
|
287
|
+
"route" => route,
|
|
288
|
+
"step" => step,
|
|
289
|
+
"n_of_inputs" => 0,
|
|
290
|
+
"values" => {}
|
|
291
|
+
}
|
|
292
|
+
tasks << task
|
|
293
|
+
(step["inputs"] || [nil]).each do |input|
|
|
294
|
+
inputs[input] ||= []
|
|
295
|
+
inputs[input] << task
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
Session.new(id, @dispatcher, collector_runner, tasks, inputs)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def resolve_descendants
|
|
303
|
+
@descendants = {}
|
|
304
|
+
@steps.size.times do |index|
|
|
305
|
+
step = @steps[index]
|
|
306
|
+
(step["inputs"] || []).each do |input|
|
|
307
|
+
@descendants[input] ||= []
|
|
308
|
+
@descendants[input] << index
|
|
309
|
+
end
|
|
310
|
+
step["n_of_expects"] = 0
|
|
311
|
+
end
|
|
312
|
+
@steps.each do |step|
|
|
313
|
+
descendants = {}
|
|
314
|
+
(step["outputs"] || []).each do |output|
|
|
315
|
+
descendants[output] = []
|
|
316
|
+
@descendants[output].each do |index|
|
|
317
|
+
@steps[index]["n_of_expects"] += step["routes"].size
|
|
318
|
+
descendants[output].concat(@steps[index]["routes"])
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
step["descendants"] = descendants
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 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
|
+
module Droonga
|
|
19
|
+
class DistributedCommandPlanner
|
|
20
|
+
attr_accessor :key, :dataset
|
|
21
|
+
|
|
22
|
+
REDUCE_SUM = "sum"
|
|
23
|
+
|
|
24
|
+
DEFAULT_LIMIT = -1
|
|
25
|
+
|
|
26
|
+
def initialize(source_message)
|
|
27
|
+
@source_message = source_message
|
|
28
|
+
|
|
29
|
+
@key = nil
|
|
30
|
+
@dataset = nil
|
|
31
|
+
@outputs = []
|
|
32
|
+
|
|
33
|
+
@reducers = []
|
|
34
|
+
@gatherers = []
|
|
35
|
+
@processor = nil
|
|
36
|
+
|
|
37
|
+
plan_errors_handling
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def plan
|
|
41
|
+
unified_reducers + unified_gatherers + [fixed_processor]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def reduce(params=nil)
|
|
45
|
+
return unless params
|
|
46
|
+
params.each do |name, reducer|
|
|
47
|
+
gatherer = nil
|
|
48
|
+
if reducer.is_a?(Hash) and reducer[:gather]
|
|
49
|
+
gatherer = reducer[:gather]
|
|
50
|
+
reducer = reducer[:reduce]
|
|
51
|
+
end
|
|
52
|
+
@reducers << reducer_message(reduce_command, name, reducer)
|
|
53
|
+
@gatherers << gatherer_message(gather_command, name, gatherer)
|
|
54
|
+
@outputs << name
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def scatter(record, options={})
|
|
59
|
+
@processor = {
|
|
60
|
+
"command" => @source_message["type"],
|
|
61
|
+
"dataset" => @dataset || @source_message["dataset"],
|
|
62
|
+
"body" => options[:body] || @source_message["body"],
|
|
63
|
+
"record" => record,
|
|
64
|
+
"type" => "scatter",
|
|
65
|
+
"outputs" => [],
|
|
66
|
+
"replica" => "all",
|
|
67
|
+
"post" => true
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def broadcast(options={})
|
|
72
|
+
processor = {
|
|
73
|
+
"command" => @source_message["type"],
|
|
74
|
+
"dataset" => @dataset || @source_message["dataset"],
|
|
75
|
+
"body" => options[:body] || @source_message["body"],
|
|
76
|
+
"type" => "broadcast",
|
|
77
|
+
"outputs" => [],
|
|
78
|
+
"replica" => "random"
|
|
79
|
+
}
|
|
80
|
+
if options[:write]
|
|
81
|
+
processor["replica"] = "all"
|
|
82
|
+
processor["post"] = true
|
|
83
|
+
end
|
|
84
|
+
@processor = processor
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private
|
|
88
|
+
def reduce_command
|
|
89
|
+
"reduce"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def gather_command
|
|
93
|
+
"gather"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def unified_reducers
|
|
97
|
+
unified_reducers = {}
|
|
98
|
+
@reducers.each do |reducer|
|
|
99
|
+
type = reducer["type"]
|
|
100
|
+
unified = unified_reducers[type]
|
|
101
|
+
if unified
|
|
102
|
+
unified["body"] = unified["body"].merge(reducer["body"])
|
|
103
|
+
unified["inputs"] += reducer["inputs"]
|
|
104
|
+
unified["outputs"] += reducer["outputs"]
|
|
105
|
+
else
|
|
106
|
+
unified_reducers[type] = reducer.dup
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
unified_reducers.values
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def unified_gatherers
|
|
113
|
+
unified_gatherers = {}
|
|
114
|
+
@gatherers.each do |gatherer|
|
|
115
|
+
type = gatherer["type"]
|
|
116
|
+
unified = unified_gatherers[type]
|
|
117
|
+
if unified
|
|
118
|
+
unified["body"] = unified["body"].merge(gatherer["body"])
|
|
119
|
+
unified["inputs"] += gatherer["inputs"]
|
|
120
|
+
else
|
|
121
|
+
unified_gatherers[type] = gatherer.dup
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
unified_gatherers.values
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def fixed_processor
|
|
128
|
+
@processor["outputs"] = @outputs
|
|
129
|
+
@processor
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def reducer_message(command, name, reducer)
|
|
133
|
+
if reducer.is_a?(String)
|
|
134
|
+
reducer = {
|
|
135
|
+
"type" => reducer,
|
|
136
|
+
}
|
|
137
|
+
if reducer["type"] == REDUCE_SUM
|
|
138
|
+
reducer["limit"] = DEFAULT_LIMIT
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
{
|
|
142
|
+
"type" => command,
|
|
143
|
+
"body" => {
|
|
144
|
+
name => {
|
|
145
|
+
output_name(name) => reducer,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
"inputs" => [name],
|
|
149
|
+
"outputs" => [output_name(name)],
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def gatherer_message(command, name, gatherer=nil)
|
|
154
|
+
gatherer ||= {}
|
|
155
|
+
{
|
|
156
|
+
"type" => command,
|
|
157
|
+
"body" => {
|
|
158
|
+
output_name(name) => {
|
|
159
|
+
"output" => name,
|
|
160
|
+
}.merge(gatherer),
|
|
161
|
+
},
|
|
162
|
+
"inputs" => [output_name(name)],
|
|
163
|
+
"post" => true,
|
|
164
|
+
}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def output_name(name)
|
|
168
|
+
"#{name}_reduced"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
#XXX Now, we include definitions to merge errors in the body.
|
|
172
|
+
# However, this makes the term "errors" reserved, so plugins
|
|
173
|
+
# cannot use their custom "errors" in the body.
|
|
174
|
+
# This must be rewritten.
|
|
175
|
+
def plan_errors_handling
|
|
176
|
+
reduce("errors"=> REDUCE_SUM)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|