fluent-plugin-droonga 0.7.0 → 0.8.0

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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -4
  3. data/benchmark/watch/benchmark-notify.rb +2 -2
  4. data/benchmark/watch/benchmark-scan.rb +3 -0
  5. data/benchmark/watch/fluentd.conf +0 -1
  6. data/fluent-plugin-droonga.gemspec +2 -3
  7. data/lib/droonga/catalog.rb +10 -124
  8. data/lib/droonga/catalog/base.rb +140 -0
  9. data/lib/droonga/catalog/version1.rb +23 -0
  10. data/lib/droonga/catalog_loader.rb +33 -0
  11. data/lib/droonga/collector.rb +2 -71
  12. data/lib/droonga/collector_plugin.rb +2 -34
  13. data/lib/droonga/dispatcher.rb +141 -196
  14. data/lib/droonga/distribution_planner.rb +76 -0
  15. data/lib/droonga/distributor.rb +5 -7
  16. data/lib/droonga/distributor_plugin.rb +23 -15
  17. data/lib/droonga/engine.rb +2 -2
  18. data/lib/droonga/event_loop.rb +46 -0
  19. data/lib/droonga/farm.rb +9 -5
  20. data/lib/droonga/fluent_message_sender.rb +84 -0
  21. data/lib/droonga/forwarder.rb +43 -53
  22. data/lib/droonga/handler.rb +20 -68
  23. data/lib/droonga/handler_message.rb +61 -0
  24. data/lib/droonga/handler_messenger.rb +92 -0
  25. data/lib/droonga/handler_plugin.rb +10 -12
  26. data/lib/droonga/input_adapter.rb +52 -0
  27. data/lib/droonga/{adapter.rb → input_adapter_plugin.rb} +7 -13
  28. data/lib/droonga/input_message.rb +11 -11
  29. data/lib/droonga/logger.rb +4 -3
  30. data/lib/droonga/message_pack_packer.rb +62 -0
  31. data/lib/droonga/message_processing_error.rb +54 -0
  32. data/lib/droonga/message_pusher.rb +60 -0
  33. data/lib/droonga/message_receiver.rb +61 -0
  34. data/lib/droonga/output_adapter.rb +53 -0
  35. data/lib/droonga/{adapter_plugin.rb → output_adapter_plugin.rb} +3 -21
  36. data/lib/droonga/output_message.rb +37 -0
  37. data/lib/droonga/partition.rb +27 -5
  38. data/lib/droonga/pluggable.rb +9 -4
  39. data/lib/droonga/plugin.rb +12 -3
  40. data/lib/droonga/plugin/collector/basic.rb +91 -18
  41. data/lib/droonga/plugin/distributor/crud.rb +9 -9
  42. data/lib/droonga/plugin/distributor/distributed_search_planner.rb +401 -0
  43. data/lib/droonga/plugin/distributor/groonga.rb +5 -5
  44. data/lib/droonga/plugin/distributor/search.rb +4 -246
  45. data/lib/droonga/plugin/distributor/watch.rb +11 -6
  46. data/lib/droonga/plugin/handler/add.rb +69 -7
  47. data/lib/droonga/plugin/handler/groonga.rb +6 -6
  48. data/lib/droonga/plugin/handler/search.rb +5 -3
  49. data/lib/droonga/plugin/handler/watch.rb +19 -13
  50. data/lib/droonga/plugin/{adapter → input_adapter}/groonga.rb +5 -11
  51. data/lib/droonga/plugin/{adapter → input_adapter}/groonga/select.rb +2 -36
  52. data/lib/droonga/plugin/output_adapter/groonga.rb +30 -0
  53. data/lib/droonga/plugin/output_adapter/groonga/select.rb +54 -0
  54. data/lib/droonga/plugin_loader.rb +2 -2
  55. data/lib/droonga/processor.rb +21 -23
  56. data/lib/droonga/replier.rb +40 -0
  57. data/lib/droonga/searcher.rb +298 -174
  58. data/lib/droonga/server.rb +0 -67
  59. data/lib/droonga/session.rb +85 -0
  60. data/lib/droonga/test.rb +21 -0
  61. data/lib/droonga/test/stub_distributor.rb +31 -0
  62. data/lib/droonga/test/stub_handler.rb +37 -0
  63. data/lib/droonga/test/stub_handler_message.rb +35 -0
  64. data/lib/droonga/test/stub_handler_messenger.rb +34 -0
  65. data/lib/droonga/time_formatter.rb +37 -0
  66. data/lib/droonga/watcher.rb +1 -0
  67. data/lib/droonga/worker.rb +16 -19
  68. data/lib/fluent/plugin/out_droonga.rb +9 -9
  69. data/lib/groonga_command_converter.rb +5 -5
  70. data/sample/cluster/catalog.json +1 -1
  71. data/test/command/config/default/catalog.json +19 -1
  72. data/test/command/fixture/event.jsons +41 -0
  73. data/test/command/fixture/user-table.jsons +9 -0
  74. data/test/command/run-test.rb +2 -2
  75. data/test/command/suite/add/error/invalid-integer.expected +20 -0
  76. data/test/command/suite/add/error/invalid-integer.test +12 -0
  77. data/test/command/suite/add/error/invalid-time.expected +20 -0
  78. data/test/command/suite/add/error/invalid-time.test +12 -0
  79. data/test/command/suite/add/error/missing-key.expected +13 -0
  80. data/test/command/suite/add/error/missing-key.test +16 -0
  81. data/test/command/suite/add/error/missing-table.expected +13 -0
  82. data/test/command/suite/add/error/missing-table.test +16 -0
  83. data/test/command/suite/add/error/unknown-column.expected +20 -0
  84. data/test/command/suite/add/error/unknown-column.test +12 -0
  85. data/test/command/suite/add/error/unknown-table.expected +13 -0
  86. data/test/command/suite/add/error/unknown-table.test +17 -0
  87. data/test/command/suite/add/minimum.expected +1 -3
  88. data/test/command/suite/add/with-values.expected +1 -3
  89. data/test/command/suite/add/without-key.expected +1 -3
  90. data/test/command/suite/message/error/missing-dataset.expected +13 -0
  91. data/test/command/suite/message/error/missing-dataset.test +5 -0
  92. data/test/command/suite/message/error/unknown-command.expected +13 -0
  93. data/test/command/suite/message/error/unknown-command.test +6 -0
  94. data/test/command/suite/message/error/unknown-dataset.expected +13 -0
  95. data/test/command/suite/message/error/unknown-dataset.test +6 -0
  96. data/test/command/suite/search/{array-attribute-label.expected → attributes/array.expected} +0 -0
  97. data/test/command/suite/search/{array-attribute-label.test → attributes/array.test} +0 -0
  98. data/test/command/suite/search/{hash-attribute-label.expected → attributes/hash.expected} +0 -0
  99. data/test/command/suite/search/{hash-attribute-label.test → attributes/hash.test} +0 -0
  100. data/test/command/suite/search/{condition-nested.expected → condition/nested.expected} +0 -0
  101. data/test/command/suite/search/{condition-nested.test → condition/nested.test} +0 -0
  102. data/test/command/suite/search/{condition-query.expected → condition/query.expected} +0 -0
  103. data/test/command/suite/search/{condition-query.test → condition/query.test} +0 -0
  104. data/test/command/suite/search/{condition-script.expected → condition/script.expected} +0 -0
  105. data/test/command/suite/search/{condition-script.test → condition/script.test} +0 -0
  106. data/test/command/suite/search/error/cyclic-source.expected +18 -0
  107. data/test/command/suite/search/error/cyclic-source.test +12 -0
  108. data/test/command/suite/search/error/deeply-cyclic-source.expected +21 -0
  109. data/test/command/suite/search/error/deeply-cyclic-source.test +15 -0
  110. data/test/command/suite/search/error/missing-source-parameter.expected +17 -0
  111. data/test/command/suite/search/error/missing-source-parameter.test +11 -0
  112. data/test/command/suite/search/error/unknown-source.expected +18 -0
  113. data/test/command/suite/search/error/unknown-source.test +12 -0
  114. data/test/command/suite/search/{minimum.expected → group/count.expected} +2 -1
  115. data/test/command/suite/search/{minimum.test → group/count.test} +5 -3
  116. data/test/command/suite/search/group/limit.expected +19 -0
  117. data/test/command/suite/search/group/limit.test +20 -0
  118. data/test/command/suite/search/group/string.expected +36 -0
  119. data/test/command/suite/search/group/string.test +44 -0
  120. data/test/command/suite/search/{chained-queries.expected → multiple/chained.expected} +0 -0
  121. data/test/command/suite/search/{chained-queries.test → multiple/chained.test} +0 -0
  122. data/test/command/suite/search/{multiple-queries.expected → multiple/parallel.expected} +0 -0
  123. data/test/command/suite/search/{multiple-queries.test → multiple/parallel.test} +0 -0
  124. data/test/command/suite/search/{output-range.expected → range/only-output.expected} +0 -0
  125. data/test/command/suite/search/{output-range.test → range/only-output.test} +0 -0
  126. data/test/command/suite/search/{sort-range.expected → range/only-sort.expected} +0 -0
  127. data/test/command/suite/search/{sort-range.test → range/only-sort.test} +0 -0
  128. data/test/command/suite/search/{sort-and-output-range.expected → range/sort-and-output.expected} +0 -0
  129. data/test/command/suite/search/{sort-and-output-range.test → range/sort-and-output.test} +0 -0
  130. data/test/command/suite/search/range/too-large-output-offset.expected +16 -0
  131. data/test/command/suite/search/range/too-large-output-offset.test +25 -0
  132. data/test/command/suite/search/range/too-large-sort-offset.expected +16 -0
  133. data/test/command/suite/search/range/too-large-sort-offset.test +28 -0
  134. data/test/command/suite/search/response/records/value/time.expected +24 -0
  135. data/test/command/suite/search/response/records/value/time.test +24 -0
  136. data/test/command/suite/search/sort/default-offset-limit.expected +43 -0
  137. data/test/command/suite/search/sort/default-offset-limit.test +26 -0
  138. data/test/command/suite/search/{sort-with-invisible-column.expected → sort/invisible-column.expected} +0 -0
  139. data/test/command/suite/search/{sort-with-invisible-column.test → sort/invisible-column.test} +0 -0
  140. data/test/command/suite/watch/subscribe.expected +12 -0
  141. data/test/command/suite/watch/subscribe.test +9 -0
  142. data/test/command/suite/watch/unsubscribe.expected +12 -0
  143. data/test/command/suite/watch/unsubscribe.test +9 -0
  144. data/test/unit/{test_catalog.rb → catalog/test_version1.rb} +12 -4
  145. data/test/unit/fixtures/{catalog.json → catalog/version1.json} +0 -0
  146. data/test/unit/helper.rb +2 -0
  147. data/test/unit/plugin/collector/test_basic.rb +289 -33
  148. data/test/unit/plugin/distributor/test_search.rb +176 -861
  149. data/test/unit/plugin/distributor/test_search_planner.rb +1102 -0
  150. data/test/unit/plugin/handler/groonga/test_column_create.rb +17 -13
  151. data/test/unit/plugin/handler/groonga/test_table_create.rb +10 -10
  152. data/test/unit/plugin/handler/test_add.rb +74 -11
  153. data/test/unit/plugin/handler/test_groonga.rb +15 -1
  154. data/test/unit/plugin/handler/test_search.rb +33 -17
  155. data/test/unit/plugin/handler/test_watch.rb +43 -27
  156. data/test/unit/run-test.rb +2 -0
  157. data/test/unit/test_message_pack_packer.rb +51 -0
  158. data/test/unit/test_time_formatter.rb +29 -0
  159. metadata +208 -110
  160. data/lib/droonga/job_queue.rb +0 -87
  161. data/lib/droonga/job_queue_schema.rb +0 -65
  162. data/test/unit/test_adapter.rb +0 -51
  163. data/test/unit/test_job_queue_schema.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16568393cd233c1f8a54d3bce227e328b6e1b293
