fluent-plugin-droonga 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Gemfile +1 -1
- data/fluent-plugin-droonga.gemspec +1 -1
- data/lib/droonga/catalog/collection_volume.rb +97 -0
- data/lib/droonga/catalog/dataset.rb +28 -1
- data/lib/droonga/catalog/errors.rb +28 -9
- data/lib/droonga/catalog/schema.rb +23 -2
- data/lib/droonga/catalog/single_volume.rb +28 -0
- data/lib/droonga/catalog/slice.rb +43 -0
- data/lib/droonga/catalog/version1.rb +3 -3
- data/lib/droonga/catalog/version2.rb +17 -81
- 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_observer.rb +7 -19
- data/lib/droonga/collectors.rb +1 -1
- data/lib/droonga/collectors/{add.rb → or.rb} +1 -1
- data/lib/droonga/dispatcher.rb +24 -18
- data/lib/droonga/distributed_command_planner.rb +7 -11
- data/lib/droonga/distributor.rb +29 -17
- data/lib/droonga/event_loop.rb +2 -11
- data/lib/droonga/fluent_message_sender.rb +51 -5
- data/lib/droonga/handler_runner.rb +1 -1
- data/lib/droonga/job_protocol.rb +20 -0
- data/lib/droonga/job_pusher.rb +178 -0
- data/lib/droonga/{message_receiver.rb → job_receiver.rb} +13 -6
- data/lib/droonga/message_matcher.rb +18 -15
- data/lib/droonga/planner.rb +2 -3
- data/lib/droonga/plugins/crud.rb +1 -1
- data/lib/droonga/plugins/groonga/column_create.rb +4 -1
- data/lib/droonga/plugins/groonga/table_create.rb +1 -1
- data/lib/droonga/plugins/groonga/table_remove.rb +1 -1
- data/lib/droonga/plugins/search/distributed_search_planner.rb +9 -0
- data/lib/droonga/processor.rb +3 -3
- data/lib/droonga/reducer.rb +15 -12
- data/lib/droonga/searcher.rb +49 -4
- data/lib/droonga/server.rb +2 -0
- data/lib/droonga/single_step.rb +22 -7
- data/lib/droonga/slice.rb +7 -7
- data/lib/droonga/step_runner.rb +3 -2
- data/lib/droonga/worker.rb +10 -8
- data/test/command/suite/add/dimension/column.catalog.json +27 -0
- data/test/command/suite/add/dimension/column.expected +57 -0
- data/test/command/suite/add/dimension/column.test +51 -0
- data/test/command/suite/search/adjusters/multiple.catalog.json +38 -0
- data/test/command/suite/search/adjusters/multiple.expected +23 -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 +23 -0
- data/test/command/suite/search/adjusters/one.test +66 -0
- data/test/command/suite/search/attributes/array.test +0 -2
- data/test/command/suite/search/attributes/hash.test +0 -2
- data/test/command/suite/search/complex.test +0 -2
- data/test/command/suite/search/condition/nested.test +0 -2
- data/test/command/suite/search/condition/query.test +0 -2
- data/test/command/suite/search/condition/script.test +0 -2
- data/test/command/suite/search/group/string.test +0 -4
- data/test/command/suite/search/group/subrecord/with-sort.catalog.json +33 -0
- data/test/command/suite/search/group/subrecord/with-sort.expected +34 -0
- data/test/command/suite/search/group/subrecord/with-sort.test +81 -0
- data/test/command/suite/search/multiple/chained.test +0 -4
- data/test/command/suite/search/multiple/parallel.test +0 -4
- data/test/command/suite/search/range/only-output.test +0 -2
- data/test/command/suite/search/range/only-sort.test +0 -2
- data/test/command/suite/search/range/sort-and-output.test +0 -2
- data/test/command/suite/search/range/too-large-output-offset.test +0 -2
- data/test/command/suite/search/range/too-large-sort-offset.test +0 -2
- data/test/command/suite/search/response/elapsed_time.catalog.json +13 -0
- data/test/command/suite/search/response/elapsed_time.expected +15 -0
- data/test/command/suite/search/response/elapsed_time.test +26 -0
- data/test/command/suite/search/response/records/value/time.test +0 -2
- data/test/command/suite/search/simple.test +0 -2
- data/test/command/suite/search/sort/default-offset-limit.test +0 -2
- data/test/command/suite/search/sort/invisible-column.test +0 -2
- data/test/unit/catalog/test_collection_volume.rb +103 -0
- data/test/unit/catalog/test_dataset.rb +69 -8
- data/test/unit/catalog/test_schema.rb +63 -23
- 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 +1 -1
- data/test/unit/catalog/test_version2.rb +1 -32
- data/test/unit/catalog/test_version2_validator.rb +66 -0
- data/test/unit/catalog/test_volume_collection.rb +50 -0
- data/test/unit/plugins/groonga/test_column_create.rb +4 -1
- data/test/unit/plugins/groonga/test_table_create.rb +1 -1
- data/test/unit/test_message_matcher.rb +15 -15
- data/test/unit/test_watch_schema.rb +1 -1
- metadata +107 -94
- checksums.yaml +0 -7
- data/lib/droonga/message_pusher.rb +0 -64
@@ -69,6 +69,9 @@ module Droonga
|
|
69
69
|
options[:type] = :scalar
|
70
70
|
elsif @command.column_vector?
|
71
71
|
options[:type] = :vector
|
72
|
+
if @command.with_weight?
|
73
|
+
options[:with_weight] = true
|
74
|
+
end
|
72
75
|
end
|
73
76
|
options
|
74
77
|
end
|
@@ -120,7 +123,7 @@ module Droonga
|
|
120
123
|
step.name = "column_create"
|
121
124
|
step.write = true
|
122
125
|
step.handler = Handler
|
123
|
-
step.collector = Collectors::
|
126
|
+
step.collector = Collectors::Or
|
124
127
|
end
|
125
128
|
end
|
126
129
|
end
|
@@ -122,6 +122,7 @@ module Droonga
|
|
122
122
|
|
123
123
|
calculate_offset_and_limit!
|
124
124
|
build_count_mapper_and_reducer!
|
125
|
+
build_elapsed_time_mapper_and_reducer!
|
125
126
|
build_records_mapper_and_reducer!
|
126
127
|
end
|
127
128
|
|
@@ -256,6 +257,14 @@ module Droonga
|
|
256
257
|
end
|
257
258
|
end
|
258
259
|
|
260
|
+
def build_elapsed_time_mapper_and_reducer!
|
261
|
+
return unless @output["elements"].include?("elapsedTime")
|
262
|
+
|
263
|
+
@reducers["elapsedTime"] = {
|
264
|
+
"type" => "sum",
|
265
|
+
}
|
266
|
+
end
|
267
|
+
|
259
268
|
def build_records_mapper_and_reducer!
|
260
269
|
# Skip reducing phase for a result with no record output.
|
261
270
|
return if !@output["elements"].include?("records") || @records_limit.zero?
|
data/lib/droonga/processor.rb
CHANGED
@@ -20,9 +20,9 @@ module Droonga
|
|
20
20
|
class Processor
|
21
21
|
include Loggable
|
22
22
|
|
23
|
-
def initialize(loop,
|
23
|
+
def initialize(loop, job_pusher, options={})
|
24
24
|
@loop = loop
|
25
|
-
@
|
25
|
+
@job_pusher = job_pusher
|
26
26
|
@options = options
|
27
27
|
@n_workers = @options[:n_workers] || 0
|
28
28
|
end
|
@@ -47,7 +47,7 @@ module Droonga
|
|
47
47
|
if @n_workers.zero? or synchronous
|
48
48
|
@handler_runner.process(message)
|
49
49
|
else
|
50
|
-
@
|
50
|
+
@job_pusher.push(message)
|
51
51
|
end
|
52
52
|
else
|
53
53
|
logger.trace("process: ignore #{type}")
|
data/lib/droonga/reducer.rb
CHANGED
@@ -134,25 +134,28 @@ module Droonga
|
|
134
134
|
base_items, unified_items = unified_items, base_items
|
135
135
|
end
|
136
136
|
|
137
|
-
|
137
|
+
unified_key_map = {}
|
138
|
+
unified_items.each do |unified_item|
|
139
|
+
unified_key_map[unified_item[key_column_index]] = unified_item
|
140
|
+
end
|
138
141
|
|
142
|
+
unified = false
|
139
143
|
base_items.reject! do |base_item|
|
140
144
|
key = base_item[key_column_index]
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
end
|
147
|
-
rest_unified_items -= [unified_item]
|
148
|
-
true
|
149
|
-
else
|
150
|
-
false
|
145
|
+
unified_item = unified_key_map[key]
|
146
|
+
if unified_item
|
147
|
+
base_item.each_with_index do |value, column_index|
|
148
|
+
next if column_index == key_column_index
|
149
|
+
unified_item[column_index] += value
|
151
150
|
end
|
151
|
+
unified = true
|
152
|
+
true
|
153
|
+
else
|
154
|
+
false
|
152
155
|
end
|
153
156
|
end
|
154
157
|
|
155
|
-
|
158
|
+
if unified
|
156
159
|
unified_items.sort! do |a, b|
|
157
160
|
if compare(a, b, options[:operators])
|
158
161
|
-1
|
data/lib/droonga/searcher.rb
CHANGED
@@ -61,14 +61,26 @@ module Droonga
|
|
61
61
|
def search(queries)
|
62
62
|
outputs = nil
|
63
63
|
logger.trace("search: start", :queries => queries)
|
64
|
-
|
65
|
-
|
64
|
+
# TODO: THIS IS JUST A WORKAROUND! We should remove it ASAP!
|
65
|
+
disable_gc do
|
66
|
+
@context.push_memory_pool do
|
67
|
+
outputs = process_queries(queries)
|
68
|
+
end
|
66
69
|
end
|
67
70
|
logger.trace("search: done")
|
68
71
|
return outputs
|
69
72
|
end
|
70
73
|
|
71
74
|
private
|
75
|
+
def disable_gc
|
76
|
+
GC.disable
|
77
|
+
begin
|
78
|
+
yield
|
79
|
+
ensure
|
80
|
+
GC.enable
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
72
84
|
def process_queries(queries)
|
73
85
|
logger.trace("process_queries: start")
|
74
86
|
if queries.nil? or queries.empty?
|
@@ -302,7 +314,12 @@ module Droonga
|
|
302
314
|
@records = @request.source
|
303
315
|
|
304
316
|
condition = @request.query["condition"]
|
305
|
-
|
317
|
+
if condition
|
318
|
+
apply_condition!(condition)
|
319
|
+
|
320
|
+
adjusters = @request.query["adjusters"]
|
321
|
+
apply_adjusters!(adjusters) if adjusters
|
322
|
+
end
|
306
323
|
|
307
324
|
group_by = @request.query["groupBy"]
|
308
325
|
apply_group_by!(group_by) if group_by
|
@@ -328,6 +345,29 @@ module Droonga
|
|
328
345
|
@result.condition = expression
|
329
346
|
end
|
330
347
|
|
348
|
+
def apply_adjusters!(adjusters)
|
349
|
+
logger.trace("search_query: adjusters: start")
|
350
|
+
adjusters.each do |adjuster|
|
351
|
+
column_name = adjuster["column"]
|
352
|
+
value = adjuster["value"]
|
353
|
+
factor = adjuster["factor"] || 1
|
354
|
+
logger.trace("search_query: adjusters: adjuster: start",
|
355
|
+
:column_name => column_name,
|
356
|
+
:value => value,
|
357
|
+
:factor => factor)
|
358
|
+
column = @request.source.column(column_name)
|
359
|
+
index, = column.indexes(:match)
|
360
|
+
# TODO: add index.nil? check
|
361
|
+
# TODO: add value.nil? check
|
362
|
+
index.search(value,
|
363
|
+
:result => @records,
|
364
|
+
:operator => :adjust,
|
365
|
+
:weight => factor)
|
366
|
+
logger.trace("search_query: adjusters: adjuster: done")
|
367
|
+
end
|
368
|
+
logger.trace("search_query: adjusters: done")
|
369
|
+
end
|
370
|
+
|
331
371
|
def apply_group_by!(group_by)
|
332
372
|
logger.trace("search_query: group: start",
|
333
373
|
:by => group_by)
|
@@ -449,7 +489,12 @@ module Droonga
|
|
449
489
|
module RecordsFormattable
|
450
490
|
def record_value(record, attribute)
|
451
491
|
if attribute[:source] == "_subrecs"
|
452
|
-
record.
|
492
|
+
if record.table.is_a?(Groonga::Array)
|
493
|
+
target_record = record.value
|
494
|
+
else
|
495
|
+
target_record = record
|
496
|
+
end
|
497
|
+
target_record.sub_records.collect do |sub_record|
|
453
498
|
sub_attributes = attribute[:attributes]
|
454
499
|
format_record(sub_attributes, sub_record)
|
455
500
|
end
|
data/lib/droonga/server.rb
CHANGED
data/lib/droonga/single_step.rb
CHANGED
@@ -18,7 +18,8 @@ require "droonga/collectors"
|
|
18
18
|
|
19
19
|
module Droonga
|
20
20
|
class SingleStep
|
21
|
-
def initialize(definition)
|
21
|
+
def initialize(dataset, definition)
|
22
|
+
@dataset = dataset
|
22
23
|
@definition = definition
|
23
24
|
end
|
24
25
|
|
@@ -40,14 +41,28 @@ module Droonga
|
|
40
41
|
reduce_key => collector_class.operator,
|
41
42
|
}
|
42
43
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
|
45
|
+
body = message["body"]
|
46
|
+
fact_input = find_fact_input(@definition.inputs, @dataset.fact, body)
|
47
|
+
if fact_input
|
48
|
+
record = body[fact_input[:filter]]
|
49
|
+
planner.send(:scatter, message, record, options)
|
46
50
|
else
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
planner.send(:broadcast, message, options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_fact_input(inputs, fact, body)
|
56
|
+
inputs.each do |key, input|
|
57
|
+
if input[:type] == :table
|
58
|
+
# for backward compatibility. We can remove the following code
|
59
|
+
# when all our catalog.json specify "fact" parameter.
|
60
|
+
return input if fact.nil?
|
61
|
+
|
62
|
+
return input if body[key] == fact
|
63
|
+
end
|
50
64
|
end
|
65
|
+
nil
|
51
66
|
end
|
52
67
|
end
|
53
68
|
end
|
data/lib/droonga/slice.rb
CHANGED
@@ -19,7 +19,7 @@ require "droonga/loggable"
|
|
19
19
|
require "droonga/server"
|
20
20
|
require "droonga/worker"
|
21
21
|
require "droonga/event_loop"
|
22
|
-
require "droonga/
|
22
|
+
require "droonga/job_pusher"
|
23
23
|
require "droonga/processor"
|
24
24
|
|
25
25
|
module Droonga
|
@@ -30,23 +30,22 @@ module Droonga
|
|
30
30
|
@options = options
|
31
31
|
@n_workers = @options[:n_workers] || 0
|
32
32
|
@loop = loop
|
33
|
-
@
|
34
|
-
@processor = Processor.new(@loop, @
|
33
|
+
@job_pusher = JobPusher.new(@loop, @options[:database])
|
34
|
+
@processor = Processor.new(@loop, @job_pusher, @options)
|
35
35
|
@supervisor = nil
|
36
36
|
end
|
37
37
|
|
38
38
|
def start
|
39
39
|
ensure_database
|
40
40
|
@processor.start
|
41
|
-
|
42
|
-
@message_pusher.start(base_path)
|
41
|
+
@job_pusher.start
|
43
42
|
start_supervisor if @n_workers > 0
|
44
43
|
end
|
45
44
|
|
46
45
|
def shutdown
|
47
46
|
logger.trace("shutdown: start")
|
48
47
|
shutdown_supervisor if @supervisor
|
49
|
-
@
|
48
|
+
@job_pusher.shutdown
|
50
49
|
@processor.shutdown
|
51
50
|
logger.trace("shutdown: done")
|
52
51
|
end
|
@@ -84,7 +83,8 @@ module Droonga
|
|
84
83
|
:log_level => logger.level,
|
85
84
|
:server_process_name => "Server[#{@options[:database]}] #$0",
|
86
85
|
:worker_process_name => "Worker[#{@options[:database]}] #$0",
|
87
|
-
:
|
86
|
+
:job_receive_socket_path => @job_pusher.socket_path,
|
87
|
+
:job_pusher => @job_pusher,
|
88
88
|
}
|
89
89
|
@options.merge(force_options)
|
90
90
|
end
|
data/lib/droonga/step_runner.rb
CHANGED
@@ -21,7 +21,8 @@ module Droonga
|
|
21
21
|
class StepRunner
|
22
22
|
include Loggable
|
23
23
|
|
24
|
-
def initialize(plugins)
|
24
|
+
def initialize(dataset, plugins)
|
25
|
+
@dataset = dataset
|
25
26
|
@definitions = {}
|
26
27
|
plugins.each do |name|
|
27
28
|
plugin = Plugin.registry[name]
|
@@ -43,7 +44,7 @@ module Droonga
|
|
43
44
|
if definition.nil?
|
44
45
|
raise UnsupportedMessageError.new(:planner, message)
|
45
46
|
end
|
46
|
-
step = SingleStep.new(definition)
|
47
|
+
step = SingleStep.new(@dataset, definition)
|
47
48
|
plan = step.plan(message)
|
48
49
|
logger.trace("plan: done",
|
49
50
|
:dataset => message["dataset"],
|
data/lib/droonga/worker.rb
CHANGED
@@ -15,16 +15,17 @@
|
|
15
15
|
|
16
16
|
require "droonga/event_loop"
|
17
17
|
require "droonga/handler_runner"
|
18
|
-
require "droonga/
|
18
|
+
require "droonga/job_receiver"
|
19
19
|
|
20
20
|
module Droonga
|
21
21
|
module Worker
|
22
22
|
def initialize
|
23
|
-
@
|
23
|
+
@raw_loop = Coolio::Loop.new
|
24
|
+
@loop = EventLoop.new(@raw_loop)
|
24
25
|
@handler_runner = HandlerRunner.new(@loop,
|
25
26
|
config.merge(:dispatcher => nil))
|
26
|
-
|
27
|
-
@
|
27
|
+
receive_socket_path = config[:job_receive_socket_path]
|
28
|
+
@job_receiver = JobReceiver.new(@loop, receive_socket_path) do |message|
|
28
29
|
process(message)
|
29
30
|
end
|
30
31
|
end
|
@@ -32,16 +33,17 @@ module Droonga
|
|
32
33
|
def run
|
33
34
|
Droonga.logger.trace("#{log_tag}: run: start")
|
34
35
|
@handler_runner.start
|
35
|
-
@
|
36
|
-
@
|
36
|
+
@job_receiver.start
|
37
|
+
@raw_loop.run
|
37
38
|
@handler_runner.shutdown
|
38
39
|
Droonga.logger.trace("#{log_tag}: run: done")
|
39
40
|
end
|
40
41
|
|
41
42
|
def stop
|
42
43
|
Droonga.logger.trace("#{log_tag}: stop: start")
|
43
|
-
@
|
44
|
-
@
|
44
|
+
@job_receiver.shutdown
|
45
|
+
@raw_loop.stop
|
46
|
+
@loop.break_current_loop
|
45
47
|
Droonga.logger.trace("#{log_tag}: stop: done")
|
46
48
|
end
|
47
49
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"datasets": {
|
3
|
+
"Droonga": {
|
4
|
+
"schema": {
|
5
|
+
"Products": {
|
6
|
+
"type": "Hash",
|
7
|
+
"keyType": "ShortText",
|
8
|
+
"columns": {
|
9
|
+
"category": {
|
10
|
+
"type": "Scalar",
|
11
|
+
"valueType": "ShortText"
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
},
|
16
|
+
"replicas": [
|
17
|
+
{
|
18
|
+
"dimension": "category"
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"dimension": "category"
|
22
|
+
}
|
23
|
+
]
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
[
|
2
|
+
"droonga.message",
|
3
|
+
0,
|
4
|
+
{
|
5
|
+
"inReplyTo": "request-id",
|
6
|
+
"statusCode": 200,
|
7
|
+
"type": "add.result",
|
8
|
+
"body": true
|
9
|
+
}
|
10
|
+
]
|
11
|
+
[
|
12
|
+
"droonga.message",
|
13
|
+
0,
|
14
|
+
{
|
15
|
+
"inReplyTo": "request-id",
|
16
|
+
"statusCode": 200,
|
17
|
+
"type": "add.result",
|
18
|
+
"body": true
|
19
|
+
}
|
20
|
+
]
|
21
|
+
[
|
22
|
+
"droonga.message",
|
23
|
+
0,
|
24
|
+
{
|
25
|
+
"inReplyTo": "request-id",
|
26
|
+
"statusCode": 200,
|
27
|
+
"type": "add.result",
|
28
|
+
"body": true
|
29
|
+
}
|
30
|
+
]
|
31
|
+
[
|
32
|
+
"droonga.message",
|
33
|
+
0,
|
34
|
+
{
|
35
|
+
"inReplyTo": "request-id",
|
36
|
+
"statusCode": 200,
|
37
|
+
"type": "search.result",
|
38
|
+
"body": {
|
39
|
+
"products": {
|
40
|
+
"records": [
|
41
|
+
[
|
42
|
+
"Groonga",
|
43
|
+
"groonga"
|
44
|
+
],
|
45
|
+
[
|
46
|
+
"Rroonga",
|
47
|
+
"groonga"
|
48
|
+
],
|
49
|
+
[
|
50
|
+
"Ruby",
|
51
|
+
"ruby"
|
52
|
+
]
|
53
|
+
]
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
]
|