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
|
@@ -52,13 +52,19 @@ module Droonga
|
|
|
52
52
|
def send(tag, data)
|
|
53
53
|
logger.trace("send: start")
|
|
54
54
|
packed_fluent_message = create_packed_fluent_message(tag, data)
|
|
55
|
-
|
|
55
|
+
unless connected?
|
|
56
|
+
logger.trace("send: reconnect")
|
|
57
|
+
connect
|
|
58
|
+
end
|
|
56
59
|
@socket.write(packed_fluent_message)
|
|
57
60
|
logger.trace("send: done")
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
def resume
|
|
61
|
-
|
|
64
|
+
unless connected?
|
|
65
|
+
logger.trace("resume: reconnect to #{target_node}")
|
|
66
|
+
connect
|
|
67
|
+
end
|
|
62
68
|
end
|
|
63
69
|
|
|
64
70
|
private
|
|
@@ -69,22 +75,8 @@ module Droonga
|
|
|
69
75
|
def connect
|
|
70
76
|
logger.trace("connect: start")
|
|
71
77
|
|
|
72
|
-
log_write_complete = lambda do
|
|
73
|
-
logger.trace("write completed")
|
|
74
|
-
end
|
|
75
|
-
log_connect = lambda do
|
|
76
|
-
logger.trace("connected to #{@host}:#{@port}")
|
|
77
|
-
end
|
|
78
|
-
log_failed = lambda do
|
|
79
|
-
logger.error("failed to connect to #{@host}:#{@port}")
|
|
80
|
-
@socket = nil
|
|
81
|
-
end
|
|
82
|
-
on_close = lambda do
|
|
83
|
-
@socket = nil
|
|
84
|
-
end
|
|
85
|
-
|
|
86
78
|
if @buffering
|
|
87
|
-
data_directory = Path.
|
|
79
|
+
data_directory = Path.accidental_buffer + "#{target_node}"
|
|
88
80
|
FileUtils.mkdir_p(data_directory.to_s)
|
|
89
81
|
@socket = BufferedTCPSocket.connect(@host, @port, data_directory)
|
|
90
82
|
@socket.resume
|
|
@@ -92,25 +84,36 @@ module Droonga
|
|
|
92
84
|
@socket = Coolio::TCPSocket.connect(@host, @port)
|
|
93
85
|
end
|
|
94
86
|
@socket.on_write_complete do
|
|
95
|
-
|
|
87
|
+
logger.trace("write completed")
|
|
96
88
|
end
|
|
97
89
|
@socket.on_connect do
|
|
98
|
-
|
|
90
|
+
logger.trace("connected")
|
|
99
91
|
end
|
|
100
92
|
@socket.on_connect_failed do
|
|
101
|
-
|
|
93
|
+
logger.error("failed to connect")
|
|
94
|
+
@socket = nil
|
|
102
95
|
end
|
|
103
96
|
@socket.on_close do
|
|
104
|
-
|
|
97
|
+
logger.trace("connection is closed by someone")
|
|
98
|
+
@socket = nil
|
|
105
99
|
end
|
|
106
100
|
@loop.attach(@socket)
|
|
101
|
+
# logger.trace("connect: new socket watcher attached",
|
|
102
|
+
# :watcher => @socket,
|
|
103
|
+
# :host => @host,
|
|
104
|
+
# :port => @port)
|
|
107
105
|
|
|
108
106
|
logger.trace("connect: done")
|
|
109
107
|
end
|
|
110
108
|
|
|
111
109
|
def shutdown_socket
|
|
112
110
|
return unless connected?
|
|
113
|
-
|
|
111
|
+
unless @socket.closed?
|
|
112
|
+
# logger.trace("shutdown_socket: socket watcher detaching",
|
|
113
|
+
# :watcher => @socket)
|
|
114
|
+
@socket.close
|
|
115
|
+
logger.trace("shutdown_socket: socket watcher detached")
|
|
116
|
+
end
|
|
114
117
|
end
|
|
115
118
|
|
|
116
119
|
def create_packed_fluent_message(tag, data)
|
|
@@ -121,8 +124,12 @@ module Droonga
|
|
|
121
124
|
packed_fluent_message
|
|
122
125
|
end
|
|
123
126
|
|
|
127
|
+
def target_node
|
|
128
|
+
"#{@host}:#{@port}"
|
|
129
|
+
end
|
|
130
|
+
|
|
124
131
|
def log_tag
|
|
125
|
-
"[#{Process.ppid}] fluent-message-sender"
|
|
132
|
+
"[#{Process.ppid}] fluent-message-sender: #{target_node}"
|
|
126
133
|
end
|
|
127
134
|
end
|
|
128
135
|
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2014-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
+
|
|
18
|
+
require "fileutils"
|
|
19
|
+
require "pathname"
|
|
20
|
+
require "msgpack"
|
|
21
|
+
require "time"
|
|
22
|
+
|
|
23
|
+
require "droonga/loggable"
|
|
24
|
+
require "droonga/path"
|
|
25
|
+
require "droonga/safe_file_writer"
|
|
26
|
+
require "droonga/serf"
|
|
27
|
+
require "droonga/timestamp"
|
|
28
|
+
|
|
29
|
+
module Droonga
|
|
30
|
+
class ForwardBuffer
|
|
31
|
+
include Loggable
|
|
32
|
+
|
|
33
|
+
SUFFIX = ".msgpack"
|
|
34
|
+
|
|
35
|
+
attr_writer :on_forward
|
|
36
|
+
|
|
37
|
+
def initialize(node_name)
|
|
38
|
+
@on_forward = nil
|
|
39
|
+
|
|
40
|
+
@packer = MessagePack::Packer.new
|
|
41
|
+
@unpacker = MessagePack::Unpacker.new
|
|
42
|
+
|
|
43
|
+
@target = node_name
|
|
44
|
+
@serf = Serf.new(ENV["DROONGA_ENGINE_NAME"])
|
|
45
|
+
|
|
46
|
+
dirname = node_name.gsub("/", ":")
|
|
47
|
+
@data_directory = Path.intentional_buffer + dirname
|
|
48
|
+
FileUtils.mkdir_p(@data_directory.to_s)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def add(message, destination)
|
|
52
|
+
logger.trace("add: start")
|
|
53
|
+
@serf.set_have_unprocessed_messages_for(@target)
|
|
54
|
+
buffered_message = {
|
|
55
|
+
"message" => message,
|
|
56
|
+
"destination" => destination,
|
|
57
|
+
}
|
|
58
|
+
@packer.pack(buffered_message)
|
|
59
|
+
file_path = create_buffered_message_path
|
|
60
|
+
SafeFileWriter.write(file_path) do |output, file|
|
|
61
|
+
output.puts(@packer.to_s)
|
|
62
|
+
end
|
|
63
|
+
@packer.clear
|
|
64
|
+
logger.trace("add: done", :path => file_path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def start_forward
|
|
68
|
+
logger.trace("start_forward: start")
|
|
69
|
+
n_forwarded_messages = 0
|
|
70
|
+
buffered_messages.each do |buffered_message_path|
|
|
71
|
+
forwarded = forward(buffered_message_path)
|
|
72
|
+
n_forwarded_messages += 1 if forwarded
|
|
73
|
+
end
|
|
74
|
+
if n_forwarded_messages > 0 and
|
|
75
|
+
@process_messages_newer_than_timestamp
|
|
76
|
+
logger.info("#{n_forwarded_messages} new messages forwarded. " +
|
|
77
|
+
"The boundary is now cleared.")
|
|
78
|
+
# Don't clear the boundary while forwarding.
|
|
79
|
+
# Because buffered messages are not sorted by their "date",
|
|
80
|
+
# so older messages can appear after newer one.
|
|
81
|
+
# (ex. messages generated by Dispatcher)
|
|
82
|
+
@process_messages_newer_than_timestamp = nil
|
|
83
|
+
end
|
|
84
|
+
@serf.reset_have_unprocessed_messages_for(@target)
|
|
85
|
+
logger.trace("start_forward: done")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def buffered_messages
|
|
89
|
+
Pathname.glob("#{@data_directory}/*#{SUFFIX}").sort_by do |path|
|
|
90
|
+
path
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def empty?
|
|
95
|
+
@data_directory.children.empty?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def process_messages_newer_than(timestamp)
|
|
99
|
+
@process_messages_newer_than_timestamp = timestamp
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
def forward(buffered_message_path)
|
|
104
|
+
logger.trace("forward: start (#{buffered_message_path})")
|
|
105
|
+
|
|
106
|
+
unless buffered_message_path.exist?
|
|
107
|
+
logger.warn("forward: no buffer file (maybe sent by other process)",
|
|
108
|
+
:path => buffered_message_path)
|
|
109
|
+
return false
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
file_contents = buffered_message_path.read
|
|
113
|
+
@unpacker.feed(file_contents)
|
|
114
|
+
buffered_message = @unpacker.read
|
|
115
|
+
@unpacker.reset
|
|
116
|
+
|
|
117
|
+
message = buffered_message["message"]
|
|
118
|
+
destination = buffered_message["destination"]
|
|
119
|
+
|
|
120
|
+
forwarded = false
|
|
121
|
+
|
|
122
|
+
if @process_messages_newer_than_timestamp
|
|
123
|
+
message_timestamp = Time.parse(message["date"])
|
|
124
|
+
logger.trace("Checking boundary of obsolete message",
|
|
125
|
+
:newer_than => @process_messages_newer_than_timestamp,
|
|
126
|
+
:message_at => message_timestamp)
|
|
127
|
+
if @process_messages_newer_than_timestamp >= message_timestamp
|
|
128
|
+
buffered_message = nil
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
if buffered_message
|
|
133
|
+
logger.trace("forward: Forwarding buffered message",
|
|
134
|
+
:message => message,
|
|
135
|
+
:destination => destination)
|
|
136
|
+
message["xSender"] = "forward-buffer"
|
|
137
|
+
on_forward(message, destination)
|
|
138
|
+
forwarded = true
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
FileUtils.rm_f(buffered_message_path.to_s)
|
|
142
|
+
logger.trace("forward: done (#{buffered_message_path})")
|
|
143
|
+
|
|
144
|
+
forwarded
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def create_buffered_message_path(time_stamp=Time.now)
|
|
148
|
+
basename = Timestamp.stringify(time_stamp)
|
|
149
|
+
Path.unique_file_path(@data_directory, basename, SUFFIX)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def on_forward(message, destination)
|
|
153
|
+
@on_forward.call(message, destination) if @on_forward
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def log_tag
|
|
157
|
+
"[#{Process.ppid}] forward-buffer"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
data/lib/droonga/forwarder.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,38 +15,45 @@
|
|
|
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 "coolio"
|
|
19
|
+
|
|
18
20
|
require "droonga/loggable"
|
|
19
21
|
require "droonga/path"
|
|
20
|
-
require "droonga/event_loop"
|
|
21
|
-
require "droonga/buffered_tcp_socket"
|
|
22
22
|
require "droonga/fluent_message_sender"
|
|
23
23
|
|
|
24
24
|
module Droonga
|
|
25
25
|
class Forwarder
|
|
26
26
|
include Loggable
|
|
27
27
|
|
|
28
|
+
class AlreadyShutdown < StandardError
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
DEFAULT_AUTO_CLOSE_TIMEOUT_SECONDS = 60
|
|
32
|
+
|
|
28
33
|
def initialize(loop, options={})
|
|
29
34
|
@loop = loop
|
|
30
|
-
@buffering = options[:buffering]
|
|
31
35
|
@senders = {}
|
|
36
|
+
@auto_close_timers = {}
|
|
37
|
+
@shutting_down = false
|
|
38
|
+
@auto_close_timeout = options[:auto_close_timeout] ||
|
|
39
|
+
DEFAULT_AUTO_CLOSE_TIMEOUT_SECONDS
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
def start
|
|
35
43
|
logger.trace("start: start")
|
|
36
|
-
resume
|
|
37
44
|
logger.trace("start: done")
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
def shutdown
|
|
41
48
|
logger.trace("shutdown: start")
|
|
42
|
-
@
|
|
43
|
-
|
|
44
|
-
end
|
|
49
|
+
@shutting_down = true
|
|
50
|
+
clear_senders
|
|
45
51
|
logger.trace("shutdown: done")
|
|
46
52
|
end
|
|
47
53
|
|
|
48
54
|
def forward(message, destination)
|
|
49
|
-
logger.trace("forward: start")
|
|
55
|
+
logger.trace("forward: start", :message => message)
|
|
56
|
+
raise AlreadyShutdown.new if @shutting_down
|
|
50
57
|
command = destination["type"]
|
|
51
58
|
receiver = destination["to"]
|
|
52
59
|
arguments = destination["arguments"]
|
|
@@ -54,33 +61,25 @@ module Droonga
|
|
|
54
61
|
logger.trace("forward: done")
|
|
55
62
|
end
|
|
56
63
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
chunk_loader = BufferedTCPSocket::ChunkLoader.new(path)
|
|
70
|
-
unless chunk_loader.have_any_chunk?
|
|
71
|
-
#FileUtils.rm_rf(path.to_s) # TODO re-enable this
|
|
72
|
-
next
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
components = destination.split(":")
|
|
76
|
-
port = components.pop.to_i
|
|
77
|
-
next if port.zero?
|
|
78
|
-
host = components.join(":")
|
|
79
|
-
|
|
80
|
-
sender = create_sender(host, port)
|
|
81
|
-
sender.resume
|
|
82
|
-
@senders[destination] = sender
|
|
64
|
+
def refresh_connection_for(name)
|
|
65
|
+
logger.trace("refresh_connection_for(#{name}): start")
|
|
66
|
+
sender = @senders[name]
|
|
67
|
+
if sender
|
|
68
|
+
sender.shutdown
|
|
69
|
+
@senders.delete(name)
|
|
70
|
+
end
|
|
71
|
+
timer = @auto_close_timers[name]
|
|
72
|
+
if timer
|
|
73
|
+
timer.detach
|
|
74
|
+
@auto_close_timers.delete(name)
|
|
83
75
|
end
|
|
76
|
+
logger.trace("refresh_connection_for(#{name}): done")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def refresh_all_connections
|
|
80
|
+
logger.trace("refresh_all_connections: start")
|
|
81
|
+
clear_senders
|
|
82
|
+
logger.trace("refresh_all_connections: done")
|
|
84
83
|
end
|
|
85
84
|
|
|
86
85
|
private
|
|
@@ -107,6 +106,7 @@ module Droonga
|
|
|
107
106
|
:params => params)
|
|
108
107
|
return
|
|
109
108
|
end
|
|
109
|
+
set_auto_close_timer(host, port, params)
|
|
110
110
|
override_message = {
|
|
111
111
|
"type" => command,
|
|
112
112
|
}
|
|
@@ -120,11 +120,15 @@ module Droonga
|
|
|
120
120
|
logger.trace("output: done")
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
-
def
|
|
123
|
+
def resolve_destination(host, port, params)
|
|
124
124
|
connection_id = extract_connection_id(params)
|
|
125
125
|
destination = "#{host}:#{port}"
|
|
126
126
|
destination << "?#{connection_id}" if connection_id
|
|
127
|
+
destination
|
|
128
|
+
end
|
|
127
129
|
|
|
130
|
+
def find_sender(host, port, params)
|
|
131
|
+
destination = resolve_destination(host, port, params)
|
|
128
132
|
@senders[destination] ||= create_sender(host, port)
|
|
129
133
|
end
|
|
130
134
|
|
|
@@ -139,14 +143,43 @@ module Droonga
|
|
|
139
143
|
end
|
|
140
144
|
|
|
141
145
|
def create_sender(host, port)
|
|
142
|
-
|
|
143
|
-
:buffering => @buffering,
|
|
144
|
-
}
|
|
145
|
-
sender = FluentMessageSender.new(@loop, host, port, options)
|
|
146
|
+
sender = FluentMessageSender.new(@loop, host, port)
|
|
146
147
|
sender.start
|
|
147
148
|
sender
|
|
148
149
|
end
|
|
149
150
|
|
|
151
|
+
def set_auto_close_timer(host, port, params)
|
|
152
|
+
destination = resolve_destination(host, port, params)
|
|
153
|
+
|
|
154
|
+
previous_timer = @auto_close_timers[destination]
|
|
155
|
+
previous_timer.detach if previous_timer
|
|
156
|
+
|
|
157
|
+
timer = Coolio::TimerWatcher.new(@auto_close_timeout)
|
|
158
|
+
timer.on_timer do
|
|
159
|
+
timer.detach
|
|
160
|
+
@auto_close_timers.delete(destination)
|
|
161
|
+
sender = @senders[destination]
|
|
162
|
+
if sender
|
|
163
|
+
logger.info("sender for #{destination} is automatically closed by timeout.")
|
|
164
|
+
sender.shutdown
|
|
165
|
+
@senders.delete(destination)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
@loop.attach(timer)
|
|
169
|
+
@auto_close_timers[destination] = timer
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def clear_senders
|
|
173
|
+
@senders.each_value do |sender|
|
|
174
|
+
sender.shutdown
|
|
175
|
+
end
|
|
176
|
+
@senders = {}
|
|
177
|
+
@auto_close_timers.each_value do |timer|
|
|
178
|
+
timer.detach
|
|
179
|
+
end
|
|
180
|
+
@auto_close_timers = {}
|
|
181
|
+
end
|
|
182
|
+
|
|
150
183
|
def log_tag
|
|
151
184
|
"[#{Process.ppid}] forwarder"
|
|
152
185
|
end
|
data/lib/droonga/handler.rb
CHANGED
|
@@ -35,12 +35,13 @@ module Droonga
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
attr_reader :messenger, :loop
|
|
39
|
-
def initialize(
|
|
40
|
-
@name
|
|
41
|
-
@
|
|
42
|
-
@
|
|
43
|
-
@
|
|
38
|
+
attr_reader :label, :messenger, :loop
|
|
39
|
+
def initialize(params)
|
|
40
|
+
@name = params[:name]
|
|
41
|
+
@label = params[:label]
|
|
42
|
+
@context = params[:context]
|
|
43
|
+
@messenger = params[:messenger]
|
|
44
|
+
@loop = params[:loop]
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
def handle(message)
|