fluent-plugin-droonga 0.0.2

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 (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +40 -0
  5. data/LICENSE.txt +14 -0
  6. data/README.md +18 -0
  7. data/Rakefile +25 -0
  8. data/benchmark/benchmark.rb +123 -0
  9. data/benchmark/utils.rb +243 -0
  10. data/benchmark/watch/benchmark-notify.rb +143 -0
  11. data/benchmark/watch/benchmark-notify.sh +19 -0
  12. data/benchmark/watch/benchmark-publish.rb +120 -0
  13. data/benchmark/watch/benchmark-scan.rb +210 -0
  14. data/benchmark/watch/catalog.json +32 -0
  15. data/benchmark/watch/fluentd.conf +12 -0
  16. data/bin/grn2jsons +85 -0
  17. data/fluent-plugin-droonga.gemspec +41 -0
  18. data/lib/droonga/adapter.rb +156 -0
  19. data/lib/droonga/catalog.rb +153 -0
  20. data/lib/droonga/command_mapper.rb +45 -0
  21. data/lib/droonga/engine.rb +83 -0
  22. data/lib/droonga/executor.rb +289 -0
  23. data/lib/droonga/handler.rb +140 -0
  24. data/lib/droonga/handler_plugin.rb +35 -0
  25. data/lib/droonga/job_queue.rb +83 -0
  26. data/lib/droonga/job_queue_schema.rb +65 -0
  27. data/lib/droonga/logger.rb +34 -0
  28. data/lib/droonga/plugin.rb +41 -0
  29. data/lib/droonga/plugin/adapter/groonga/select.rb +88 -0
  30. data/lib/droonga/plugin/adapter_groonga.rb +40 -0
  31. data/lib/droonga/plugin/handler/groonga/column_create.rb +103 -0
  32. data/lib/droonga/plugin/handler/groonga/table_create.rb +100 -0
  33. data/lib/droonga/plugin/handler_add.rb +44 -0
  34. data/lib/droonga/plugin/handler_forward.rb +70 -0
  35. data/lib/droonga/plugin/handler_groonga.rb +52 -0
  36. data/lib/droonga/plugin/handler_proxy.rb +82 -0
  37. data/lib/droonga/plugin/handler_search.rb +33 -0
  38. data/lib/droonga/plugin/handler_watch.rb +102 -0
  39. data/lib/droonga/proxy.rb +371 -0
  40. data/lib/droonga/searcher.rb +415 -0
  41. data/lib/droonga/server.rb +112 -0
  42. data/lib/droonga/sweeper.rb +42 -0
  43. data/lib/droonga/watch_schema.rb +88 -0
  44. data/lib/droonga/watcher.rb +256 -0
  45. data/lib/droonga/worker.rb +51 -0
  46. data/lib/fluent/plugin/out_droonga.rb +56 -0
  47. data/lib/groonga_command_converter.rb +137 -0
  48. data/sample/cluster/catalog.json +43 -0
  49. data/sample/cluster/fluentd.conf +12 -0
  50. data/sample/fluentd.conf +8 -0
  51. data/test/fixtures/catalog.json +43 -0
  52. data/test/fixtures/document.grn +23 -0
  53. data/test/helper.rb +24 -0
  54. data/test/helper/fixture.rb +28 -0
  55. data/test/helper/sandbox.rb +73 -0
  56. data/test/helper/stub_worker.rb +27 -0
  57. data/test/helper/watch_helper.rb +35 -0
  58. data/test/plugin/adapter/groonga/test_select.rb +176 -0
  59. data/test/plugin/handler/groonga/test_column_create.rb +127 -0
  60. data/test/plugin/handler/groonga/test_table_create.rb +140 -0
  61. data/test/plugin/handler/test_handler_add.rb +135 -0
  62. data/test/plugin/handler/test_handler_groonga.rb +64 -0
  63. data/test/plugin/handler/test_handler_search.rb +512 -0
  64. data/test/plugin/handler/test_handler_watch.rb +168 -0
  65. data/test/run-test.rb +55 -0
  66. data/test/test_adapter.rb +48 -0
  67. data/test/test_catalog.rb +59 -0
  68. data/test/test_command_mapper.rb +44 -0
  69. data/test/test_groonga_command_converter.rb +242 -0
  70. data/test/test_handler.rb +53 -0
  71. data/test/test_job_queue_schema.rb +45 -0
  72. data/test/test_output.rb +99 -0
  73. data/test/test_sweeper.rb +95 -0
  74. data/test/test_watch_schema.rb +57 -0
  75. data/test/test_watcher.rb +336 -0
  76. data/test/test_worker.rb +144 -0
  77. metadata +299 -0
@@ -0,0 +1,100 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "groonga"
19
+ require "groonga/command/table-create"
20
+
21
+ module Droonga
22
+ class GroongaHandler
23
+ class TableCreate
24
+ def initialize(context)
25
+ @context = context
26
+ end
27
+
28
+ def header(return_code, error_message="")
29
+ elapsed_time = Time.now.to_f - @start_time
30
+ header = [return_code, @start_time, elapsed_time]
31
+ header.push(error_message) unless error_message.empty?
32
+ header
33
+ end
34
+
35
+ def execute(request)
36
+ @start_time = Time.now.to_f
37
+
38
+ command_class = Groonga::Command.find("table_create")
39
+ @command = command_class.new("table_create", request)
40
+
41
+ name = @command["name"]
42
+ return [header(Status::INVALID_ARGUMENT, "Should not create anonymous table"), false] unless name
43
+
44
+ options = parse_command
45
+ Groonga::Schema.define(:context => @context) do |schema|
46
+ schema.create_table(name, options)
47
+ end
48
+ [header(Status::SUCCESS), true]
49
+ end
50
+
51
+ private
52
+ def parse_command
53
+ options = {}
54
+ parse_flags(options)
55
+ parse_key_type(options)
56
+ parse_value_type(options)
57
+ parse_default_tokenizer(options)
58
+ parse_normalizer(options)
59
+ options
60
+ end
61
+
62
+ def parse_flags(options)
63
+ options[:type] = :hash
64
+ if @command.table_no_key?
65
+ options[:type] = :array
66
+ elsif @command.table_hash_key?
67
+ options[:type] = :hash
68
+ elsif @command.table_pat_key?
69
+ options[:type] = :patricia_trie
70
+ elsif @command.table_dat_key?
71
+ options[:type] = :double_array_trie
72
+ end
73
+ if @command.key_with_sis? and @command.table_pat_key?
74
+ options[:key_with_sis] = true
75
+ end
76
+ options
77
+ end
78
+
79
+ def parse_key_type(options)
80
+ options[:key_type] = @command["key_type"] if @command["key_type"]
81
+ options
82
+ end
83
+
84
+ def parse_value_type(options)
85
+ options[:value_type] = @command["value_type"] if @command["value_type"]
86
+ options
87
+ end
88
+
89
+ def parse_default_tokenizer(options)
90
+ options[:default_tokenizer] = @command["default_tokenizer"] if @command["default_tokenizer"]
91
+ options
92
+ end
93
+
94
+ def parse_normalizer(options)
95
+ options[:normalizer] = @command["normalizer"] if @command["normalizer"]
96
+ options
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "groonga"
19
+
20
+ require "droonga/handler"
21
+
22
+ module Droonga
23
+ class AddHandler < Droonga::Handler
24
+ Droonga::HandlerPlugin.register("add", self)
25
+
26
+ command :add
27
+ def add(request)
28
+ outputs = process(request)
29
+ emit(outputs)
30
+ end
31
+
32
+ private
33
+ def process(request)
34
+ table = @context[request["table"]]
35
+ return [false] unless table
36
+ if table.support_key?
37
+ table.add(request["key"], request["values"])
38
+ else
39
+ table.add(request["values"])
40
+ end
41
+ [true]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/handler"
19
+ require "droonga/logger"
20
+
21
+ module Droonga
22
+ class MergeHandler < Droonga::Handler
23
+ Droonga::HandlerPlugin.register("forward", self)
24
+
25
+ CONFIG_FILE_PATH = 'config.json'
26
+
27
+ def handlable?(command)
28
+ true
29
+ end
30
+
31
+ def handle(command, request, *arguments)
32
+ destination = get_destination
33
+ post(request,
34
+ "to" => destination, "type" => command, "arguments" => arguments)
35
+ rescue => exception
36
+ Logger.error("error while handling #{command}",
37
+ request: request,
38
+ arguments: arguments,
39
+ exception: exception)
40
+ end
41
+
42
+ def get_destination
43
+ loop do
44
+ refresh_config
45
+ if @config && @config["forward"]
46
+ path = @context.database.path
47
+ destination = @config["forward"][path]
48
+ return destination unless destination.nil? || destination.empty?
49
+ end
50
+ sleep 5
51
+ end
52
+ end
53
+
54
+ def refresh_config
55
+ unless File.exists?(CONFIG_FILE_PATH)
56
+ @config = nil
57
+ return
58
+ end
59
+ mtime = File.mtime(CONFIG_FILE_PATH)
60
+ return if @config_mtime == mtime
61
+ open(CONFIG_FILE_PATH) do |file|
62
+ @config = JSON.parse(file.read)
63
+ end
64
+ @config_mtime = mtime
65
+ rescue => exception
66
+ Logger.error("error while refreshing config", exception: exception)
67
+ @config = nil
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "groonga"
19
+
20
+ require "droonga/handler"
21
+
22
+ module Droonga
23
+ class GroongaHandler < Droonga::Handler
24
+ Droonga::HandlerPlugin.register("groonga", self)
25
+
26
+ command :table_create
27
+ def table_create(request)
28
+ command = TableCreate.new(@context)
29
+ outputs = command.execute(request)
30
+ emit(outputs)
31
+ end
32
+
33
+ command :column_create
34
+ def column_create(request)
35
+ command = ColumnCreate.new(@context)
36
+ outputs = command.execute(request)
37
+ emit(outputs)
38
+ end
39
+
40
+ def prefer_synchronous?(command)
41
+ return true
42
+ end
43
+
44
+ module Status
45
+ SUCCESS = 0
46
+ INVALID_ARGUMENT = -22
47
+ end
48
+ end
49
+ end
50
+
51
+ require "droonga/plugin/handler/groonga/table_create"
52
+ require "droonga/plugin/handler/groonga/column_create"
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/handler"
19
+ require "droonga/searcher"
20
+
21
+ module Droonga
22
+ class BasicProxyHandler < Droonga::ProxyHandler
23
+ Droonga::HandlerPlugin.register("proxy", self)
24
+
25
+ command :proxy_gather
26
+ def proxy_gather(request)
27
+ output = body ? body[input_name] : input_name
28
+ emit(request, output)
29
+ end
30
+
31
+ command :proxy_reduce
32
+ def proxy_reduce(request)
33
+ return unless request
34
+ body[input_name].each do |output, elements|
35
+ value = request
36
+ old_value = output_values[output]
37
+ value = reduce(elements, old_value, request) if old_value
38
+ emit(value, output)
39
+ end
40
+ end
41
+
42
+ def reduce(elements, *values)
43
+ result = {}
44
+ elements.each do |key, deal|
45
+ func, *args = deal
46
+ case func
47
+ when "sum"
48
+ result[key] = values[0][key] + values[1][key]
49
+ when "sort"
50
+ result[key] = merge(values[0][key], values[1][key], args)
51
+ end
52
+ end
53
+ return result
54
+ end
55
+
56
+ def merge(x, y, order)
57
+ index = 0
58
+ y.each do |_y|
59
+ loop do
60
+ _x = x[index]
61
+ break unless _x
62
+ break if compare(_y, _x, order)
63
+ index += 1
64
+ end
65
+ x.insert(index, _y)
66
+ index += 1
67
+ end
68
+ return x
69
+ end
70
+
71
+ def compare(x, y, operators)
72
+ for index in 0..x.size-1 do
73
+ _x = x[index]
74
+ _y = y[index]
75
+ operator = operators[index]
76
+ break unless operator
77
+ return true if _x.__send__(operator, _y)
78
+ end
79
+ return false
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/handler"
19
+ require "droonga/searcher"
20
+
21
+ module Droonga
22
+ class SearchHandler < Droonga::Handler
23
+ Droonga::HandlerPlugin.register("search", self)
24
+
25
+ command :search
26
+ def search(request)
27
+ searcher = Droonga::Searcher.new(@context)
28
+ searcher.search(request["queries"]).each do |output, value|
29
+ emit(value, output)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,102 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2013 droonga project
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "droonga/watcher"
19
+ require "droonga/sweeper"
20
+ require "droonga/watch_schema"
21
+ require "droonga/handler"
22
+
23
+ module Droonga
24
+ class WatchHandler < Droonga::Handler
25
+ Droonga::HandlerPlugin.register("watch", self)
26
+
27
+ def initialize(*args)
28
+ super
29
+
30
+ # XXX just workaround. This must be re-written.
31
+ # When secondary and later processes opens the database,
32
+ # creation processes of tables by the first process is
33
+ # not finished yet. Then secondary and others tries to
34
+ # create tables and raises errors. To avoid such a problem,
35
+ # the creation processes of tables is disabled on workers.
36
+ if $0 !~ /\AServer/
37
+ ensure_schema_created
38
+ else
39
+ until @context["Keyword"]
40
+ sleep 0.1
41
+ end
42
+ sleep 1
43
+ end
44
+
45
+ @watcher = Watcher.new(@context)
46
+ @sweeper = Sweeper.new(@context)
47
+ end
48
+
49
+ command "watch.subscribe" => :subscribe
50
+ def subscribe(request)
51
+ subscriber, condition, query, route = parse_request(request)
52
+ normalized_request = {
53
+ :subscriber => subscriber,
54
+ :condition => condition,
55
+ :query => query,
56
+ :route => route,
57
+ }
58
+ @watcher.subscribe(normalized_request)
59
+ emit([true])
60
+ end
61
+
62
+ command "watch.unsubscribe" => :unsubscribe
63
+ def unsubscribe(request)
64
+ subscriber, condition, query, route = parse_request(request)
65
+ normalized_request = {
66
+ :subscriber => subscriber,
67
+ :condition => condition,
68
+ :query => query,
69
+ }
70
+ @watcher.unsubscribe(normalized_request)
71
+ emit([true])
72
+ end
73
+
74
+ command "watch.feed" => :feed
75
+ def feed(request)
76
+ @watcher.feed(:targets => request["targets"]) do |route, subscribers|
77
+ message = request # return request itself
78
+ envelope["to"] = subscribers
79
+ post(message, "to" => route, "type" => "watch.notification")
80
+ end
81
+ end
82
+
83
+ command "watch.sweep" => :sweep
84
+ def sweep(request)
85
+ @sweeper.sweep_expired_subscribers
86
+ end
87
+
88
+ private
89
+ def parse_request(request)
90
+ subscriber = request["subscriber"]
91
+ condition = request["condition"]
92
+ route = request["route"] || envelope["from"]
93
+ query = condition && condition.to_json
94
+ [subscriber, condition, query, route]
95
+ end
96
+
97
+ def ensure_schema_created
98
+ schema = WatchSchema.new(@context)
99
+ schema.ensure_created
100
+ end
101
+ end
102
+ end