4
- data.tar.gz: 48f158466e6f15a069f3f5c8f92add90f740114c
3
+ metadata.gz: f03ac63db8e9b4b082da89c26c8bbf7caea45e76
4
+ data.tar.gz: 20b6f9a80dc7f198003fb4932b483f85c6a1d976
5
5
  SHA512:
6
- metadata.gz: aa5bedb70c57916313b56a3639f8567f3a3efc3a43ba9b8bd68fae5d547e91c481ab71865fa1864d9b9cd425f54488acdc60c8cc53d652754b6552ccbe6e1f40
7
- data.tar.gz: 3a3c6fa0f130808929a5225ea02b5a89bf5b5b850bc2a227cf9a35d54702bb2b63857d136672bc6849455e2de350f7de95c12bdb5dac4313a67785881ad63ef4
6
+ metadata.gz: 06af50c670901878e0d42f72182cd9848194eb5b14f04428fbe788098b7a7b715cb57e94241742620a0bf89fa7cbea03f7e8ea825a1e4816c3aedf59e2a19e33
7
+ data.tar.gz: 69cc3370c3401f24bf1749ef71f7fe2b45cf1de4b7c06c8d5171c3650e296d75ac8576851375ddefd3856c137fa5836a414e2dafef21c03e908b0296d1e5c464
data/.gitignore CHANGED
@@ -1,7 +1,4 @@
1
1
  /Gemfile.lock
