droonga-engine 1.0.9 → 1.1.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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/benchmark/timer-watcher/benchmark.rb +44 -0
- data/bin/droonga-engine-absorb-data +246 -187
- data/bin/droonga-engine-catalog-generate +12 -12
- data/bin/droonga-engine-catalog-modify +4 -4
- data/bin/droonga-engine-join +352 -171
- data/bin/droonga-engine-set-role +54 -0
- data/bin/droonga-engine-unjoin +107 -112
- data/droonga-engine.gemspec +3 -3
- data/install.sh +55 -36
- data/install/centos/functions.sh +2 -2
- data/install/debian/functions.sh +2 -2
- data/lib/droonga/address.rb +26 -24
- data/lib/droonga/buffered_tcp_socket.rb +65 -10
- data/lib/droonga/catalog/base.rb +9 -6
- data/lib/droonga/catalog/dataset.rb +17 -41
- data/lib/droonga/catalog/fetcher.rb +64 -0
- data/lib/droonga/catalog/generator.rb +245 -0
- data/lib/droonga/catalog/loader.rb +66 -0
- data/lib/droonga/{catalog_modifier.rb → catalog/modifier.rb} +11 -18
- data/lib/droonga/catalog/replicas_volume.rb +123 -0
- data/lib/droonga/catalog/schema.rb +37 -37
- data/lib/droonga/catalog/single_volume.rb +11 -3
- data/lib/droonga/catalog/slice.rb +10 -6
- data/lib/droonga/catalog/{collection_volume.rb → slices_volume.rb} +47 -11
- data/lib/droonga/catalog/version1.rb +47 -19
- data/lib/droonga/catalog/version2.rb +11 -10
- data/lib/droonga/catalog/version2_validator.rb +4 -4
- data/lib/droonga/catalog/volume.rb +17 -5
- data/lib/droonga/changable.rb +25 -0
- data/lib/droonga/cluster.rb +237 -0
- data/lib/droonga/collector_runner.rb +4 -0
- data/lib/droonga/collectors.rb +2 -1
- data/lib/droonga/collectors/recursive_sum.rb +26 -0
- data/lib/droonga/command/droonga_engine.rb +404 -127
- data/lib/droonga/command/droonga_engine_service.rb +47 -11
- data/lib/droonga/command/droonga_engine_worker.rb +21 -1
- data/lib/droonga/command/remote_command_base.rb +78 -0
- data/lib/droonga/command/serf_event_handler.rb +29 -20
- data/lib/droonga/data_absorber_client.rb +222 -0
- data/lib/droonga/database_scanner.rb +106 -0
- data/lib/droonga/{live_nodes_list_loader.rb → deferrable.rb} +11 -24
- data/lib/droonga/differ.rb +58 -0
- data/lib/droonga/dispatcher.rb +155 -32
- data/lib/droonga/distributed_command_planner.rb +9 -11
- data/lib/droonga/engine.rb +83 -78
- data/lib/droonga/engine/version.rb +1 -1
- data/lib/droonga/engine_node.rb +301 -0
- data/lib/droonga/engine_state.rb +62 -40
- data/lib/droonga/farm.rb +44 -5
- data/lib/droonga/file_observer.rb +16 -12
- data/lib/droonga/fluent_message_receiver.rb +98 -29
- data/lib/droonga/fluent_message_sender.rb +30 -23
- data/lib/droonga/forward_buffer.rb +160 -0
- data/lib/droonga/forwarder.rb +73 -40
- data/lib/droonga/handler.rb +7 -6
- data/lib/droonga/handler_messenger.rb +15 -6
- data/lib/droonga/handler_runner.rb +6 -1
- data/lib/droonga/internal_fluent_message_receiver.rb +28 -8
- data/lib/droonga/job_pusher.rb +10 -7
- data/lib/droonga/job_receiver.rb +6 -4
- data/lib/droonga/logger.rb +7 -1
- data/lib/droonga/node_name.rb +90 -0
- data/lib/droonga/node_role.rb +72 -0
- data/lib/droonga/path.rb +34 -9
- data/lib/droonga/planner.rb +73 -7
- data/lib/droonga/plugin/async_command.rb +154 -0
- data/lib/droonga/plugins/catalog.rb +1 -0
- data/lib/droonga/plugins/crud.rb +22 -6
- data/lib/droonga/plugins/dump.rb +66 -135
- data/lib/droonga/plugins/groonga/delete.rb +13 -0
- data/lib/droonga/plugins/search/distributed_search_planner.rb +4 -4
- data/lib/droonga/plugins/system.rb +5 -26
- data/lib/droonga/plugins/system/absorb_data.rb +405 -0
- data/lib/droonga/plugins/system/statistics.rb +71 -0
- data/lib/droonga/plugins/system/status.rb +53 -0
- data/lib/droonga/process_control_protocol.rb +3 -1
- data/lib/droonga/process_supervisor.rb +32 -15
- data/lib/droonga/reducer.rb +69 -0
- data/lib/droonga/safe_file_writer.rb +1 -1
- data/lib/droonga/serf.rb +207 -276
- data/lib/droonga/serf/agent.rb +228 -0
- data/lib/droonga/serf/command.rb +94 -0
- data/lib/droonga/serf/downloader.rb +120 -0
- data/lib/droonga/serf/remote_command.rb +348 -0
- data/lib/droonga/serf/tag.rb +56 -0
- data/lib/droonga/service_installation.rb +2 -2
- data/lib/droonga/session.rb +49 -1
- data/lib/droonga/single_step.rb +6 -11
- data/lib/droonga/single_step_definition.rb +32 -1
- data/lib/droonga/slice.rb +14 -9
- data/lib/droonga/supervisor.rb +27 -20
- data/lib/droonga/test/stub_handler_messenger.rb +2 -1
- data/lib/droonga/timestamp.rb +69 -0
- data/lib/droonga/worker_process_agent.rb +33 -15
- data/sample/cluster-state.json +8 -0
- data/sample/cluster/Rakefile +30 -6
- data/test/command/fixture/integer-key-table.jsons +11 -0
- data/test/command/fixture/string-key-table.jsons +11 -0
- data/test/command/run-test.rb +4 -0
- data/test/command/suite/add/error/invalid-integer.expected +3 -3
- data/test/command/suite/add/error/invalid-time.expected +3 -3
- data/test/command/suite/add/{minimum.expected → key-integer.expected} +0 -0
- data/test/command/suite/add/{minimum.test → key-integer.test} +0 -0
- data/test/command/suite/add/key-string.expected +6 -0
- data/test/command/suite/add/key-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/integer-for-string.test +9 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.expected +6 -0
- data/test/command/suite/add/mismatched-key-type/acceptable/string-for-integer.test +9 -0
- data/test/command/suite/add/without-values.expected +6 -0
- data/test/command/suite/add/without-values.test +11 -0
- data/test/command/suite/dump/column/index.expected +33 -1
- data/test/command/suite/dump/column/index.test +1 -0
- data/test/command/suite/dump/column/scalar.expected +29 -1
- data/test/command/suite/dump/column/scalar.test +1 -0
- data/test/command/suite/dump/column/vector.expected +29 -1
- data/test/command/suite/dump/column/vector.test +1 -0
- data/test/command/suite/dump/record/scalar.catalog.json +12 -0
- data/test/command/suite/dump/record/scalar.expected +84 -0
- data/test/command/suite/dump/record/scalar.test +16 -0
- data/test/command/suite/dump/record/vector/reference.expected +83 -1
- data/test/command/suite/dump/record/vector/reference.test +1 -0
- data/test/command/suite/dump/table/array.expected +27 -1
- data/test/command/suite/dump/table/array.test +1 -0
- data/test/command/suite/dump/table/double_array_trie.expected +27 -1
- data/test/command/suite/dump/table/double_array_trie.test +1 -0
- data/test/command/suite/dump/table/hash.expected +27 -1
- data/test/command/suite/dump/table/hash.test +1 -0
- data/test/command/suite/dump/table/patricia_trie.expected +27 -1
- data/test/command/suite/dump/table/patricia_trie.test +1 -0
- data/test/command/suite/groonga/delete/{success.expected → key-integer.expected} +0 -0
- data/test/command/suite/groonga/delete/key-integer.test +17 -0
- data/test/command/suite/groonga/delete/key-string.expected +19 -0
- data/test/command/suite/groonga/delete/{success.test → key-string.test} +4 -6
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/integer-for-string.test +17 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.expected +19 -0
- data/test/command/suite/groonga/delete/mismatched-type-key/acceptable/string-for-integer.test +17 -0
- data/test/command/suite/message/error/missing-dataset.test +1 -0
- data/test/command/suite/system/absorb-data/records.catalog.json +58 -0
- data/test/command/suite/system/absorb-data/records.expected +32 -0
- data/test/command/suite/system/absorb-data/records.test +24 -0
- data/test/command/suite/system/statistics/object/count/empty.expected +11 -0
- data/test/command/suite/system/statistics/object/count/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.catalog.json +36 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/empty.test +12 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.catalog.json +40 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.expected +19 -0
- data/test/command/suite/system/statistics/object/count/per-volume/schema.test +13 -0
- data/test/command/suite/system/statistics/object/count/record.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/record.expected +11 -0
- data/test/command/suite/system/statistics/object/count/record.test +23 -0
- data/test/command/suite/system/statistics/object/count/schema.catalog.json +12 -0
- data/test/command/suite/system/statistics/object/count/schema.expected +11 -0
- data/test/command/suite/system/statistics/object/count/schema.test +13 -0
- data/test/command/suite/system/status.expected +3 -2
- data/test/unit/catalog/test_dataset.rb +4 -1
- data/test/unit/{test_catalog_generator.rb → catalog/test_generator.rb} +2 -2
- data/test/unit/catalog/test_replicas_volume.rb +79 -0
- data/test/unit/catalog/test_single_volume.rb +2 -2
- data/test/unit/catalog/test_slice.rb +33 -1
- data/test/unit/catalog/{test_collection_volume.rb → test_slices_volume.rb} +72 -11
- data/test/unit/catalog/test_version2.rb +3 -0
- data/test/unit/helper/distributed_search_planner_helper.rb +2 -2
- data/test/unit/plugins/catalog/test_fetch.rb +4 -4
- data/test/unit/plugins/crud/test_add.rb +44 -4
- data/test/unit/plugins/groonga/test_column_create.rb +4 -4
- data/test/unit/plugins/groonga/test_column_list.rb +4 -4
- data/test/unit/plugins/groonga/test_column_remove.rb +4 -4
- data/test/unit/plugins/groonga/test_column_rename.rb +4 -4
- data/test/unit/plugins/groonga/test_delete.rb +73 -10
- data/test/unit/plugins/groonga/test_table_create.rb +4 -4
- data/test/unit/plugins/groonga/test_table_list.rb +4 -4
- data/test/unit/plugins/groonga/test_table_remove.rb +4 -4
- data/test/unit/plugins/search/test_handler.rb +4 -4
- data/test/unit/plugins/search/test_planner.rb +4 -2
- data/test/unit/plugins/system/test_status.rb +31 -15
- data/test/unit/plugins/test_watch.rb +16 -16
- data/test/unit/test_address.rb +4 -4
- metadata +134 -35
- data/lib/droonga/catalog/volume_collection.rb +0 -79
- data/lib/droonga/catalog_fetcher.rb +0 -53
- data/lib/droonga/catalog_generator.rb +0 -243
- data/lib/droonga/catalog_loader.rb +0 -56
- data/lib/droonga/command/remote.rb +0 -404
- data/lib/droonga/data_absorber.rb +0 -264
- data/lib/droonga/node_status.rb +0 -71
- data/lib/droonga/serf_downloader.rb +0 -115
- data/test/unit/catalog/test_volume_collection.rb +0 -78
data/lib/droonga/engine_state.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (C) 2014 Droonga Project
|
|
1
|
+
# Copyright (C) 2014-2015 Droonga Project
|
|
2
2
|
#
|
|
3
3
|
# This library is free software; you can redistribute it and/or
|
|
4
4
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
require "English"
|
|
17
17
|
|
|
18
|
-
require "coolio"
|
|
19
|
-
|
|
20
18
|
require "droonga/loggable"
|
|
19
|
+
require "droonga/deferrable"
|
|
21
20
|
require "droonga/event_loop"
|
|
22
21
|
require "droonga/forwarder"
|
|
23
22
|
require "droonga/replier"
|
|
@@ -25,28 +24,32 @@ require "droonga/replier"
|
|
|
25
24
|
module Droonga
|
|
26
25
|
class EngineState
|
|
27
26
|
include Loggable
|
|
27
|
+
include Deferrable
|
|
28
|
+
|
|
29
|
+
DEFAULT_SESSION_TIMEOUT_SECONDS = 60
|
|
28
30
|
|
|
29
31
|
attr_reader :loop
|
|
30
32
|
attr_reader :name
|
|
31
33
|
attr_reader :internal_name
|
|
34
|
+
attr_reader :internal_connection_lifetime
|
|
32
35
|
attr_reader :forwarder
|
|
33
36
|
attr_reader :replier
|
|
34
|
-
attr_writer :on_ready
|
|
35
|
-
attr_accessor :on_finish
|
|
36
37
|
attr_accessor :catalog
|
|
37
|
-
|
|
38
|
+
attr_accessor :on_finish
|
|
39
|
+
|
|
40
|
+
def initialize(loop, name, internal_name, params)
|
|
38
41
|
@loop = loop
|
|
39
42
|
@name = name
|
|
40
43
|
@internal_name = internal_name
|
|
44
|
+
@internal_connection_lifetime = params[:internal_connection_lifetime]
|
|
41
45
|
@sessions = {}
|
|
42
46
|
@current_id = 0
|
|
43
|
-
@forwarder = Forwarder.new(@loop,
|
|
47
|
+
@forwarder = Forwarder.new(@loop,
|
|
48
|
+
:auto_close_timeout =>
|
|
49
|
+
@internal_connection_lifetime)
|
|
44
50
|
@replier = Replier.new(@forwarder)
|
|
45
|
-
@on_ready = nil
|
|
46
51
|
@on_finish = nil
|
|
47
|
-
@catalog =
|
|
48
|
-
@live_nodes = nil
|
|
49
|
-
@dead_nodes = []
|
|
52
|
+
@catalog = params[:catalog]
|
|
50
53
|
end
|
|
51
54
|
|
|
52
55
|
def start
|
|
@@ -65,8 +68,43 @@ module Droonga
|
|
|
65
68
|
route.start_with?(@name) or route.start_with?(@internal_name)
|
|
66
69
|
end
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
FARM_PATH_MATCHER = /\A[^:]+:\d+\/[^.]+/
|
|
72
|
+
|
|
73
|
+
def internal_route(route)
|
|
74
|
+
if FARM_PATH_MATCHER =~ route
|
|
75
|
+
name = $MATCH
|
|
76
|
+
if name == @name or name == @internal_name
|
|
77
|
+
return route.sub(name, @internal_name)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
route
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def public_route(route)
|
|
84
|
+
if FARM_PATH_MATCHER =~ route
|
|
85
|
+
name = $MATCH
|
|
86
|
+
if name == @internal_name
|
|
87
|
+
return route.sub(name, @name)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
route
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def internal_farm_path(route)
|
|
94
|
+
if FARM_PATH_MATCHER =~ route
|
|
95
|
+
name = $MATCH
|
|
96
|
+
if name == @name or name == @internal_name
|
|
97
|
+
@internal_name
|
|
98
|
+
else
|
|
99
|
+
name
|
|
100
|
+
end
|
|
101
|
+
else
|
|
102
|
+
route
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def public_farm_path(route)
|
|
107
|
+
if FARM_PATH_MATCHER =~ route
|
|
70
108
|
name = $MATCH
|
|
71
109
|
if name == @internal_name
|
|
72
110
|
@name
|
|
@@ -88,12 +126,22 @@ module Droonga
|
|
|
88
126
|
@sessions[id]
|
|
89
127
|
end
|
|
90
128
|
|
|
91
|
-
def register_session(id, session)
|
|
129
|
+
def register_session(id, session, options={})
|
|
92
130
|
@sessions[id] = session
|
|
93
131
|
logger.trace("new session #{id} is registered. rest sessions=#{@sessions.size}")
|
|
132
|
+
|
|
133
|
+
timeout = options[:timeout] ||
|
|
134
|
+
@internal_connection_lifetime ||
|
|
135
|
+
DEFAULT_SESSION_TIMEOUT_SECONDS
|
|
136
|
+
session.set_timeout(@loop, timeout) do
|
|
137
|
+
logger.trace("session #{id} is timed out!")
|
|
138
|
+
unregister_session(id)
|
|
139
|
+
end
|
|
94
140
|
end
|
|
95
141
|
|
|
96
142
|
def unregister_session(id)
|
|
143
|
+
session = @sessions[id]
|
|
144
|
+
session.finish
|
|
97
145
|
@sessions.delete(id)
|
|
98
146
|
unless have_session?
|
|
99
147
|
@on_finish.call if @on_finish
|
|
@@ -105,32 +153,6 @@ module Droonga
|
|
|
105
153
|
not @sessions.empty?
|
|
106
154
|
end
|
|
107
155
|
|
|
108
|
-
def all_nodes
|
|
109
|
-
@catalog.all_nodes
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def live_nodes
|
|
113
|
-
@live_nodes || @catalog.all_nodes
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def live_nodes=(nodes)
|
|
117
|
-
old_live_nodes = @live_nodes
|
|
118
|
-
@live_nodes = nodes
|
|
119
|
-
@dead_nodes = all_nodes - @live_nodes
|
|
120
|
-
@forwarder.resume if old_live_nodes != @live_nodes
|
|
121
|
-
@live_nodes
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def remove_dead_routes(routes)
|
|
125
|
-
routes.reject do |route|
|
|
126
|
-
@dead_nodes.include?(farm_path(route))
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def on_ready
|
|
131
|
-
@on_ready.call if @on_ready
|
|
132
|
-
end
|
|
133
|
-
|
|
134
156
|
private
|
|
135
157
|
def log_tag
|
|
136
158
|
"engine_state"
|
data/lib/droonga/farm.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2013 Droonga Project
|
|
3
|
+
# Copyright (C) 2013-2015 Droonga Project
|
|
4
4
|
#
|
|
5
5
|
# This library is free software; you can redistribute it and/or
|
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -15,11 +15,22 @@
|
|
|
15
15
|
# License along with this library; if not, write to the Free Software
|
|
16
16
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
17
|
|
|
18
|
+
require "droonga/loggable"
|
|
19
|
+
require "droonga/deferrable"
|
|
18
20
|
require "droonga/slice"
|
|
19
21
|
|
|
20
22
|
module Droonga
|
|
21
23
|
class Farm
|
|
22
|
-
|
|
24
|
+
include Loggable
|
|
25
|
+
include Deferrable
|
|
26
|
+
|
|
27
|
+
class NoSlice < StandardError
|
|
28
|
+
def initialize(message, extra_informations={})
|
|
29
|
+
message = "#{message}: #{extra_informations.inspect}"
|
|
30
|
+
super(message)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
23
34
|
def initialize(name, catalog, loop, options={})
|
|
24
35
|
@name = name
|
|
25
36
|
@catalog = catalog
|
|
@@ -29,7 +40,7 @@ module Droonga
|
|
|
29
40
|
slices = @catalog.slices(name)
|
|
30
41
|
slices.each do |slice_name, slice_options|
|
|
31
42
|
dataset = @catalog.datasets[slice_options[:dataset]]
|
|
32
|
-
slice = Droonga::Slice.new(dataset,
|
|
43
|
+
slice = Droonga::Slice.new(slice_name, dataset,
|
|
33
44
|
@loop,
|
|
34
45
|
@options.merge(slice_options))
|
|
35
46
|
@slices[slice_name] = slice
|
|
@@ -37,12 +48,18 @@ module Droonga
|
|
|
37
48
|
end
|
|
38
49
|
|
|
39
50
|
def start
|
|
51
|
+
n_slices = @slices.size
|
|
52
|
+
if n_slices.zero?
|
|
53
|
+
on_ready
|
|
54
|
+
return
|
|
55
|
+
end
|
|
56
|
+
|
|
40
57
|
n_ready_slices = 0
|
|
41
58
|
@slices.each_value do |slice|
|
|
42
59
|
slice.on_ready = lambda do
|
|
43
60
|
n_ready_slices += 1
|
|
44
|
-
if n_ready_slices ==
|
|
45
|
-
|
|
61
|
+
if n_ready_slices == n_slices
|
|
62
|
+
on_ready
|
|
46
63
|
end
|
|
47
64
|
end
|
|
48
65
|
slice.start
|
|
@@ -50,13 +67,21 @@ module Droonga
|
|
|
50
67
|
end
|
|
51
68
|
|
|
52
69
|
def stop_gracefully
|
|
70
|
+
logger.trace("stop_gracefully: start")
|
|
53
71
|
n_slices = @slices.size
|
|
72
|
+
if n_slices.zero?
|
|
73
|
+
yield if block_given?
|
|
74
|
+
logger.trace("stop_gracefully: done")
|
|
75
|
+
return
|
|
76
|
+
end
|
|
77
|
+
|
|
54
78
|
n_done_slices = 0
|
|
55
79
|
@slices.each_value do |slice|
|
|
56
80
|
slice.stop_gracefully do
|
|
57
81
|
n_done_slices += 1
|
|
58
82
|
if n_done_slices == n_slices
|
|
59
83
|
yield if block_given?
|
|
84
|
+
logger.trace("stop_gracefully: done")
|
|
60
85
|
end
|
|
61
86
|
end
|
|
62
87
|
end
|
|
@@ -68,8 +93,22 @@ module Droonga
|
|
|
68
93
|
end
|
|
69
94
|
end
|
|
70
95
|
|
|
96
|
+
def refresh_node_reference
|
|
97
|
+
@slices.each_value do |slice|
|
|
98
|
+
slice.refresh_node_reference
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
71
102
|
def process(slice_name, message)
|
|
103
|
+
unless @slices.key?(slice_name)
|
|
104
|
+
raise NoSlice.new(slice_name, :message => message, :slices => @slices.keys)
|
|
105
|
+
end
|
|
72
106
|
@slices[slice_name].process(message)
|
|
73
107
|
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
def log_tag
|
|
111
|
+
"farm"
|
|
112
|
+
end
|
|
74
113
|
end
|
|
75
114
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2014 Droonga Project
|
|
3
|
+
# Copyright (C) 2014-2015 Droonga Project
|
|
4
4
|
#
|
|
5
5
|
# This library is free software; you can redistribute it and/or
|
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
|
@@ -19,15 +19,15 @@ require "coolio"
|
|
|
19
19
|
|
|
20
20
|
require "droonga/path"
|
|
21
21
|
require "droonga/loggable"
|
|
22
|
+
require "droonga/changable"
|
|
22
23
|
|
|
23
24
|
module Droonga
|
|
24
25
|
class FileObserver
|
|
25
26
|
include Loggable
|
|
27
|
+
include Changable
|
|
26
28
|
|
|
27
29
|
CHECK_INTERVAL = 1
|
|
28
30
|
|
|
29
|
-
attr_accessor :on_change
|
|
30
|
-
|
|
31
31
|
def initialize(loop, path)
|
|
32
32
|
@loop = loop
|
|
33
33
|
@path = path
|
|
@@ -36,25 +36,29 @@ module Droonga
|
|
|
36
36
|
else
|
|
37
37
|
@mtime = nil
|
|
38
38
|
end
|
|
39
|
-
@on_change = nil
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
def start
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return if @timer
|
|
43
|
+
@timer = Coolio::TimerWatcher.new(CHECK_INTERVAL, true)
|
|
44
|
+
@timer.on_timer do
|
|
45
45
|
if updated?
|
|
46
46
|
@mtime = @path.mtime
|
|
47
|
-
|
|
47
|
+
on_change
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
|
-
@
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
@loop.attach(@timer)
|
|
51
|
+
logger.trace("start: timer attached",
|
|
52
|
+
:watcher => @timer,
|
|
53
|
+
:path => @path)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def stop
|
|
57
|
-
@
|
|
57
|
+
@timer.detach if @timer
|
|
58
|
+
logger.trace("stop: timer detached",
|
|
59
|
+
:watcher => @timer,
|
|
60
|
+
:path => @path)
|
|
61
|
+
@timer = nil
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
private
|
|
@@ -24,6 +24,21 @@ module Droonga
|
|
|
24
24
|
class FluentMessageReceiver
|
|
25
25
|
include Loggable
|
|
26
26
|
|
|
27
|
+
class InvalidObject < StandardError
|
|
28
|
+
def initialize(object)
|
|
29
|
+
message = "no valid tag information: #{object.inspect}"
|
|
30
|
+
super(message)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class UnknownTypeEntries < StandardError
|
|
35
|
+
def initialize(object)
|
|
36
|
+
message = "unknown type message: couldn't detect entries: " +
|
|
37
|
+
"#{object.inspect}"
|
|
38
|
+
super(message)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
27
42
|
def initialize(loop, options={}, &on_message)
|
|
28
43
|
@loop = loop
|
|
29
44
|
@listen_fd = options[:listen_fd]
|
|
@@ -31,6 +46,7 @@ module Droonga
|
|
|
31
46
|
@server = nil
|
|
32
47
|
@clients = []
|
|
33
48
|
@on_message = on_message
|
|
49
|
+
@on_shutdown_ready = nil
|
|
34
50
|
end
|
|
35
51
|
|
|
36
52
|
def start
|
|
@@ -48,20 +64,34 @@ module Droonga
|
|
|
48
64
|
logger.trace("stop_gracefully: done")
|
|
49
65
|
end
|
|
50
66
|
|
|
67
|
+
def ensure_no_client(&block)
|
|
68
|
+
if @clients.empty?
|
|
69
|
+
logger.trace("ensure_no_client: no client")
|
|
70
|
+
yield
|
|
71
|
+
elsif block_given?
|
|
72
|
+
logger.trace("ensure_no_client: waiting for #{@clients.size} clients to be disconnected",
|
|
73
|
+
:clients => @clients)
|
|
74
|
+
@on_shutdown_ready = lambda do
|
|
75
|
+
logger.trace("ensure_no_client: all clients are disconnected")
|
|
76
|
+
yield
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
51
81
|
def stop_immediately
|
|
52
82
|
logger.trace("stop_immediately: start")
|
|
53
83
|
stop_gracefully
|
|
54
|
-
|
|
84
|
+
force_shutdown_clients
|
|
55
85
|
logger.trace("stop_immediately: done")
|
|
56
86
|
end
|
|
57
87
|
|
|
58
|
-
|
|
88
|
+
private
|
|
89
|
+
def force_shutdown_clients
|
|
59
90
|
@clients.dup.each do |client|
|
|
60
91
|
client.close
|
|
61
92
|
end
|
|
62
93
|
end
|
|
63
94
|
|
|
64
|
-
private
|
|
65
95
|
def start_heartbeat_receiver
|
|
66
96
|
logger.trace("start_heartbeat_receiver: start")
|
|
67
97
|
@heartbeat_receiver = HeartbeatReceiver.new(@loop, @heartbeat_fd)
|
|
@@ -80,15 +110,29 @@ module Droonga
|
|
|
80
110
|
|
|
81
111
|
@clients = []
|
|
82
112
|
@server = create_server do |connection|
|
|
113
|
+
logger.trace("Client: new connection", :connection => connection)
|
|
83
114
|
client = Client.new(connection) do |tag, time, record|
|
|
115
|
+
logger.trace("Client: on_message: start")
|
|
84
116
|
@on_message.call(tag, time, record)
|
|
117
|
+
logger.trace("Client: on_message: done")
|
|
85
118
|
end
|
|
86
119
|
client.on_close = lambda do
|
|
87
120
|
@clients.delete(client)
|
|
121
|
+
if @on_shutdown_ready
|
|
122
|
+
logger.trace("Client: a client is disconnected. still waiting for #{@clients.size} clients.",
|
|
123
|
+
:clients => @clients)
|
|
124
|
+
if @clients.empty?
|
|
125
|
+
@on_shutdown_ready.call
|
|
126
|
+
end
|
|
127
|
+
end
|
|
88
128
|
end
|
|
89
129
|
@clients << client
|
|
90
130
|
end
|
|
91
131
|
@loop.attach(@server)
|
|
132
|
+
logger.trace("start_server: server watcher attached",
|
|
133
|
+
:watcher => @server,
|
|
134
|
+
:listen_fd => @listen_fd,
|
|
135
|
+
:heartbeat_fd => @heartbeat_fd)
|
|
92
136
|
|
|
93
137
|
logger.trace("start_server: done")
|
|
94
138
|
end
|
|
@@ -100,6 +144,8 @@ module Droonga
|
|
|
100
144
|
def shutdown_server
|
|
101
145
|
logger.trace("shutdown_server: start")
|
|
102
146
|
@server.close
|
|
147
|
+
logger.trace("shutdown_server: server watcher detached",
|
|
148
|
+
:watcher => @server)
|
|
103
149
|
logger.trace("shutdown_server: done")
|
|
104
150
|
end
|
|
105
151
|
|
|
@@ -108,6 +154,8 @@ module Droonga
|
|
|
108
154
|
end
|
|
109
155
|
|
|
110
156
|
class HeartbeatReceiver
|
|
157
|
+
include Loggable
|
|
158
|
+
|
|
111
159
|
def initialize(loop, fd)
|
|
112
160
|
@loop = loop
|
|
113
161
|
@fd = fd
|
|
@@ -117,18 +165,21 @@ module Droonga
|
|
|
117
165
|
@socket = UDPSocket.for_fd(@fd)
|
|
118
166
|
|
|
119
167
|
@watcher = Coolio::IOWatcher.new(@socket, "r")
|
|
120
|
-
on_readable = lambda do
|
|
121
|
-
receive_heartbeat
|
|
122
|
-
end
|
|
123
168
|
@watcher.on_readable do
|
|
124
|
-
|
|
169
|
+
receive_heartbeat
|
|
125
170
|
end
|
|
126
171
|
@loop.attach(@watcher)
|
|
172
|
+
logger.trace("start: heartbeat IO watcher attached",
|
|
173
|
+
:watcher => @watcher,
|
|
174
|
+
:fd => @fd)
|
|
127
175
|
end
|
|
128
176
|
|
|
129
177
|
def shutdown
|
|
130
178
|
@socket.close
|
|
131
179
|
@watcher.detach
|
|
180
|
+
logger.trace("shutdown: heartbeat watcher detached",
|
|
181
|
+
:watcher => @watcher,
|
|
182
|
+
:fd => @fd)
|
|
132
183
|
end
|
|
133
184
|
|
|
134
185
|
private
|
|
@@ -153,6 +204,10 @@ module Droonga
|
|
|
153
204
|
rescue SystemCallError
|
|
154
205
|
end
|
|
155
206
|
end
|
|
207
|
+
|
|
208
|
+
def log_tag
|
|
209
|
+
"heartbeat-receiver"
|
|
210
|
+
end
|
|
156
211
|
end
|
|
157
212
|
|
|
158
213
|
class Client
|
|
@@ -165,20 +220,14 @@ module Droonga
|
|
|
165
220
|
@on_close = nil
|
|
166
221
|
@unpacker = MessagePack::Unpacker.new
|
|
167
222
|
|
|
168
|
-
on_read = lambda do |data|
|
|
169
|
-
feed(data)
|
|
170
|
-
end
|
|
171
223
|
@io.on_read do |data|
|
|
172
|
-
|
|
224
|
+
feed(data)
|
|
173
225
|
end
|
|
174
226
|
|
|
175
|
-
on_close
|
|
227
|
+
@io.on_close do
|
|
176
228
|
@io = nil
|
|
177
229
|
@on_close.call if @on_close
|
|
178
230
|
end
|
|
179
|
-
@io.on_close do
|
|
180
|
-
on_close.call
|
|
181
|
-
end
|
|
182
231
|
end
|
|
183
232
|
|
|
184
233
|
def close
|
|
@@ -187,22 +236,42 @@ module Droonga
|
|
|
187
236
|
|
|
188
237
|
private
|
|
189
238
|
def feed(data)
|
|
239
|
+
logger.trace("Client: feed: start", :data => data)
|
|
190
240
|
@unpacker.feed_each(data) do |object|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
entries = object[1]
|
|
197
|
-
when Integer, Float # Message message
|
|
198
|
-
entries = [[object[1], object[2]]]
|
|
199
|
-
else
|
|
200
|
-
logger.error("unknown message", :message => object)
|
|
201
|
-
next
|
|
202
|
-
end
|
|
203
|
-
entries.each do |time, record|
|
|
204
|
-
@on_message.call(tag, time || Time.now.to_i, record)
|
|
241
|
+
logger.trace("Client: feed_each: start", :object => object)
|
|
242
|
+
begin
|
|
243
|
+
handle_feeded_object(object)
|
|
244
|
+
rescue InvalidObject, UnknownTypeEntries, MessagePack::MalformedFormatError => error
|
|
245
|
+
logger.exception("failed to process feeded object", error)
|
|
205
246
|
end
|
|
247
|
+
logger.trace("Client: feed_each: done")
|
|
248
|
+
end
|
|
249
|
+
logger.trace("Client: feed: done")
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def handle_feeded_object(object)
|
|
253
|
+
raise InvalidObject.new(object) unless object.is_a?(Array)
|
|
254
|
+
|
|
255
|
+
tag = object[0]
|
|
256
|
+
raise InvalidObject.new(object) unless tag.is_a?(String)
|
|
257
|
+
|
|
258
|
+
case object[1]
|
|
259
|
+
when String # PackedForward message [tag, "packed entries"]
|
|
260
|
+
raise InvalidObject.new(object) unless object.size == 2
|
|
261
|
+
entries = MessagePack.unpack(object[1])
|
|
262
|
+
when Array # Forward message [tag, [entry, entry...]]
|
|
263
|
+
raise InvalidObject.new(object) unless object.size == 2
|
|
264
|
+
entries = object[1]
|
|
265
|
+
when Integer, Float # Message message [tag, time, record]
|
|
266
|
+
raise InvalidObject.new(object) unless object.size == 3
|
|
267
|
+
entries = [[object[1], object[2]]]
|
|
268
|
+
else
|
|
269
|
+
raise UnknownTypeEntries.new(object)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
raise InvalidObject.new(object) unless entries.is_a?(Array)
|
|
273
|
+
entries.each do |time, record|
|
|
274
|
+
@on_message.call(tag, time || Time.now.to_i, record)
|
|
206
275
|
end
|
|
207
276
|
end
|
|
208
277
|
|