droonga-client 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/droonga-send +1 -0
- data/doc/text/news.md +4 -0
- data/droonga-client.gemspec +1 -0
- data/lib/droonga/client/connection/droonga-protocol.rb +20 -170
- data/lib/droonga/client/connection/droonga-protocol/coolio.rb +232 -0
- data/lib/droonga/client/connection/droonga-protocol/thread.rb +217 -0
- data/lib/droonga/client/connection/empty-request.rb +28 -0
- data/lib/droonga/client/connection/error.rb +10 -0
- data/lib/droonga/client/version.rb +1 -1
- metadata +30 -16
data/bin/droonga-send
CHANGED
data/doc/text/news.md
CHANGED
data/droonga-client.gemspec
CHANGED
@@ -39,6 +39,7 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_runtime_dependency "fluent-logger"
|
40
40
|
spec.add_runtime_dependency "rack"
|
41
41
|
spec.add_runtime_dependency "yajl-ruby"
|
42
|
+
spec.add_runtime_dependency "droonga-message-pack-packer"
|
42
43
|
|
43
44
|
spec.add_development_dependency "bundler", "~> 1.3"
|
44
45
|
spec.add_development_dependency "rake"
|
@@ -15,36 +15,18 @@
|
|
15
15
|
# License along with this library; if not, write to the Free Software
|
16
16
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
17
|
|
18
|
-
require "
|
19
|
-
require "thread"
|
20
|
-
require "msgpack"
|
21
|
-
require "fluent-logger"
|
18
|
+
require "droonga/client/connection/error"
|
22
19
|
|
23
20
|
module Droonga
|
24
21
|
class Client
|
25
22
|
module Connection
|
26
23
|
class DroongaProtocol
|
27
|
-
class Request
|
28
|
-
def initialize(thread)
|
29
|
-
@thread = thread
|
30
|
-
end
|
31
|
-
|
32
|
-
def wait
|
33
|
-
@thread.join
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
24
|
def initialize(options={})
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}
|
44
|
-
@options = default_options.merge(options)
|
45
|
-
@logger = Fluent::Logger::FluentLogger.new(@options.delete(:tag),
|
46
|
-
@options)
|
47
|
-
@timeout = @options[:timeout]
|
25
|
+
@host = options[:host] || "127.0.0.1"
|
26
|
+
@port = options[:port] || 24224
|
27
|
+
@tag = options[:tag] || "droonga"
|
28
|
+
@options = options
|
29
|
+
@backend = create_backend
|
48
30
|
end
|
49
31
|
|
50
32
|
# Sends a request message and receives one or more response
|
@@ -72,28 +54,7 @@ module Droonga
|
|
72
54
|
#
|
73
55
|
# @return [Request] The request object.
|
74
56
|
def request(message, options={}, &block)
|
75
|
-
|
76
|
-
message = message.dup
|
77
|
-
message["replyTo"] = "#{receiver.host}:#{receiver.port}/droonga"
|
78
|
-
send(message, options)
|
79
|
-
|
80
|
-
sync = block.nil?
|
81
|
-
if sync
|
82
|
-
responses = []
|
83
|
-
receive(receiver, options) do |response|
|
84
|
-
responses << response
|
85
|
-
end
|
86
|
-
if responses.size > 1
|
87
|
-
responses
|
88
|
-
else
|
89
|
-
responses.first
|
90
|
-
end
|
91
|
-
else
|
92
|
-
thread = Thread.new do
|
93
|
-
receive(receiver, options, &block)
|
94
|
-
end
|
95
|
-
Request.new(thread)
|
96
|
-
end
|
57
|
+
@backend.request(message, options, &block)
|
97
58
|
end
|
98
59
|
|
99
60
|
# Subscribes something and receives zero or more published
|
@@ -123,35 +84,7 @@ module Droonga
|
|
123
84
|
#
|
124
85
|
# @return [Request] The request object.
|
125
86
|
def subscribe(message, options={}, &block)
|
126
|
-
|
127
|
-
message = message.dup
|
128
|
-
message["from"] = "#{receiver.host}:#{receiver.port}/droonga"
|
129
|
-
send(message, options)
|
130
|
-
|
131
|
-
receive_options = {
|
132
|
-
:timeout => nil,
|
133
|
-
}
|
134
|
-
sync = block.nil?
|
135
|
-
if sync
|
136
|
-
Enumerator.new do |yielder|
|
137
|
-
loop do
|
138
|
-
receiver.receive(receive_options) do |object|
|
139
|
-
yielder << object
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
else
|
144
|
-
thread = Thread.new do
|
145
|
-
begin
|
146
|
-
loop do
|
147
|
-
receiver.receive(receive_options, &block)
|
148
|
-
end
|
149
|
-
ensure
|
150
|
-
receiver.close
|
151
|
-
end
|
152
|
-
end
|
153
|
-
Request.new(thread)
|
154
|
-
end
|
87
|
+
@backend.subscribe(message, options, &block)
|
155
88
|
end
|
156
89
|
|
157
90
|
# Sends low level request. Normally, you should use other
|
@@ -162,114 +95,31 @@ module Droonga
|
|
162
95
|
# TODO: WRITE ME
|
163
96
|
# @return [void]
|
164
97
|
def send(message, options={}, &block)
|
165
|
-
|
166
|
-
message = message.merge("id" => Time.now.to_f.to_s,
|
167
|
-
"date" => Time.now)
|
168
|
-
end
|
169
|
-
@logger.post("message", message)
|
98
|
+
@backend.send(message, options, &block)
|
170
99
|
end
|
171
100
|
|
172
101
|
# Close the connection. This connection can't be used anymore.
|
173
102
|
#
|
174
103
|
# @return [void]
|
175
104
|
def close
|
176
|
-
@
|
105
|
+
@backend.close
|
177
106
|
end
|
178
107
|
|
179
108
|
private
|
180
|
-
def
|
181
|
-
|
182
|
-
:port => @options[:receiver_port])
|
183
|
-
end
|
184
|
-
|
185
|
-
def receive(receiver, options)
|
186
|
-
timeout = options[:timeout] || @timeout
|
109
|
+
def create_backend
|
110
|
+
backend = @options[:backend] || :thread
|
187
111
|
|
188
|
-
receive_options = {
|
189
|
-
:timeout => timeout,
|
190
|
-
}
|
191
112
|
begin
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
class Receiver
|
201
|
-
def initialize(options={})
|
202
|
-
host = options[:host] || Socket.gethostname
|
203
|
-
port = options[:port] || 0
|
204
|
-
@socket = TCPServer.new(host, port)
|
205
|
-
@read_ios = [@socket]
|
206
|
-
@client_handlers = {}
|
207
|
-
end
|
208
|
-
|
209
|
-
def close
|
210
|
-
@socket.close
|
211
|
-
@client_handlers.each_key do |client|
|
212
|
-
client.close
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def host
|
217
|
-
@socket.addr[3]
|
218
|
-
end
|
219
|
-
|
220
|
-
def port
|
221
|
-
@socket.addr[1]
|
113
|
+
require "droonga/client/connection/droonga-protocol/#{backend}"
|
114
|
+
rescue LoadError
|
115
|
+
raise UnknownBackendError.new("Droonga protocol",
|
116
|
+
backend,
|
117
|
+
$!.message)
|
222
118
|
end
|
223
119
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
catch do |tag|
|
228
|
-
loop do
|
229
|
-
start = Time.new
|
230
|
-
readable_ios, = IO.select(@read_ios, nil, nil, timeout)
|
231
|
-
break if readable_ios.nil?
|
232
|
-
if timeout
|
233
|
-
timeout -= (Time.now - start)
|
234
|
-
timeout = 0 if timeout < 0
|
235
|
-
end
|
236
|
-
readable_ios.each do |readable_io|
|
237
|
-
on_readable(readable_io) do |object|
|
238
|
-
begin
|
239
|
-
yield(object)
|
240
|
-
rescue LocalJumpError
|
241
|
-
throw(tag)
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
private
|
250
|
-
def on_readable(io)
|
251
|
-
case io
|
252
|
-
when @socket
|
253
|
-
client = @socket.accept
|
254
|
-
@read_ios << client
|
255
|
-
@client_handlers[client] = lambda do
|
256
|
-
unpacker = MessagePack::Unpacker.new
|
257
|
-
loop do
|
258
|
-
readable, = IO.select([client], nil, nil, 0)
|
259
|
-
break unless readable
|
260
|
-
data = client.read_nonblock(BUFFER_SIZE)
|
261
|
-
unpacker.feed_each(data) do |object|
|
262
|
-
yield(object)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
client.close
|
266
|
-
@read_ios.delete(client)
|
267
|
-
@client_handlers.delete(client)
|
268
|
-
end
|
269
|
-
else
|
270
|
-
@client_handlers[io].call
|
271
|
-
end
|
272
|
-
end
|
120
|
+
backend_name = backend.to_s.capitalize
|
121
|
+
backend_class = self.class.const_get(backend_name)
|
122
|
+
backend_class.new(@host, @port, @tag, @options)
|
273
123
|
end
|
274
124
|
end
|
275
125
|
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# Copyright (C) 2014 Droonga Project
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
6
|
+
#
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
10
|
+
# Lesser General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
13
|
+
# License along with this library; if not, write to the Free Software
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
15
|
+
|
16
|
+
require "coolio"
|
17
|
+
require "droonga/message-pack-packer"
|
18
|
+
|
19
|
+
module Droonga
|
20
|
+
class Client
|
21
|
+
module Connection
|
22
|
+
class DroongaProtocol
|
23
|
+
class Coolio
|
24
|
+
class Request
|
25
|
+
def initialize(receiver, id, loop)
|
26
|
+
@receiver = receiver
|
27
|
+
@id = id
|
28
|
+
@loop = loop
|
29
|
+
end
|
30
|
+
|
31
|
+
def wait
|
32
|
+
return if @receiver.received?(@id)
|
33
|
+
until @receiver.received?(@id)
|
34
|
+
@loop.run_once
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class InfiniteRequest
|
40
|
+
def initialize(loop)
|
41
|
+
@loop = loop
|
42
|
+
end
|
43
|
+
|
44
|
+
def wait
|
45
|
+
@loop.run
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Sender < ::Coolio::TCPSocket
|
50
|
+
def initialize(socket)
|
51
|
+
super(socket)
|
52
|
+
end
|
53
|
+
|
54
|
+
def send(tag, data)
|
55
|
+
fluent_message = [tag, Time.now.to_i, data]
|
56
|
+
packed_fluent_message = MessagePackPacker.pack(fluent_message)
|
57
|
+
write(packed_fluent_message)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Receiver < ::Coolio::TCPServer
|
62
|
+
def initialize(*args)
|
63
|
+
super(*args) do |engine|
|
64
|
+
@engines << engine
|
65
|
+
handle_engine(engine)
|
66
|
+
end
|
67
|
+
@requests = {}
|
68
|
+
@engines = []
|
69
|
+
end
|
70
|
+
|
71
|
+
def close
|
72
|
+
super
|
73
|
+
@engines.each do |engine|
|
74
|
+
engine.close
|
75
|
+
end
|
76
|
+
@engines.clear
|
77
|
+
end
|
78
|
+
|
79
|
+
def host
|
80
|
+
@listen_socket.addr[3]
|
81
|
+
end
|
82
|
+
|
83
|
+
def port
|
84
|
+
@listen_socket.addr[1]
|
85
|
+
end
|
86
|
+
|
87
|
+
def droonga_name
|
88
|
+
"#{host}:#{port}/droonga"
|
89
|
+
end
|
90
|
+
|
91
|
+
def register(id, &callback)
|
92
|
+
@requests[id] = {
|
93
|
+
:received => false,
|
94
|
+
:callback => callback,
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def unregister(id)
|
99
|
+
@requests.delete(id)
|
100
|
+
end
|
101
|
+
|
102
|
+
def received?(id)
|
103
|
+
if @requests.key?(id)
|
104
|
+
@requests[id][:received]
|
105
|
+
else
|
106
|
+
true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
def handle_engine(engine)
|
112
|
+
unpacker = MessagePack::Unpacker.new
|
113
|
+
on_read = lambda do |data|
|
114
|
+
unpacker.feed_each(data) do |fluent_message|
|
115
|
+
tag, time, droonga_message = fluent_message
|
116
|
+
id = droonga_message["inReplyTo"]
|
117
|
+
request = @requests[id]
|
118
|
+
next if request.nil?
|
119
|
+
request[:received] = true
|
120
|
+
request[:callback].call(droonga_message)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
engine.on_read do |data|
|
124
|
+
on_read.call(data)
|
125
|
+
end
|
126
|
+
|
127
|
+
on_close = lambda do
|
128
|
+
@engines.delete(engine)
|
129
|
+
end
|
130
|
+
engine.on_close do
|
131
|
+
on_close.call
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def initialize(host, port, tag, options={})
|
137
|
+
@host = host
|
138
|
+
@port = port
|
139
|
+
@tag = tag
|
140
|
+
default_options = {
|
141
|
+
}
|
142
|
+
@options = default_options.merge(options)
|
143
|
+
@loop = options[:loop] || ::Coolio::Loop.default
|
144
|
+
|
145
|
+
@sender = Sender.connect(@host, @port)
|
146
|
+
@sender.attach(@loop)
|
147
|
+
@receiver_host = @options[:receiver_host] || Socket.gethostname
|
148
|
+
@receiver_port = @options[:receiver_port] || 0
|
149
|
+
@receiver = Receiver.new(@receiver_host, @receiver_port)
|
150
|
+
@receiver.attach(@loop)
|
151
|
+
end
|
152
|
+
|
153
|
+
def request(message, options={}, &block)
|
154
|
+
id = message["id"] || generate_id
|
155
|
+
message = message.merge("id" => id,
|
156
|
+
"replyTo" => @receiver.droonga_name)
|
157
|
+
send(message, options)
|
158
|
+
|
159
|
+
sync = block.nil?
|
160
|
+
if sync
|
161
|
+
response = nil
|
162
|
+
block = lambda do |_response|
|
163
|
+
response = _response
|
164
|
+
end
|
165
|
+
end
|
166
|
+
@receiver.register(id) do |response|
|
167
|
+
@receiver.unregister(id)
|
168
|
+
block.call(response)
|
169
|
+
end
|
170
|
+
request = Request.new(@receiver, id, @loop)
|
171
|
+
if sync
|
172
|
+
request.wait
|
173
|
+
response
|
174
|
+
else
|
175
|
+
request
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def subscribe(message, options={}, &block)
|
180
|
+
id = message["id"] || generate_id
|
181
|
+
message = message.merge("id" => id,
|
182
|
+
"from" => @receiver.droonga_name)
|
183
|
+
send(message, options)
|
184
|
+
|
185
|
+
request = InfiniteRequest.new(@loop)
|
186
|
+
sync = block.nil?
|
187
|
+
if sync
|
188
|
+
yielder = nil
|
189
|
+
buffer = []
|
190
|
+
@receiver.register(id) do |response|
|
191
|
+
if yielder
|
192
|
+
while (old_response = buffer.shift)
|
193
|
+
yielder << old_response
|
194
|
+
end
|
195
|
+
yielder << response
|
196
|
+
else
|
197
|
+
buffer << response
|
198
|
+
end
|
199
|
+
end
|
200
|
+
Enumerator.new do |_yielder|
|
201
|
+
yielder = _yielder
|
202
|
+
request.wait
|
203
|
+
end
|
204
|
+
else
|
205
|
+
@receiver.register(id, &block)
|
206
|
+
request
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def send(message, options={}, &block)
|
211
|
+
if message["id"].nil? or message["date"].nil?
|
212
|
+
id = message["id"] || generate_id
|
213
|
+
date = message["date"] || Time.now
|
214
|
+
message = message.merge("id" => id, "date" => date)
|
215
|
+
end
|
216
|
+
@sender.send("#{@tag}.message", message)
|
217
|
+
end
|
218
|
+
|
219
|
+
def close
|
220
|
+
@sender.close
|
221
|
+
@receiver.close
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
def generate_id
|
226
|
+
Time.now.to_f.to_s
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# Copyright (C) 2013-2014 Droonga Project
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
6
|
+
#
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
10
|
+
# Lesser General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
13
|
+
# License along with this library; if not, write to the Free Software
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
15
|
+
|
16
|
+
require "socket"
|
17
|
+
require "thread"
|
18
|
+
require "msgpack"
|
19
|
+
require "fluent-logger"
|
20
|
+
|
21
|
+
module Droonga
|
22
|
+
class Client
|
23
|
+
module Connection
|
24
|
+
class DroongaProtocol
|
25
|
+
class Thread
|
26
|
+
class Request
|
27
|
+
def initialize(thread)
|
28
|
+
@thread = thread
|
29
|
+
end
|
30
|
+
|
31
|
+
def wait
|
32
|
+
@thread.join
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(host, port, tag, options={})
|
37
|
+
@host = host
|
38
|
+
@port = port
|
39
|
+
@tag = tag
|
40
|
+
default_options = {
|
41
|
+
:timeout => 1,
|
42
|
+
}
|
43
|
+
@options = default_options.merge(options)
|
44
|
+
@logger = Fluent::Logger::FluentLogger.new(@tag, @options)
|
45
|
+
@timeout = @options[:timeout]
|
46
|
+
end
|
47
|
+
|
48
|
+
def request(message, options={}, &block)
|
49
|
+
receiver = create_receiver
|
50
|
+
message = message.dup
|
51
|
+
message["replyTo"] = "#{receiver.host}:#{receiver.port}/droonga"
|
52
|
+
send(message, options)
|
53
|
+
|
54
|
+
sync = block.nil?
|
55
|
+
if sync
|
56
|
+
responses = []
|
57
|
+
receive(receiver, options) do |response|
|
58
|
+
responses << response
|
59
|
+
end
|
60
|
+
if responses.size > 1
|
61
|
+
responses
|
62
|
+
else
|
63
|
+
responses.first
|
64
|
+
end
|
65
|
+
else
|
66
|
+
thread = ::Thread.new do
|
67
|
+
receive(receiver, options, &block)
|
68
|
+
end
|
69
|
+
Request.new(thread)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def subscribe(message, options={}, &block)
|
74
|
+
receiver = create_receiver
|
75
|
+
message = message.dup
|
76
|
+
message["from"] = "#{receiver.host}:#{receiver.port}/droonga"
|
77
|
+
send(message, options)
|
78
|
+
|
79
|
+
receive_options = {
|
80
|
+
:timeout => nil,
|
81
|
+
}
|
82
|
+
sync = block.nil?
|
83
|
+
if sync
|
84
|
+
Enumerator.new do |yielder|
|
85
|
+
loop do
|
86
|
+
receiver.receive(receive_options) do |object|
|
87
|
+
yielder << object
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
thread = ::Thread.new do
|
93
|
+
begin
|
94
|
+
loop do
|
95
|
+
receiver.receive(receive_options, &block)
|
96
|
+
end
|
97
|
+
ensure
|
98
|
+
receiver.close
|
99
|
+
end
|
100
|
+
end
|
101
|
+
Request.new(thread)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def send(message, options={}, &block)
|
106
|
+
if message["id"].nil? or message["date"].nil?
|
107
|
+
message = message.merge("id" => Time.now.to_f.to_s,
|
108
|
+
"date" => Time.now)
|
109
|
+
end
|
110
|
+
@logger.post("message", message)
|
111
|
+
end
|
112
|
+
|
113
|
+
def close
|
114
|
+
@logger.close
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
def create_receiver
|
119
|
+
Receiver.new(:host => @options[:receiver_host],
|
120
|
+
:port => @options[:receiver_port])
|
121
|
+
end
|
122
|
+
|
123
|
+
def receive(receiver, options)
|
124
|
+
timeout = options[:timeout] || @timeout
|
125
|
+
|
126
|
+
receive_options = {
|
127
|
+
:timeout => timeout,
|
128
|
+
}
|
129
|
+
begin
|
130
|
+
receiver.receive(receive_options) do |response|
|
131
|
+
yield(response)
|
132
|
+
end
|
133
|
+
ensure
|
134
|
+
receiver.close
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Receiver
|
139
|
+
def initialize(options={})
|
140
|
+
host = options[:host] || Socket.gethostname
|
141
|
+
port = options[:port] || 0
|
142
|
+
@socket = TCPServer.new(host, port)
|
143
|
+
@read_ios = [@socket]
|
144
|
+
@client_handlers = {}
|
145
|
+
end
|
146
|
+
|
147
|
+
def close
|
148
|
+
@socket.close
|
149
|
+
@client_handlers.each_key do |client|
|
150
|
+
client.close
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def host
|
155
|
+
@socket.addr[3]
|
156
|
+
end
|
157
|
+
|
158
|
+
def port
|
159
|
+
@socket.addr[1]
|
160
|
+
end
|
161
|
+
|
162
|
+
BUFFER_SIZE = 8192
|
163
|
+
def receive(options={}, &block)
|
164
|
+
timeout = options[:timeout]
|
165
|
+
catch do |tag|
|
166
|
+
loop do
|
167
|
+
start = Time.new
|
168
|
+
readable_ios, = IO.select(@read_ios, nil, nil, timeout)
|
169
|
+
break if readable_ios.nil?
|
170
|
+
if timeout
|
171
|
+
timeout -= (Time.now - start)
|
172
|
+
timeout = 0 if timeout < 0
|
173
|
+
end
|
174
|
+
readable_ios.each do |readable_io|
|
175
|
+
on_readable(readable_io) do |object|
|
176
|
+
begin
|
177
|
+
yield(object)
|
178
|
+
rescue LocalJumpError
|
179
|
+
throw(tag)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
def on_readable(io)
|
189
|
+
case io
|
190
|
+
when @socket
|
191
|
+
client = @socket.accept
|
192
|
+
@read_ios << client
|
193
|
+
@client_handlers[client] = lambda do
|
194
|
+
unpacker = MessagePack::Unpacker.new
|
195
|
+
loop do
|
196
|
+
readable, = IO.select([client], nil, nil, 0)
|
197
|
+
break unless readable
|
198
|
+
data = client.read_nonblock(BUFFER_SIZE)
|
199
|
+
unpacker.feed_each(data) do |fluent_message|
|
200
|
+
tag, time, droonga_message = fluent_message
|
201
|
+
yield(droonga_message)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
client.close
|
205
|
+
@read_ios.delete(client)
|
206
|
+
@client_handlers.delete(client)
|
207
|
+
end
|
208
|
+
else
|
209
|
+
@client_handlers[io].call
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright (C) 2014 Droonga Project
|
2
|
+
#
|
3
|
+
# This library is free software; you can redistribute it and/or
|
4
|
+
# modify it under the terms of the GNU Lesser General Public
|
5
|
+
# License version 2.1 as published by the Free Software Foundation.
|
6
|
+
#
|
7
|
+
# This library is distributed in the hope that it will be useful,
|
8
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
9
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
10
|
+
# Lesser General Public License for more details.
|
11
|
+
#
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
13
|
+
# License along with this library; if not, write to the Free Software
|
14
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
15
|
+
|
16
|
+
module Droonga
|
17
|
+
class Client
|
18
|
+
module Connection
|
19
|
+
class EmptyRequest
|
20
|
+
def initialize
|
21
|
+
end
|
22
|
+
|
23
|
+
def wait
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -23,6 +23,16 @@ module Droonga
|
|
23
23
|
# The top error class of connection module.
|
24
24
|
class Error < Client::Error
|
25
25
|
end
|
26
|
+
|
27
|
+
class UnknownBackendError < Error
|
28
|
+
attr_reader :protocol
|
29
|
+
attr_reader :backend
|
30
|
+
def initialize(protocol, backend, detail)
|
31
|
+
@protocol = protocol
|
32
|
+
@backend = backend
|
33
|
+
super("Unknown #{@protocol} backend: <#{backend}>: #{detail}")
|
34
|
+
end
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: droonga-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-04-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: msgpack
|
16
|
-
requirement: &
|
16
|
+
requirement: &76464960 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *76464960
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: fluent-logger
|
27
|
-
requirement: &
|
27
|
+
requirement: &76464730 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *76464730
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rack
|
38
|
-
requirement: &
|
38
|
+
requirement: &76464520 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *76464520
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: yajl-ruby
|
49
|
-
requirement: &
|
49
|
+
requirement: &76464310 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,21 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *76464310
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: droonga-message-pack-packer
|
60
|
+
requirement: &76464100 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *76464100
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: bundler
|
60
|
-
requirement: &
|
71
|
+
requirement: &76463850 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ~>
|
@@ -65,10 +76,10 @@ dependencies:
|
|
65
76
|
version: '1.3'
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *76463850
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: rake
|
71
|
-
requirement: &
|
82
|
+
requirement: &76463640 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ! '>='
|
@@ -76,10 +87,10 @@ dependencies:
|
|
76
87
|
version: '0'
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *76463640
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: packnga
|
82
|
-
requirement: &
|
93
|
+
requirement: &76463410 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ! '>='
|
@@ -87,7 +98,7 @@ dependencies:
|
|
87
98
|
version: '0'
|
88
99
|
type: :development
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *76463410
|
91
102
|
description: Droonga client for Ruby
|
92
103
|
email:
|
93
104
|
- droonga@groonga.org
|
@@ -109,6 +120,9 @@ files:
|
|
109
120
|
- droonga-client.gemspec
|
110
121
|
- lib/droonga/client.rb
|
111
122
|
- lib/droonga/client/connection/droonga-protocol.rb
|
123
|
+
- lib/droonga/client/connection/droonga-protocol/coolio.rb
|
124
|
+
- lib/droonga/client/connection/droonga-protocol/thread.rb
|
125
|
+
- lib/droonga/client/connection/empty-request.rb
|
112
126
|
- lib/droonga/client/connection/error.rb
|
113
127
|
- lib/droonga/client/connection/http.rb
|
114
128
|
- lib/droonga/client/error.rb
|