2
- /test/command/.bundle/
3
- /test/command/Gemfile.lock
4
- /test/command/bin/
5
- /test/command/vendor/
2
+ /test/command/tmp
6
3
  /doc/
7
4
  /.yardoc/
@@ -66,14 +66,14 @@ class NotifyBenchmark
66
66
  message = DroongaBenchmark::MessageCreator.envelope_to_subscribe(WATCHING_KEYWORD)
67
67
  message["body"]["subscriber"] += " #{@n_subscribers + index}"
68
68
  message["body"]["route"] = @route
69
- @client.connection.send_receive(message)
69
+ @client.connection.send(message, :response => :one)
70
70
  end
71
71
  @n_subscribers += n_subscribers
72
72
  end
73
73
 
74
74
  def do_feed(target)
75
75
  message = DroongaBenchmark::MessageCreator.envelope_to_feed(target)
76
- @client.connection.send(message)
76
+ @client.connection.send(message, :response => :none)
77
77
  end
78
78
  end
79
79
 
@@ -19,12 +19,15 @@ require "benchmark"
19
19
  require "fileutils"
20
20
  require "optparse"
21
21
  require "csv"
22
+ require "fluent/log"
22
23
 
23
24
  require "groonga"
24
25
 
25
26
  require "droonga/watcher"
