droonga-engine 1.0.2 → 1.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +7 -0
- data/Rakefile +6 -2
- data/bin/droonga-engine +2 -2
- data/bin/{droonga-catalog-generate → droonga-engine-catalog-generate} +15 -3
- data/bin/droonga-engine-serf-event-handler +20 -0
- data/bin/droonga-engine-service +2 -2
- data/doc/text/news.md +21 -1
- data/droonga-engine.gemspec +5 -2
- data/lib/droonga/catalog/collection_volume.rb +12 -0
- data/lib/droonga/catalog/dataset.rb +25 -0
- data/lib/droonga/catalog/single_volume.rb +10 -0
- data/lib/droonga/catalog/slice.rb +4 -0
- data/lib/droonga/catalog/version1.rb +59 -48
- data/lib/droonga/catalog/version2.rb +10 -20
- data/lib/droonga/catalog/volume_collection.rb +27 -4
- data/lib/droonga/catalog_generator.rb +12 -5
- data/lib/droonga/catalog_observer.rb +17 -35
- data/lib/droonga/command/droonga_engine.rb +436 -0
- data/lib/droonga/command/droonga_engine_service.rb +273 -0
- data/lib/droonga/command/serf_event_handler.rb +85 -0
- data/lib/droonga/dispatcher.rb +8 -8
- data/lib/droonga/engine.rb +90 -26
- data/lib/droonga/engine/version.rb +1 -1
- data/lib/droonga/engine_state.rb +29 -3
- data/lib/droonga/internal_fluent_message_receiver.rb +100 -0
- data/lib/droonga/live_nodes_list_loader.rb +48 -0
- data/lib/droonga/live_nodes_list_observer.rb +72 -0
- data/lib/droonga/path.rb +47 -0
- data/lib/droonga/plugins/dump.rb +279 -38
- data/lib/droonga/plugins/groonga/select.rb +26 -14
- data/lib/droonga/plugins/search.rb +30 -2
- data/lib/droonga/plugins/search/distributed_search_planner.rb +28 -11
- data/lib/droonga/processor.rb +4 -0
- data/lib/droonga/searcher.rb +26 -0
- data/lib/droonga/serf.rb +119 -0
- data/lib/droonga/serf_downloader.rb +90 -0
- data/lib/droonga/server.rb +2 -2
- data/lib/droonga/service_control_protocol.rb +26 -0
- data/sample/cluster/catalog.json +1 -1
- data/test/command/config/default/catalog.json +2 -2
- data/test/command/config/version1/catalog.json +1 -1
- data/test/command/fixture/documents.jsons +18 -18
- data/test/command/fixture/event.jsons +4 -4
- data/test/command/fixture/user-table-array.jsons +4 -4
- data/test/command/fixture/user-table.jsons +5 -5
- data/test/command/suite/add/dimension/column.catalog.json +1 -1
- data/test/command/suite/add/dimension/column.test +4 -4
- data/test/command/suite/add/dimension/integer.catalog.json +1 -1
- data/test/command/suite/add/dimension/integer.test +4 -4
- data/test/command/suite/add/error/invalid-integer.test +1 -1
- data/test/command/suite/add/error/invalid-time.test +1 -1
- data/test/command/suite/add/error/missing-key.test +1 -1
- data/test/command/suite/add/error/missing-table.test +1 -1
- data/test/command/suite/add/error/unknown-column.test +1 -1
- data/test/command/suite/add/error/unknown-table.test +1 -1
- data/test/command/suite/add/minimum.test +1 -1
- data/test/command/suite/add/vector/short_text.catalog.json +26 -0
- data/test/command/suite/add/vector/short_text.expected +42 -0
- data/test/command/suite/add/vector/short_text.test +35 -0
- data/test/command/suite/add/with-values.test +1 -1
- data/test/command/suite/add/without-key.test +1 -1
- data/test/command/suite/dump/column/index.catalog.json +40 -0
- data/test/command/suite/dump/column/index.expected +195 -0
- data/test/command/suite/dump/column/index.test +5 -0
- data/test/command/suite/dump/column/scalar.catalog.json +19 -0
- data/test/command/suite/dump/column/scalar.expected +99 -0
- data/test/command/suite/dump/column/scalar.test +5 -0
- data/test/command/suite/dump/column/vector.catalog.json +22 -0
- data/test/command/suite/dump/column/vector.expected +108 -0
- data/test/command/suite/dump/column/vector.test +5 -0
- data/test/command/suite/dump/record/vector/reference.catalog.json +27 -0
- data/test/command/suite/dump/record/vector/reference.expected +213 -0
- data/test/command/suite/dump/record/vector/reference.test +21 -0
- data/test/command/suite/dump/table/array.catalog.json +13 -0
- data/test/command/suite/dump/table/array.expected +63 -0
- data/test/command/suite/dump/table/array.test +5 -0
- data/test/command/suite/dump/table/double_array_trie.catalog.json +14 -0
- data/test/command/suite/dump/table/double_array_trie.expected +66 -0
- data/test/command/suite/dump/table/double_array_trie.test +5 -0
- data/test/command/suite/dump/table/hash.catalog.json +14 -0
- data/test/command/suite/dump/table/hash.expected +66 -0
- data/test/command/suite/dump/table/hash.test +5 -0
- data/test/command/suite/dump/table/patricia_trie.catalog.json +14 -0
- data/test/command/suite/dump/table/patricia_trie.expected +66 -0
- data/test/command/suite/dump/table/patricia_trie.test +5 -0
- data/test/command/suite/groonga/column_create/scalar.test +2 -2
- data/test/command/suite/groonga/column_create/unknown-table.test +1 -1
- data/test/command/suite/groonga/column_create/vector.test +2 -2
- data/test/command/suite/groonga/column_list/success.test +3 -3
- data/test/command/suite/groonga/column_list/unknown-table.test +1 -1
- data/test/command/suite/groonga/column_remove/success.test +3 -3
- data/test/command/suite/groonga/column_remove/unknown-column.test +2 -2
- data/test/command/suite/groonga/column_remove/unknown-table.test +1 -1
- data/test/command/suite/groonga/column_rename/success.test +3 -3
- data/test/command/suite/groonga/column_rename/unknown-column.test +2 -2
- data/test/command/suite/groonga/column_rename/unknown-table.test +1 -1
- data/test/command/suite/groonga/delete/duplicated-identifiers.test +2 -2
- data/test/command/suite/groonga/delete/filter.test +2 -2
- data/test/command/suite/groonga/delete/invalid-filter.test +1 -1
- data/test/command/suite/groonga/delete/no-identifier.test +2 -2
- data/test/command/suite/groonga/delete/success.test +2 -2
- data/test/command/suite/groonga/delete/unknown-table.test +1 -1
- data/test/command/suite/groonga/select/minimum.expected +24 -1
- data/test/command/suite/groonga/select/minimum.test +1 -1
- data/test/command/suite/groonga/select/type/time.catalog.json +19 -0
- data/test/command/suite/groonga/select/type/time.expected +37 -0
- data/test/command/suite/groonga/select/type/time.test +35 -0
- data/test/command/suite/groonga/table_create/array.test +1 -1
- data/test/command/suite/groonga/table_create/hash.test +1 -1
- data/test/command/suite/groonga/table_list/success.test +2 -2
- data/test/command/suite/groonga/table_remove/success.test +1 -1
- data/test/command/suite/groonga/table_remove/unknown-table.test +1 -1
- data/test/command/suite/message/error/unknown-type.expected +1 -1
- data/test/command/suite/message/error/unknown-type.test +1 -1
- data/test/command/suite/search/adjusters/multiple.catalog.json +1 -1
- data/test/command/suite/search/adjusters/multiple.test +3 -3
- data/test/command/suite/search/adjusters/one.catalog.json +1 -1
- data/test/command/suite/search/adjusters/one.test +3 -3
- data/test/command/suite/search/attributes/array.expected +7 -0
- data/test/command/suite/search/attributes/array.test +1 -1
- data/test/command/suite/search/attributes/hash.expected +18 -0
- data/test/command/suite/search/attributes/hash.test +1 -1
- data/test/command/suite/search/complex.expected +12 -0
- data/test/command/suite/search/complex.test +1 -1
- data/test/command/suite/search/condition/nested.catalog.json +37 -0
- data/test/command/suite/search/condition/nested.expected +7 -0
- data/test/command/suite/search/condition/nested.test +103 -2
- data/test/command/suite/search/condition/query.catalog.json +37 -0
- data/test/command/suite/search/condition/query.expected +7 -0
- data/test/command/suite/search/condition/query.test +103 -2
- data/test/command/suite/search/condition/query/nonexistent_column.catalog.json +1 -1
- data/test/command/suite/search/condition/query/nonexistent_column.test +2 -2
- data/test/command/suite/search/condition/query/syntax_error.catalog.json +1 -1
- data/test/command/suite/search/condition/query/syntax_error.test +2 -2
- data/test/command/suite/search/condition/script.catalog.json +37 -0
- data/test/command/suite/search/condition/script.expected +7 -0
- data/test/command/suite/search/condition/script.test +103 -2
- data/test/command/suite/search/error/cyclic-source.test +1 -1
- data/test/command/suite/search/error/deeply-cyclic-source.test +1 -1
- data/test/command/suite/search/error/missing-source-parameter.test +1 -1
- data/test/command/suite/search/error/no-query.test +1 -1
- data/test/command/suite/search/error/unknown-source.test +1 -1
- data/test/command/suite/search/group/count.test +1 -1
- data/test/command/suite/search/group/limit.test +1 -1
- data/test/command/suite/search/group/string.catalog.json +41 -0
- data/test/command/suite/search/group/string.expected +18 -18
- data/test/command/suite/search/group/string.test +67 -22
- data/test/command/suite/search/group/subrecord/with-sort.catalog.json +1 -1
- data/test/command/suite/search/group/subrecord/with-sort.test +5 -5
- data/test/command/suite/search/multiple/chained.catalog.json +37 -0
- data/test/command/suite/search/multiple/chained.expected +14 -0
- data/test/command/suite/search/multiple/chained.test +103 -2
- data/test/command/suite/search/multiple/parallel.expected +14 -0
- data/test/command/suite/search/multiple/parallel.test +1 -1
- data/test/command/suite/search/output/attributes/invalid.catalog.json +1 -1
- data/test/command/suite/search/output/attributes/invalid.test +2 -2
- data/test/command/suite/search/output/attributes/star.catalog.json +23 -0
- data/test/command/suite/search/output/attributes/star.expected +27 -0
- data/test/command/suite/search/output/attributes/star.test +32 -0
- data/test/command/suite/search/range/only-output.expected +7 -0
- data/test/command/suite/search/range/only-output.test +1 -1
- data/test/command/suite/search/range/only-sort.expected +7 -0
- data/test/command/suite/search/range/only-sort.test +1 -1
- data/test/command/suite/search/range/sort-and-output.expected +7 -0
- data/test/command/suite/search/range/sort-and-output.test +1 -1
- data/test/command/suite/search/range/too-large-output-offset.expected +8 -0
- data/test/command/suite/search/range/too-large-output-offset.test +1 -1
- data/test/command/suite/search/range/too-large-sort-offset.expected +8 -0
- data/test/command/suite/search/range/too-large-sort-offset.test +1 -1
- data/test/command/suite/search/response/elapsed_time.catalog.json +1 -1
- data/test/command/suite/search/response/elapsed_time.test +2 -2
- data/test/command/suite/search/response/records/value/time.expected +12 -0
- data/test/command/suite/search/response/records/value/time.test +1 -1
- data/test/command/suite/search/simple.expected +12 -0
- data/test/command/suite/search/simple.test +1 -1
- data/test/command/suite/search/sort/default-offset-limit.expected +7 -0
- data/test/command/suite/search/sort/default-offset-limit.test +1 -1
- data/test/command/suite/search/sort/invisible-column.expected +7 -0
- data/test/command/suite/search/sort/invisible-column.test +1 -1
- data/test/unit/catalog/test_collection_volume.rb +16 -0
- data/test/unit/catalog/test_dataset.rb +36 -0
- data/test/unit/catalog/test_single_volume.rb +9 -0
- data/test/unit/catalog/test_slice.rb +11 -0
- data/test/unit/catalog/test_version1.rb +7 -12
- data/test/unit/catalog/test_version2.rb +7 -0
- data/test/unit/catalog/test_volume_collection.rb +28 -0
- data/test/unit/fixtures/catalog/version1.json +10 -3
- data/test/unit/fixtures/catalog/version2.json +2 -2
- data/test/unit/plugins/groonga/select/test_adapter_output.rb +8 -14
- data/test/unit/plugins/groonga/test_column_create.rb +5 -5
- data/test/unit/plugins/groonga/test_column_remove.rb +2 -2
- data/test/unit/plugins/groonga/test_column_rename.rb +2 -2
- data/test/unit/plugins/groonga/test_delete.rb +2 -2
- data/test/unit/plugins/groonga/test_table_create.rb +9 -9
- data/test/unit/plugins/groonga/test_table_remove.rb +1 -1
- data/test/unit/test_catalog_generator.rb +1 -1
- data/test/unit/test_schema_applier.rb +2 -2
- data/test/unit/test_watch_schema.rb +4 -4
- metadata +241 -72
- data/lib/droonga/engine/command/droonga_engine.rb +0 -441
|
@@ -26,8 +26,8 @@ module Droonga
|
|
|
26
26
|
@table = select_request["table"]
|
|
27
27
|
@result_name = @table + "_result"
|
|
28
28
|
|
|
29
|
-
output_columns = select_request["output_columns"] || ""
|
|
30
|
-
attributes = output_columns.split(
|
|
29
|
+
output_columns = select_request["output_columns"] || "_id, _key, *"
|
|
30
|
+
attributes = output_columns.split(/\s*,\s*/)
|
|
31
31
|
offset = (select_request["offset"] || "0").to_i
|
|
32
32
|
limit = (select_request["limit"] || "10").to_i
|
|
33
33
|
|
|
@@ -121,7 +121,7 @@ module Droonga
|
|
|
121
121
|
drilldown_keys = drilldown_keys.split(",")
|
|
122
122
|
|
|
123
123
|
sort_keys = (select_request["drilldown_sortby"] || "").split(",")
|
|
124
|
-
columns = (select_request["drilldown_output_columns"] || "").split(",")
|
|
124
|
+
columns = (select_request["drilldown_output_columns"] || "_key,_nsubrecs").split(",")
|
|
125
125
|
offset = (select_request["drilldown_offset"] || "0").to_i
|
|
126
126
|
limit = (select_request["drilldown_limit"] || "10").to_i
|
|
127
127
|
|
|
@@ -177,16 +177,18 @@ module Droonga
|
|
|
177
177
|
def convert_main_result(result)
|
|
178
178
|
status_code = 0
|
|
179
179
|
start_time = result["startTime"]
|
|
180
|
-
start_time_in_unix_time =
|
|
181
|
-
Time.parse(start_time).to_f
|
|
182
|
-
else
|
|
183
|
-
Time.now.to_f
|
|
184
|
-
end
|
|
180
|
+
start_time_in_unix_time = normalize_time(start_time).to_f
|
|
185
181
|
elapsed_time = result["elapsedTime"] || 0
|
|
186
182
|
@header = [status_code, start_time_in_unix_time, elapsed_time]
|
|
187
183
|
@body = convert_search_result(result)
|
|
188
184
|
end
|
|
189
185
|
|
|
186
|
+
def normalize_time(time)
|
|
187
|
+
time ||= Time.now
|
|
188
|
+
time = Time.parse(time) if time.is_a?(String)
|
|
189
|
+
time
|
|
190
|
+
end
|
|
191
|
+
|
|
190
192
|
def convert_drilldown_result(key, result)
|
|
191
193
|
@drilldown_results << convert_search_result(result)
|
|
192
194
|
end
|
|
@@ -194,12 +196,8 @@ module Droonga
|
|
|
194
196
|
def convert_search_result(result)
|
|
195
197
|
count = result["count"]
|
|
196
198
|
attributes = convert_attributes(result["attributes"])
|
|
197
|
-
records = result["records"]
|
|
198
|
-
|
|
199
|
-
[[count], attributes]
|
|
200
|
-
else
|
|
201
|
-
[[count], attributes, records]
|
|
202
|
-
end
|
|
199
|
+
records = convert_records(attributes, result["records"] || [])
|
|
200
|
+
[[count], attributes, *records]
|
|
203
201
|
end
|
|
204
202
|
|
|
205
203
|
def convert_attributes(attributes)
|
|
@@ -210,6 +208,20 @@ module Droonga
|
|
|
210
208
|
[name, type]
|
|
211
209
|
end
|
|
212
210
|
end
|
|
211
|
+
|
|
212
|
+
def convert_records(attributes, records)
|
|
213
|
+
records.collect do |record|
|
|
214
|
+
record.collect.each_with_index do |value, i|
|
|
215
|
+
name, type = attributes[i]
|
|
216
|
+
case type
|
|
217
|
+
when "Time"
|
|
218
|
+
normalize_time(value).to_f
|
|
219
|
+
else
|
|
220
|
+
value
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
213
225
|
end
|
|
214
226
|
|
|
215
227
|
class Adapter < Droonga::Adapter
|
|
@@ -76,6 +76,28 @@ module Droonga
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
+
attributes_mapper = elements["attributes"]
|
|
80
|
+
if attributes_mapper and value["attributes"]
|
|
81
|
+
attributes = value["attributes"]
|
|
82
|
+
output_attributes = []
|
|
83
|
+
attributes_mapper["names"].each do |name|
|
|
84
|
+
if name == "*"
|
|
85
|
+
attributes.each do |attribute|
|
|
86
|
+
next if attribute["name"].start_with?("_")
|
|
87
|
+
output_attributes << attribute
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
attributes.each do |attribute|
|
|
91
|
+
if attribute["name"] == name
|
|
92
|
+
output_attributes << attribute
|
|
93
|
+
break
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
value["attributes"] = output_attributes
|
|
99
|
+
end
|
|
100
|
+
|
|
79
101
|
records_mapper = elements["records"]
|
|
80
102
|
if records_mapper and value["records"]
|
|
81
103
|
if records_mapper["no_output"]
|
|
@@ -99,8 +121,14 @@ module Droonga
|
|
|
99
121
|
complex_item
|
|
100
122
|
end
|
|
101
123
|
else
|
|
102
|
-
|
|
103
|
-
|
|
124
|
+
# FIXME: Compare with "attributes" value from "search" not
|
|
125
|
+
# gather parameter like the following.
|
|
126
|
+
if attributes.include?("*")
|
|
127
|
+
items
|
|
128
|
+
else
|
|
129
|
+
items.collect do |item|
|
|
130
|
+
item[0...attributes.size]
|
|
131
|
+
end
|
|
104
132
|
end
|
|
105
133
|
end
|
|
106
134
|
end
|
|
@@ -77,18 +77,9 @@ module Droonga
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def transform_query(input_name, query)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Skip reducing phase for a result with no output.
|
|
83
|
-
if output.nil? or
|
|
84
|
-
output["elements"].nil? or
|
|
85
|
-
(!output["elements"].include?("count") and
|
|
86
|
-
!output["elements"].include?("records"))
|
|
87
|
-
return
|
|
88
|
-
end
|
|
80
|
+
return unless need_reduce?(query)
|
|
89
81
|
|
|
90
82
|
transformer = QueryTransformer.new(query)
|
|
91
|
-
|
|
92
83
|
elements = transformer.mappers
|
|
93
84
|
mapper = {}
|
|
94
85
|
mapper["elements"] = elements unless elements.empty?
|
|
@@ -96,6 +87,19 @@ module Droonga
|
|
|
96
87
|
:gather => mapper })
|
|
97
88
|
end
|
|
98
89
|
|
|
90
|
+
def need_reduce?(query)
|
|
91
|
+
output = query["output"]
|
|
92
|
+
return false if output.nil?
|
|
93
|
+
|
|
94
|
+
output_elements = output["elements"]
|
|
95
|
+
return false if output_elements.nil?
|
|
96
|
+
|
|
97
|
+
need_reduce_elements = ["count", "attributes", "records"]
|
|
98
|
+
output_elements.any? do |element|
|
|
99
|
+
need_reduce_elements.include?(element)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
99
103
|
class QueryTransformer
|
|
100
104
|
attr_reader :reducers, :mappers
|
|
101
105
|
|
|
@@ -123,6 +127,7 @@ module Droonga
|
|
|
123
127
|
calculate_offset_and_limit!
|
|
124
128
|
build_count_mapper_and_reducer!
|
|
125
129
|
build_elapsed_time_mapper_and_reducer!
|
|
130
|
+
build_attributes_mapper_and_reducer!
|
|
126
131
|
build_records_mapper_and_reducer!
|
|
127
132
|
end
|
|
128
133
|
|
|
@@ -265,6 +270,18 @@ module Droonga
|
|
|
265
270
|
}
|
|
266
271
|
end
|
|
267
272
|
|
|
273
|
+
def build_attributes_mapper_and_reducer!
|
|
274
|
+
return unless @output["elements"].include?("attributes")
|
|
275
|
+
|
|
276
|
+
@reducers["attributes"] = {
|
|
277
|
+
"type" => "or",
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@mappers["attributes"] = {
|
|
281
|
+
"names" => output_attribute_names,
|
|
282
|
+
}
|
|
283
|
+
end
|
|
284
|
+
|
|
268
285
|
def build_records_mapper_and_reducer!
|
|
269
286
|
# Skip reducing phase for a result with no record output.
|
|
270
287
|
return if !@output["elements"].include?("records") || @records_limit.zero?
|
|
@@ -325,7 +342,7 @@ module Droonga
|
|
|
325
342
|
}
|
|
326
343
|
when Hash
|
|
327
344
|
attribute["label"] = key
|
|
328
|
-
|
|
345
|
+
attribute
|
|
329
346
|
end
|
|
330
347
|
end
|
|
331
348
|
else
|
data/lib/droonga/processor.rb
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
require "droonga/loggable"
|
|
17
17
|
require "droonga/handler_runner"
|
|
18
|
+
require "fileutils"
|
|
18
19
|
|
|
19
20
|
module Droonga
|
|
20
21
|
class Processor
|
|
@@ -46,6 +47,9 @@ module Droonga
|
|
|
46
47
|
synchronous = @handler_runner.prefer_synchronous?(type)
|
|
47
48
|
if @n_workers.zero? or synchronous
|
|
48
49
|
@handler_runner.process(message)
|
|
50
|
+
#XXX Workaround to restart system by any schema change.
|
|
51
|
+
# This should be done more smartly...
|
|
52
|
+
FileUtils.touch(Path.catalog.to_s) if synchronous
|
|
49
53
|
else
|
|
50
54
|
@job_pusher.push(message)
|
|
51
55
|
end
|
data/lib/droonga/searcher.rb
CHANGED
|
@@ -663,6 +663,7 @@ module Droonga
|
|
|
663
663
|
|
|
664
664
|
def output_target_attributes
|
|
665
665
|
attributes = @request.output["attributes"]
|
|
666
|
+
attributes = expand_attributes(attributes)
|
|
666
667
|
normalize_target_attributes(attributes)
|
|
667
668
|
end
|
|
668
669
|
|
|
@@ -675,6 +676,31 @@ module Droonga
|
|
|
675
676
|
formatter.format(output_target_attributes, @result.records, output_limit, output_offset)
|
|
676
677
|
end
|
|
677
678
|
|
|
679
|
+
def expand_attributes(attributes, domain = @result.records)
|
|
680
|
+
expanded_attributes = []
|
|
681
|
+
attributes.each do |attribute|
|
|
682
|
+
if attribute.is_a?(String)
|
|
683
|
+
source = attribute
|
|
684
|
+
else
|
|
685
|
+
source = attribute["source"]
|
|
686
|
+
end
|
|
687
|
+
if source == "*"
|
|
688
|
+
real_table = domain
|
|
689
|
+
loop do
|
|
690
|
+
next_domain = real_table.domain
|
|
691
|
+
break unless next_domain.is_a?(Groonga::Table)
|
|
692
|
+
real_table = next_domain
|
|
693
|
+
end
|
|
694
|
+
real_table.columns.each do |column|
|
|
695
|
+
expanded_attributes << column.local_name
|
|
696
|
+
end
|
|
697
|
+
else
|
|
698
|
+
expanded_attributes << attribute
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
expanded_attributes
|
|
702
|
+
end
|
|
703
|
+
|
|
678
704
|
def normalize_target_attributes(attributes, domain = @result.records)
|
|
679
705
|
attributes.collect do |attribute|
|
|
680
706
|
if attribute.is_a?(String)
|
data/lib/droonga/serf.rb
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
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/path"
|
|
17
|
+
require "droonga/loggable"
|
|
18
|
+
require "droonga/catalog_loader"
|
|
19
|
+
require "droonga/serf_downloader"
|
|
20
|
+
|
|
21
|
+
module Droonga
|
|
22
|
+
class Serf
|
|
23
|
+
class << self
|
|
24
|
+
def path
|
|
25
|
+
Droonga::Path.base + "serf"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
include Loggable
|
|
30
|
+
|
|
31
|
+
def initialize(loop, name)
|
|
32
|
+
@loop = loop
|
|
33
|
+
@name = name
|
|
34
|
+
@pid = nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def start
|
|
38
|
+
logger.trace("start: start")
|
|
39
|
+
ensure_serf
|
|
40
|
+
ENV["SERF"] = @serf
|
|
41
|
+
ENV["SERF_RPC_ADDRESS"] = rpc_address
|
|
42
|
+
retry_joins = []
|
|
43
|
+
detect_other_hosts.each do |other_host|
|
|
44
|
+
retry_joins.push("-retry-join", other_host)
|
|
45
|
+
end
|
|
46
|
+
@pid = run("agent",
|
|
47
|
+
"-node", @name,
|
|
48
|
+
"-bind", extract_host(@name),
|
|
49
|
+
"-event-handler", "droonga-engine-serf-event-handler",
|
|
50
|
+
*retry_joins)
|
|
51
|
+
logger.trace("start: done")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def running?
|
|
55
|
+
not @pid.nil?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def shutdown
|
|
59
|
+
logger.trace("shutdown: start")
|
|
60
|
+
Process.waitpid(run("leave"))
|
|
61
|
+
Process.waitpid(@pid)
|
|
62
|
+
@pid = nil
|
|
63
|
+
logger.trace("shutdown: done")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def restart
|
|
67
|
+
shutdown
|
|
68
|
+
start
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
def ensure_serf
|
|
73
|
+
@serf = find_system_serf
|
|
74
|
+
return if @serf
|
|
75
|
+
|
|
76
|
+
serf_path = self.class.path
|
|
77
|
+
@serf = serf_path.to_s
|
|
78
|
+
return if serf_path.executable?
|
|
79
|
+
downloader = SerfDownloader.new(serf_path)
|
|
80
|
+
downloader.download
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def find_system_serf
|
|
84
|
+
paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
|
|
85
|
+
paths.each do |path|
|
|
86
|
+
serf = File.join(path, "serf")
|
|
87
|
+
return serf if File.executable?(serf)
|
|
88
|
+
end
|
|
89
|
+
nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def run(command, *options)
|
|
93
|
+
spawn(@serf, command, "-rpc-addr", rpc_address, *options)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def extract_host(node_name)
|
|
97
|
+
node_name.split(":").first
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def rpc_address
|
|
101
|
+
"#{extract_host(@name)}:7373"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def detect_other_hosts
|
|
105
|
+
loader = CatalogLoader.new(Path.catalog.to_s)
|
|
106
|
+
catalog = loader.load
|
|
107
|
+
other_nodes = catalog.all_nodes.reject do |node|
|
|
108
|
+
node == @name
|
|
109
|
+
end
|
|
110
|
+
other_nodes.collect do |node|
|
|
111
|
+
extract_host(node)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def log_tag
|
|
116
|
+
"serf"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
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 "stringio"
|
|
17
|
+
require "tmpdir"
|
|
18
|
+
require "fileutils"
|
|
19
|
+
|
|
20
|
+
require "faraday"
|
|
21
|
+
require "faraday_middleware"
|
|
22
|
+
require "archive/zip"
|
|
23
|
+
|
|
24
|
+
require "droonga/loggable"
|
|
25
|
+
|
|
26
|
+
module Droonga
|
|
27
|
+
class SerfDownloader
|
|
28
|
+
include Loggable
|
|
29
|
+
|
|
30
|
+
def initialize(output_path)
|
|
31
|
+
@output_path = output_path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def download
|
|
35
|
+
detect_platform
|
|
36
|
+
version = "0.6.0"
|
|
37
|
+
url_base = "https://dl.bintray.com/mitchellh/serf"
|
|
38
|
+
base_name = "#{version}_#{@os}_#{@architecture}.zip"
|
|
39
|
+
connection = Faraday.new(url_base) do |builder|
|
|
40
|
+
builder.response(:follow_redirects)
|
|
41
|
+
builder.adapter(Faraday.default_adapter)
|
|
42
|
+
end
|
|
43
|
+
response = connection.get(base_name)
|
|
44
|
+
absolete_output_path = @output_path.expand_path
|
|
45
|
+
Dir.mktmpdir do |dir|
|
|
46
|
+
Archive::Zip.extract(StringIO.new(response.body),
|
|
47
|
+
dir,
|
|
48
|
+
:directories => false)
|
|
49
|
+
FileUtils.mv("#{dir}/serf", absolete_output_path.to_s)
|
|
50
|
+
FileUtils.chmod(0755, absolete_output_path.to_s)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
def detect_platform
|
|
56
|
+
detect_os
|
|
57
|
+
detect_architecture
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def detect_os
|
|
61
|
+
case RUBY_PLATFORM
|
|
62
|
+
when /linux/
|
|
63
|
+
@os = "linux"
|
|
64
|
+
when /freebsd/
|
|
65
|
+
@os = "freebsd"
|
|
66
|
+
when /darwin/
|
|
67
|
+
@os = "darwin"
|
|
68
|
+
when /mswin|mingw/
|
|
69
|
+
@os = "windows"
|
|
70
|
+
else
|
|
71
|
+
raise "Unsupported OS: #{RUBY_PLATFORM}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def detect_architecture
|
|
76
|
+
case RUBY_PLATFORM
|
|
77
|
+
when /x86_64|x64/
|
|
78
|
+
@architecture = "amd64"
|
|
79
|
+
when /i\d86/
|
|
80
|
+
@architecture = "i386"
|
|
81
|
+
else
|
|
82
|
+
raise "Unsupported architecture: #{RUBY_PLATFORM}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def log_tag
|
|
87
|
+
"serf-downloader"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|