26
27
  require File.expand_path(File.join(__FILE__, "..", "..", "utils.rb"))
27
28
 
29
+ $log = Fluent::Log.new
30
+
28
31
  class ScanBenchmark
29
32
  attr_reader :n_keywords
30
33
 
@@ -5,7 +5,6 @@
5
5
  <match droonga.message>
6
6
  name localhost:23003/droonga
7
7
  type droonga
8
- proxy true
9
8
  </match>
10
9
  <match output.message>
11
10
  type stdout
@@ -17,7 +17,7 @@
17
17
 
18
18
  Gem::Specification.new do |gem|
19
19
  gem.name = "fluent-plugin-droonga"
20
- gem.version = "0.7.0"
20
+ gem.version = "0.8.0"
21
21
  gem.authors = ["Droonga Project"]
22
22
  gem.email = ["droonga@groonga.org"]
23
23
  gem.description = "Droonga(distributed Groonga) plugin for Fluent event collector"
@@ -28,9 +28,8 @@ Gem::Specification.new do |gem|
28
28
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
29
29
  gem.require_paths = ["lib"]
30
30
  gem.add_dependency "fluentd"
31
- gem.add_dependency "rroonga", ">= 3.0.3"
31
+ gem.add_dependency "rroonga", ">= 3.1.0"
32
32
  gem.add_dependency "groonga-command-parser"
33
- gem.add_dependency "fluent-logger"
34
33
  gem.add_dependency "serverengine"
35
34
  gem.add_development_dependency "rake"
36
35
  gem.add_development_dependency "bundler"
@@ -15,139 +15,25 @@
15
15
  # License along with this library; if not, write to the Free Software
16
16
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
 
18
- require "digest/sha1"
19
- require "zlib"
18
+ require "droonga/catalog_loader"
20
19
 
21
20
  module Droonga
22
21
  class << self
23
22
  def catalog
24
- @catalog ||= Catalog.new
23
+ @catalog ||= Catalog.load
25
24
  end
26
25
  end
27
26
 
28
- class Catalog
29
- CATALOG_FILE_PATH = "catalog.json"
27
+ module Catalog
28
+ PATH = "catalog.json"
30
29
 
31
- attr_reader :path
32
-
33
- def initialize(path=nil)
34
- @path = path || default_path
35
-
36
- open(@path) do |file|
37
- @catalog = JSON.parse(file.read)
38
- end
39
- @catalog["datasets"].each do |name, dataset|
40
- number_of_partitions = dataset["number_of_partitions"]
41
- next if number_of_partitions < 2
42
- total_weight = dataset["ring"].reduce do |a, b|
43
- a[1]["weight"] + b[1]["weight"]
44
- end
45
- continuum = []
46
- dataset["ring"].each do |key, value|
47
- points = number_of_partitions * 160 * value["weight"] / total_weight
48
- points.times do |point|
49
- hash = Digest::SHA1.hexdigest("#{key}:#{point}")
50
- continuum << [hash[0..7].to_i(16), key]
51
- end
52
- end
53
- dataset["continuum"] = continuum.sort do |a, b| a[0] - b[0]; end
54
- end
55
- @options = @catalog["options"] || {}
56
- end
57
-
58
- def base_path
59
- @base_path ||= File.dirname(@path)
60
- end
61
-
62
- def option(name)
63
- @options[name]
64
- end
65
-
66
- def get_partitions(name)
67
- device = @catalog["farms"][name]["device"]
68
- pattern = Regexp.new("^#{name}\.")
69
- results = {}
70
- @catalog["datasets"].each do |key, dataset|
71
- workers = dataset["workers"]
72
- plugins = dataset["plugins"]
73
- dataset["ring"].each do |key, part|
74
- part["partitions"].each do |range, partitions|
75
- partitions.each do |partition|
76
- if partition =~ pattern
77
- path = File.join([device, $POSTMATCH, "db"])
78
- path = File.expand_path(path, base_path)
79
- options = {
80
- :database => path,
81
- :n_workers => workers,
82
- :handlers => plugins
83
- }
84
- results[partition] = options
85
- end
86
- end
87
- end
88
- end
30
+ class << self
31
+ def load(path=nil)
32
+ path = ENV["DROONGA_CATALOG"] || PATH
33
+ path = File.expand_path(path)
34
+ loader = CatalogLoader.new(path)
35
+ loader.load
89
36
  end
90
- return results
91
- end
92
-
93
- def get_routes(name, args)
94
- routes = []
95
- dataset = dataset(name)
96
- return routes unless dataset
97
- case args["type"]
98
- when "broadcast"
99
- dataset["ring"].each do |key, partition|
100
- select_range_and_replicas(partition, args, routes)
101
- end
102
- when "scatter"
103
- name = get_partition(dataset, args["key"])
104
- partition = dataset["ring"][name]
105
- select_range_and_replicas(partition, args, routes)
106
- end
107
- return routes
108
- end
109
-
110
- def get_partition(dataset, key)
111
- continuum = dataset["continuum"]
112
- return dataset["ring"].keys[0] unless continuum
113
- hash = Zlib.crc32(key)
114
- min = 0
115
- max = continuum.size - 1
116
- while (min < max) do
117
- index = (min + max) / 2
118
- value, key = continuum[index]
119
- return key if value == hash
120
- if value > hash
121
- max = index
122
- else
123
- min = index + 1
124
- end
125
- end
126
- return continuum[max][1]
127
- end
128
-
129
- def dataset(name)
130
- @catalog["datasets"][name]
131
- end
132
-
133
- def select_range_and_replicas(partition, args, routes)
134
- date_range = args["date_range"] || 0..-1
135
- partition["partitions"].sort[date_range].each do |time, replicas|
136
- case args["replica"]
137
- when "top"
138
- routes << replicas[0]
139
- when "random"
140
- routes << replicas[rand(replicas.size)]
141
- when "all"
142
- routes.concat(replicas)
143
- end
144
- end
145
- end
146
-
147
- private
148
- def default_path
149
- path = ENV["DROONGA_CATALOG"] || Catalog::CATALOG_FILE_PATH
150
- File.expand_path(path)
151
37
  end
152
38
  end
153
39
  end
@@ -0,0 +1,140 @@
1
+ # Copyright (C) 2013 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 "digest/sha1"
17
+ require "zlib"
18
+ require "droonga/message_processing_error"
19
+
20
+ module Droonga
21
+ module Catalog
22
+ class Base
23
+ class UnknownDataset < NotFound
24
+ def initialize(dataset)
25
+ super("The dataset #{dataset.inspect} does not exist.")
26
+ end
27
+ end
28
+
29
+ attr_reader :base_path
30
+ def initialize(data, base_path)
31
+ @data = data
32
+ @base_path = base_path
33
+
34
+ @data["datasets"].each do |name, dataset|
35
+ number_of_partitions = dataset["number_of_partitions"]
36
+ next if number_of_partitions < 2
37
+ total_weight = dataset["ring"].reduce do |a, b|
38
+ a[1]["weight"] + b[1]["weight"]
39
+ end
40
+ continuum = []
41
+ dataset["ring"].each do |key, value|
42
+ points = number_of_partitions * 160 * value["weight"] / total_weight
43
+ points.times do |point|
44
+ hash = Digest::SHA1.hexdigest("#{key}:#{point}")
45
+ continuum << [hash[0..7].to_i(16), key]
46
+ end
47
+ end
48
+ dataset["continuum"] = continuum.sort do |a, b| a[0] - b[0]; end
49
+ end
50
+ @options = @data["options"] || {}
51
+ end
52
+
53
+ def option(name)
54
+ @options[name]
55
+ end
56
+
57
+ def get_partitions(name)
58
+ device = @data["farms"][name]["device"]
59
+ pattern = Regexp.new("^#{name}\.")
60
+ results = {}
61
+ @data["datasets"].each do |key, dataset|
62
+ workers = dataset["workers"]
63
+ plugins = dataset["plugins"]
64
+ dataset["ring"].each do |key, part|
65
+ part["partitions"].each do |range, partitions|
66
+ partitions.each do |partition|
67
+ if partition =~ pattern
68
+ path = File.join([device, $POSTMATCH, "db"])
69
+ path = File.expand_path(path, base_path)
70
+ options = {
71
+ :database => path,
72
+ :n_workers => workers,
73
+ :handlers => plugins
74
+ }
75
+ results[partition] = options
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ return results
82
+ end
83
+
84
+ def get_routes(name, args)
85
+ routes = []
86
+ dataset = dataset(name)
87
+ case args["type"]
88
+ when "broadcast"
89
+ dataset["ring"].each do |key, partition|
90
+ select_range_and_replicas(partition, args, routes)
91
+ end
92
+ when "scatter"
93
+ name = get_partition(dataset, args["key"])
94
+ partition = dataset["ring"][name]
95
+ select_range_and_replicas(partition, args, routes)
96
+ end
97
+ return routes
98
+ end
99
+
100
+ def get_partition(dataset, key)
101
+ continuum = dataset["continuum"]
102
+ return dataset["ring"].keys[0] unless continuum
103
+ hash = Zlib.crc32(key)
104
+ min = 0
105
+ max = continuum.size - 1
106
+ while (min < max) do
107
+ index = (min + max) / 2
108
+ value, key = continuum[index]
109
+ return key if value == hash
110
+ if value > hash
111
+ max = index
112
+ else
113
+ min = index + 1
114
+ end
115
+ end
116
+ return continuum[max][1]
117
+ end
118
+
119
+ def dataset(name)
120
+ dataset = @data["datasets"][name]
121
+ raise UnknownDataset.new(name) unless dataset
122
+ dataset
123
+ end
124
+
125
+ def select_range_and_replicas(partition, args, routes)
126
+ date_range = args["date_range"] || 0..-1
127
+ partition["partitions"].sort[date_range].each do |time, replicas|
128
+ case args["replica"]
129
+ when "top"
130
+ routes << replicas[0]
131
+ when "random"
132
+ routes << replicas[rand(replicas.size)]
133
+ when "all"
134
+ routes.concat(replicas)
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,23 @@
1
+ # Copyright (C) 2013 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/catalog/base"
17
+
18
+ module Droonga
19
+ module Catalog
20
+ class Version1 < Base
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright (C) 2013 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 "json"
17
+
18
+ require "droonga/catalog/version1"
19
+
20
+ module Droonga
21
+ class CatalogLoader
22
+ def initialize(path)
23
+ @path = path
24
+ end
25
+
26
+ def load
27
+ data = File.open(@path) do |file|
28
+ JSON.parse(file.read)
29
+ end
30
+ Catalog::Version1.new(data, File.dirname(@path))
31
+ end
32
+ end
33
+ end
@@ -22,82 +22,13 @@ module Droonga
22
22
  class Collector
23
23
  include Pluggable
24
24
 
25
- def initialize(id, dispatcher, components, tasks, inputs)
26
- @id = id
27
- @dispatcher = dispatcher
28
- @components = components
29
- @tasks = tasks
30
- @n_dones = 0
31
- @inputs = inputs
25
+ def initialize
32
26
  load_plugins(["basic"]) # TODO: make customizable
33
27
  end
34
28
 
35
- def handle(name, value)
36
- tasks = @inputs[name]
37
- unless tasks
38
- #TODO: result arrived before its query
39
- return
40
- end
41
- tasks.each do |task|
42
- task["n_of_inputs"] += 1 if name
43
- component = task["component"]
44
- type = component["type"]
45
- command = component["command"] || ("collector_" + type)
46
- n_of_expects = component["n_of_expects"]
47
- synchronous = nil
48
- if command
49
- synchronous = true unless n_of_expects.zero?
50
- # TODO: check if asynchronous execution is available.
51
- message = {
52
- "task"=>task,
53
- "name"=>name,
54
- "value"=>value
55
- }
56
- unless synchronous
57
- descendants = {}
58
- component["descendants"].each do |name, indices|
59
- descendants[name] = indices.collect do |index|
60
- @components[index]["routes"].map do |route|
61
- @dispatcher.farm_path(route)
62
- end
63
- end
64
- end
65
- message["descendants"] = descendants
66
- message["id"] = @id
67
- end
68
- if @id == task["route"]
69
- process(command, message)
70
- else
71
- @dispatcher.deliver(@id, task["route"], message, command, synchronous)
72
- end
73
- end
74
- return if task["n_of_inputs"] < n_of_expects
75
- #the task is done
76
- if synchronous
77
- result = task["values"]
78
- post = component["post"]
79
- @dispatcher.post(result, post) if post
80
- component["descendants"].each do |name, indices|
81
- message = {
82
- "id" => @id,
83
- "input" => name,
84
- "value" => result[name]
85
- }
86
- indices.each do |index|
87
- @components[index]["routes"].each do |route|
88
- @dispatcher.dispatch(message, route)
89
- end
90
- end
91
- end
92
- end
93
- @n_dones += 1
94
- @dispatcher.collectors.delete(@id) if @n_dones == @tasks.size
95
- end
96
- end
97
-
98
29
  private
99
30
  def instantiate_plugin(name)
100
- CollectorPlugin.repository.instantiate(name, @dispatcher)
31
+ CollectorPlugin.repository.instantiate(name)
101
32
  end
102
33
 
103
34
  def log_tag