zmqmachine 0.6.0 → 0.7.1
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.
- data/.gitignore +15 -0
- data/AUTHORS.txt +3 -0
- data/History.txt +19 -0
- data/examples/fake_ftp.rb +9 -1
- data/examples/one_handed_ping_pong.rb +2 -1
- data/examples/ping_pong.rb +2 -2
- data/examples/pub_sub.rb +10 -4
- data/examples/pubsub_forwarder.rb +8 -3
- data/examples/throttled_ping_pong.rb +2 -2
- data/lib/zm/configuration.rb +129 -0
- data/lib/zm/device.rb +4 -0
- data/lib/zm/device/configuration.rb +24 -0
- data/lib/zm/{devices → device}/forwarder.rb +48 -46
- data/lib/zm/{devices → device}/queue.rb +63 -44
- data/lib/zm/log_client.rb +2 -2
- data/lib/zm/log_server.rb +68 -0
- data/lib/zm/reactor.rb +42 -29
- data/lib/zm/server.rb +4 -0
- data/lib/zm/server/base.rb +139 -0
- data/lib/zm/server/configuration.rb +53 -0
- data/lib/zm/server/pair.rb +23 -0
- data/lib/zm/server/pub.rb +23 -0
- data/lib/zm/server/pull.rb +24 -0
- data/lib/zm/server/push.rb +23 -0
- data/lib/zm/server/rep.rb +42 -0
- data/lib/zm/server/req.rb +41 -0
- data/lib/zm/server/routing_envelope.rb +26 -0
- data/lib/zm/server/sub.rb +40 -0
- data/lib/zm/sockets.rb +1 -1
- data/lib/zm/sockets/base.rb +3 -12
- data/lib/zm/sockets/envelope_help.rb +49 -0
- data/lib/zm/sockets/pair.rb +0 -1
- data/lib/zm/sockets/pub.rb +0 -1
- data/lib/zm/sockets/rep.rb +45 -0
- data/lib/zm/sockets/req.rb +46 -1
- data/lib/zm/sockets/sub.rb +0 -1
- data/lib/zm/timers.rb +26 -13
- data/lib/zmqmachine.rb +1 -1
- data/version.txt +1 -1
- data/zmqmachine.gemspec +6 -6
- metadata +90 -91
- data/lib/zm/devices.rb +0 -4
- data/lib/zm/sockets/xrep.rb +0 -86
- data/lib/zm/sockets/xreq.rb +0 -86
@@ -35,7 +35,6 @@
|
|
35
35
|
#
|
36
36
|
|
37
37
|
module ZMQMachine
|
38
|
-
|
39
38
|
module Device
|
40
39
|
|
41
40
|
|
@@ -53,102 +52,122 @@ module ZMQMachine
|
|
53
52
|
#
|
54
53
|
# # the queue creates sockets and binds to both given addresses; all messages get
|
55
54
|
# # routed between the two
|
56
|
-
#
|
55
|
+
# config = ZM::Device::Configuration.new
|
56
|
+
# config.reactor = reactor
|
57
|
+
# config.incoming_endpoint = "tcp://192.168.0.100:5050"
|
58
|
+
# config.outgoing_endpoint = "tcp://192.168.0.100:5051"
|
59
|
+
# config.verbose = false
|
60
|
+
# config.linger = 10 # ms
|
61
|
+
# config.hwm = 0
|
62
|
+
# queue = ZM::Device::Queue.new(config)
|
57
63
|
#
|
58
64
|
# # the +client_handler+ internally calls "connect" to the incoming address given above
|
59
|
-
# client = reactor.req_socket
|
60
|
-
# client2 = reactor.req_socket
|
65
|
+
# client = reactor.req_socket(client_handler)
|
66
|
+
# client2 = reactor.req_socket(client_handler)
|
61
67
|
#
|
62
68
|
# # the +server_handler+ internally calls "connect" to the outgoing address given above
|
63
|
-
# server = reactor.rep_socket
|
69
|
+
# server = reactor.rep_socket(server_handler)
|
64
70
|
#
|
65
71
|
class Queue
|
66
72
|
|
67
|
-
class
|
73
|
+
class XReqHandler
|
68
74
|
attr_accessor :socket_out
|
69
75
|
|
70
|
-
def initialize
|
71
|
-
@reactor = reactor
|
76
|
+
def initialize(config, address, direction)
|
77
|
+
@reactor = config.reactor
|
72
78
|
@address = address
|
73
|
-
@verbose =
|
74
|
-
@
|
75
|
-
@
|
79
|
+
@verbose = config.verbose
|
80
|
+
@config = config
|
81
|
+
@direction = direction
|
76
82
|
end
|
77
83
|
|
78
|
-
def on_attach
|
79
|
-
set_options
|
80
|
-
rc = socket.bind
|
84
|
+
def on_attach(socket)
|
85
|
+
set_options(socket)
|
86
|
+
rc = socket.bind(@address)
|
81
87
|
error_check(rc)
|
82
|
-
#FIXME: error handling!
|
83
88
|
end
|
84
89
|
|
85
|
-
def on_writable
|
86
|
-
@reactor.deregister_writable
|
90
|
+
def on_writable(socket)
|
91
|
+
@reactor.deregister_writable(socket)
|
87
92
|
end
|
88
93
|
|
89
|
-
def on_readable
|
90
|
-
|
94
|
+
def on_readable(socket, messages, envelope)
|
95
|
+
all = (envelope + messages)
|
96
|
+
all.each { |msg| @reactor.log(:device, "[Q#{@direction}] [#{msg.copy_out_string}]") } if @verbose
|
91
97
|
|
92
98
|
if @socket_out
|
93
99
|
# FIXME: need to be able to handle EAGAIN/failed send
|
94
|
-
rc = socket_out.send_messages
|
95
|
-
|
100
|
+
rc = socket_out.send_messages(all)
|
101
|
+
all.each { |message| message.close }
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
|
-
if LibZMQ.version2?
|
105
|
+
if ZMQ::LibZMQ.version2?
|
100
106
|
|
101
|
-
def set_options
|
102
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::HWM,
|
103
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER,
|
107
|
+
def set_options(socket)
|
108
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::HWM, @config.hwm))
|
109
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER, @config.linger))
|
104
110
|
end
|
105
111
|
|
106
|
-
elsif LibZMQ.version3?
|
112
|
+
elsif ZMQ::LibZMQ.version3?
|
107
113
|
|
108
|
-
def set_options
|
109
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::SNDHWM,
|
110
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::RCVHWM,
|
111
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER,
|
114
|
+
def set_options(socket)
|
115
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::SNDHWM, @config.hwm))
|
116
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::RCVHWM, @config.hwm))
|
117
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER, @config.linger))
|
112
118
|
end
|
113
119
|
|
114
120
|
end
|
115
121
|
|
116
|
-
def error_check
|
122
|
+
def error_check(rc)
|
117
123
|
if ZMQ::Util.resultcode_ok?(rc)
|
118
124
|
false
|
119
125
|
else
|
120
|
-
|
121
|
-
caller(1).each { |callstack|
|
126
|
+
@reactor.log(:error, "Operation failed, errno [#{ZMQ::Util.errno}] description [#{ZMQ::Util.error_string}]")
|
127
|
+
caller(1).each { |callstack| @reactor.log(:callstack, callstack) }
|
122
128
|
true
|
123
129
|
end
|
124
130
|
end
|
125
131
|
|
126
|
-
end # class
|
132
|
+
end # class XReqHandler
|
133
|
+
|
134
|
+
class XRepHandler < XReqHandler
|
135
|
+
|
136
|
+
def on_readable(socket, messages, envelope)
|
137
|
+
all = envelope + messages
|
138
|
+
all.each { |msg| @reactor.log(:device, "[Q#{@direction}] [#{msg.copy_out_string}]") } if @verbose
|
127
139
|
|
140
|
+
if @socket_out
|
141
|
+
# FIXME: need to be able to handle EAGAIN/failed send
|
142
|
+
rc = socket_out.send_messages(all)
|
143
|
+
all.each { |message| message.close }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
128
147
|
|
129
148
|
# Takes either a properly formatted string that can be converted into a ZM::Address
|
130
149
|
# or takes a ZM::Address directly.
|
131
150
|
#
|
132
151
|
# Routes all messages received by either address to the other address.
|
133
152
|
#
|
134
|
-
def initialize
|
135
|
-
|
136
|
-
|
153
|
+
def initialize(config)
|
154
|
+
@reactor = config.reactor
|
155
|
+
incoming = Address.from_string(config.incoming_endpoint.to_s)
|
156
|
+
outgoing = Address.from_string(config.outgoing_endpoint.to_s)
|
137
157
|
|
138
158
|
# setup the handlers for processing messages
|
139
|
-
@handler_in =
|
140
|
-
@handler_out =
|
159
|
+
@handler_in = XRepHandler.new(config, incoming, :in)
|
160
|
+
@handler_out = XReqHandler.new(config, outgoing, :out)
|
141
161
|
|
142
162
|
# create each socket and pass in the appropriate handler
|
143
|
-
@
|
144
|
-
@
|
163
|
+
@incoming_sock = @reactor.xrep_socket(@handler_in)
|
164
|
+
@outgoing_sock = @reactor.xreq_socket(@handler_out)
|
145
165
|
|
146
166
|
# set each handler's outgoing socket
|
147
|
-
@handler_in.socket_out = @
|
148
|
-
@handler_out.socket_out = @
|
167
|
+
@handler_in.socket_out = @outgoing_sock
|
168
|
+
@handler_out.socket_out = @incoming_sock
|
149
169
|
end
|
150
170
|
end # class Queue
|
151
171
|
|
152
172
|
end # module Device
|
153
|
-
|
154
173
|
end # module ZMQMachine
|
data/lib/zm/log_client.rb
CHANGED
@@ -109,14 +109,14 @@ module ZMQMachine
|
|
109
109
|
@reactor.deregister_writable socket
|
110
110
|
end
|
111
111
|
|
112
|
-
if LibZMQ.version2?
|
112
|
+
if ZMQ::LibZMQ.version2?
|
113
113
|
|
114
114
|
def set_options socket
|
115
115
|
socket.raw_socket.setsockopt ZMQ::HWM, 0
|
116
116
|
socket.raw_socket.setsockopt ZMQ::LINGER, 0
|
117
117
|
end
|
118
118
|
|
119
|
-
elsif LibZMQ.version3?
|
119
|
+
elsif ZMQ::LibZMQ.version3?
|
120
120
|
|
121
121
|
def set_options socket
|
122
122
|
socket.raw_socket.setsockopt ZMQ::SNDHWM, 0
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Chuck Remes
|
4
|
+
# Homepage:: http://github.com/chuckremes/zmqmachine
|
5
|
+
# Date:: 20111101
|
6
|
+
#
|
7
|
+
#----------------------------------------------------------------------------
|
8
|
+
#
|
9
|
+
# Copyright (C) 2011 by Chuck Remes. All Rights Reserved.
|
10
|
+
# Email: cremes at mac dot com
|
11
|
+
#
|
12
|
+
# (The MIT License)
|
13
|
+
#
|
14
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
15
|
+
# a copy of this software and associated documentation files (the
|
16
|
+
# 'Software'), to deal in the Software without restriction, including
|
17
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
18
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
19
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
20
|
+
# the following conditions:
|
21
|
+
#
|
22
|
+
# The above copyright notice and this permission notice shall be
|
23
|
+
# included in all copies or substantial portions of the Software.
|
24
|
+
#
|
25
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
26
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
27
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
28
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
29
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
30
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
31
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
|
+
#
|
33
|
+
#---------------------------------------------------------------------------
|
34
|
+
#
|
35
|
+
#
|
36
|
+
|
37
|
+
module ZMQMachine
|
38
|
+
|
39
|
+
class LogServer
|
40
|
+
include Server::SUB
|
41
|
+
|
42
|
+
def initialize(configuration)
|
43
|
+
configuration.on_read = method(:on_read)
|
44
|
+
super
|
45
|
+
|
46
|
+
@file = configuration.extra[:file] || STDOUT
|
47
|
+
end
|
48
|
+
|
49
|
+
# Writes all messages to the file.
|
50
|
+
#
|
51
|
+
def on_read socket, messages
|
52
|
+
string = ''
|
53
|
+
messages.each_with_index do |message, index|
|
54
|
+
string << '|' if index > 0
|
55
|
+
string << "#{message.copy_out_string}"
|
56
|
+
end
|
57
|
+
|
58
|
+
@file.print "#{string}\n"
|
59
|
+
@file.flush
|
60
|
+
end
|
61
|
+
|
62
|
+
def write messages
|
63
|
+
# no op
|
64
|
+
end
|
65
|
+
|
66
|
+
end # class LogServer
|
67
|
+
|
68
|
+
end
|
data/lib/zm/reactor.rb
CHANGED
@@ -39,46 +39,58 @@ module ZMQMachine
|
|
39
39
|
class Reactor
|
40
40
|
attr_reader :name, :context, :logger, :exception_handler
|
41
41
|
|
42
|
+
# Takes a ZMQ::Configuration instance to initialize itself.
|
43
|
+
#
|
42
44
|
# +name+ provides a name for this reactor instance. It's unused
|
43
45
|
# at present but may be used in the future for allowing multiple
|
44
|
-
# reactors to communicate amongst each other.
|
46
|
+
# reactors to communicate amongst each other. Defaults to 'unnamed'
|
47
|
+
# if it isn't set.
|
45
48
|
#
|
46
49
|
# +poll_interval+ is the number of milliseconds to block while
|
47
|
-
# waiting for new 0mq socket events; default is 10
|
50
|
+
# waiting for new 0mq socket events; default is 10 ms.
|
48
51
|
#
|
49
|
-
# +
|
50
|
-
# hash is provided, the value for :zeromq_context should be a
|
52
|
+
# +context+ should be a
|
51
53
|
# 0mq context as created by ZMQ::Context.new. The purpose of
|
52
54
|
# providing a context to the reactor is so that multiple
|
53
55
|
# reactors can share a single context. Doing so allows for sockets
|
54
56
|
# within each reactor to communicate with each other via an
|
55
57
|
# :inproc transport (:inproc is misnamed, it should be :incontext).
|
56
58
|
# By not supplying this hash, the reactor will create and use
|
57
|
-
# its own 0mq context.
|
59
|
+
# its own 0mq context. Default is nil.
|
58
60
|
#
|
59
|
-
# +
|
61
|
+
# +log_endpoint+ is a
|
60
62
|
# a transport string for an endpoint that a logger client may connect
|
61
63
|
# to for publishing log messages. when this key is defined, the
|
62
64
|
# client is automatically created and connected to the indicated
|
63
|
-
# endpoint.
|
64
|
-
#
|
65
|
-
#
|
66
|
-
# handler should respond to #call and take a single argument.
|
67
|
-
#
|
68
|
-
|
69
|
-
|
65
|
+
# endpoint. Default is nil.
|
66
|
+
#
|
67
|
+
# +exception_handler+ is called for all exceptions. The
|
68
|
+
# handler should respond to #call and take a single argument. Default
|
69
|
+
# is to just raise the exception and exit.
|
70
|
+
#
|
71
|
+
# config = ZM::Configuration.new
|
72
|
+
# config.context = master_context
|
73
|
+
# config.log_endpoint = endpoint
|
74
|
+
# config.name = :test_rig
|
75
|
+
# config.poll_interval = 100 # defaults to 10 if unset
|
76
|
+
# Reactor.new(config).run do |reactor|
|
77
|
+
# reactor.oneshot_timer(50) { print("At least 50ms have elapsed\n")}
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
def initialize configuration = nil
|
81
|
+
configuration ||= Configuration.new
|
82
|
+
@name = configuration.name || 'unnamed'
|
70
83
|
@running = false
|
71
84
|
@thread = nil
|
72
|
-
@poll_interval = determine_interval
|
73
|
-
@timers = ZMQMachine::Timers.new
|
85
|
+
@poll_interval = determine_interval(configuration.poll_interval || 10)
|
74
86
|
|
75
87
|
@proc_queue = []
|
76
88
|
@proc_queue_mutex = Mutex.new
|
77
89
|
|
78
90
|
# could raise if it fails to allocate a Context
|
79
|
-
@context = if
|
91
|
+
@context = if configuration.context
|
80
92
|
@shared_context = true
|
81
|
-
|
93
|
+
configuration.context
|
82
94
|
else
|
83
95
|
@shared_context = false
|
84
96
|
ZMQ::Context.new
|
@@ -89,14 +101,13 @@ module ZMQMachine
|
|
89
101
|
@raw_to_socket = {}
|
90
102
|
Thread.abort_on_exception = true
|
91
103
|
|
92
|
-
if
|
93
|
-
@logger = LogClient.new self,
|
104
|
+
if configuration.log_endpoint
|
105
|
+
@logger = LogClient.new self, configuration.log_endpoint
|
94
106
|
@logging_enabled = true
|
95
107
|
end
|
96
108
|
|
97
|
-
if
|
98
|
-
|
99
|
-
end
|
109
|
+
@exception_handler = configuration.exception_handler if configuration.exception_handler
|
110
|
+
@timers = ZMQMachine::Timers.new(@exception_handler)
|
100
111
|
end
|
101
112
|
|
102
113
|
def shared_context?
|
@@ -249,6 +260,7 @@ module ZMQMachine
|
|
249
260
|
def xreq_socket handler_instance
|
250
261
|
create_socket handler_instance, ZMQMachine::Socket::XReq
|
251
262
|
end
|
263
|
+
alias :dealer_socket :xreq_socket
|
252
264
|
|
253
265
|
# Creates a XREP socket and attaches +handler_instance+ to the
|
254
266
|
# resulting socket. Should only be paired with one other
|
@@ -264,6 +276,7 @@ module ZMQMachine
|
|
264
276
|
def xrep_socket handler_instance
|
265
277
|
create_socket handler_instance, ZMQMachine::Socket::XRep
|
266
278
|
end
|
279
|
+
alias :router_socket :xrep_socket
|
267
280
|
|
268
281
|
# Creates a PAIR socket and attaches +handler_instance+ to the
|
269
282
|
# resulting socket. Works only with other #pair_socket instances
|
@@ -437,16 +450,16 @@ module ZMQMachine
|
|
437
450
|
end
|
438
451
|
|
439
452
|
# Publishes log messages to an existing transport passed in to the Reactor
|
440
|
-
# constructor using the :
|
453
|
+
# constructor using the :log_endpoint key.
|
441
454
|
#
|
442
|
-
# Reactor.new :
|
455
|
+
# Reactor.new :log_endpoint => 'inproc://reactor_log'
|
443
456
|
#
|
444
457
|
# +level+ parameter refers to a key to indicate severity level, e.g. :warn,
|
445
458
|
# :debug, level0, level9, etc.
|
446
459
|
#
|
447
460
|
# +message+ is a plain string that will be written out in its entirety.
|
448
461
|
#
|
449
|
-
# When no :
|
462
|
+
# When no :log_endpoint was defined when creating the Reactor, all calls
|
450
463
|
# just discard the messages.
|
451
464
|
#
|
452
465
|
# reactor.log(:info, "some message")
|
@@ -518,11 +531,11 @@ module ZMQMachine
|
|
518
531
|
sleep(@poll_interval / 1000.0)
|
519
532
|
else
|
520
533
|
rc = @poller.poll @poll_interval
|
521
|
-
end
|
522
534
|
|
523
|
-
|
524
|
-
|
525
|
-
|
535
|
+
if ZMQ::Util.resultcode_ok?(rc)
|
536
|
+
@poller.readables.each { |sock| @raw_to_socket[sock].resume_read }
|
537
|
+
@poller.writables.each { |sock| @raw_to_socket[sock].resume_write }
|
538
|
+
end
|
526
539
|
end
|
527
540
|
|
528
541
|
rc
|
data/lib/zm/server.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module Base
|
7
|
+
def initialize configuration
|
8
|
+
@reactor = configuration.reactor
|
9
|
+
@configuration = configuration
|
10
|
+
|
11
|
+
@on_read = @configuration.on_read
|
12
|
+
allocate_socket
|
13
|
+
|
14
|
+
@message_queue = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def shutdown
|
18
|
+
@reactor.log :debug, "#{self.class}#shutdown_socket, closing reactor socket"
|
19
|
+
@on_read = nil
|
20
|
+
@reactor.close_socket @socket
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_attach socket
|
24
|
+
# socket options *must* be set before we bind/connect otherwise they are ignored
|
25
|
+
set_options socket
|
26
|
+
rc = -1
|
27
|
+
|
28
|
+
if @configuration.bind
|
29
|
+
rc = socket.bind @configuration.endpoint
|
30
|
+
@reactor.log :debug, "#{self.class}#on_attach, bind rc [#{rc}], endpoint #{@configuration.endpoint}"
|
31
|
+
raise "#{self.class}#on_attach, failed to bind to endpoint [#{@configuration.endpoint}]" unless ZMQ::Util.resultcode_ok?(rc)
|
32
|
+
elsif @configuration.connect
|
33
|
+
rc = socket.connect @configuration.endpoint
|
34
|
+
@reactor.log :debug, "#{self.class}#on_attach, connect rc [#{rc}], endpoint #{@configuration.endpoint}"
|
35
|
+
raise "#{self.class}#on_attach, failed to connect to endpoint [#{@configuration.endpoint}]" unless ZMQ::Util.resultcode_ok?(rc)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
register_for_events socket
|
40
|
+
end
|
41
|
+
|
42
|
+
# Takes an array of ZM::Message instances and writes them out to the socket. If any
|
43
|
+
# socket write fails, the message is saved. We will attempt to write it again in
|
44
|
+
# 10 milliseconds or when another message array is sent, whichever comes first.
|
45
|
+
#
|
46
|
+
# All messages passed here are guaranteed to be written in the *order they were
|
47
|
+
# received*.
|
48
|
+
#
|
49
|
+
def write messages, verbose = false
|
50
|
+
@verbose = verbose
|
51
|
+
@message_queue << messages
|
52
|
+
write_queue_to_socket
|
53
|
+
end
|
54
|
+
|
55
|
+
# Prints each message when global debugging is enabled.
|
56
|
+
#
|
57
|
+
# Forwards +messages+ on to the :on_read callback given in the constructor.
|
58
|
+
#
|
59
|
+
def on_readable socket, messages
|
60
|
+
@on_read.call socket, messages
|
61
|
+
close_messages messages
|
62
|
+
end
|
63
|
+
|
64
|
+
# Just deregisters from receiving any further write *events*
|
65
|
+
#
|
66
|
+
def on_writable socket
|
67
|
+
#@reactor.log :debug, "#{self.class}#on_writable, deregister for writes on sid [#{@session_id}]"
|
68
|
+
@reactor.deregister_writable socket
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_readable_error socket, return_code
|
72
|
+
STDERR.puts "#{self.class}#on_readable_error, rc [#{return_code}], errno [#{ZMQ::Util.errno}], description [#{ZMQ::Util.error_string}], sock #{socket.inspect}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def on_writable_error socket, return_code
|
76
|
+
STDERR.puts "#{self.class}#on_writable_error, rc [#{return_code}], errno [#{ZMQ::Util.errno}], description [#{ZMQ::Util.error_string}], sock #{socket.inspect}"
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
|
83
|
+
def register_for_events socket
|
84
|
+
@reactor.register_readable socket
|
85
|
+
@reactor.deregister_writable socket
|
86
|
+
end
|
87
|
+
|
88
|
+
if ZMQ::LibZMQ.version2?
|
89
|
+
|
90
|
+
def set_options socket
|
91
|
+
socket.raw_socket.setsockopt ZMQ::HWM, (@configuration.hwm || 0)
|
92
|
+
socket.raw_socket.setsockopt ZMQ::LINGER, (@configuration.linger || 1)
|
93
|
+
end
|
94
|
+
|
95
|
+
elsif ZMQ::LibZMQ.version3?
|
96
|
+
|
97
|
+
def set_options socket
|
98
|
+
socket.raw_socket.setsockopt ZMQ::RCVHWM, (@configuration.hwm || 0)
|
99
|
+
socket.raw_socket.setsockopt ZMQ::SNDHWM, (@configuration.hwm || 0)
|
100
|
+
socket.raw_socket.setsockopt ZMQ::LINGER, (@configuration.linger || 1)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_queue_to_socket
|
106
|
+
until @message_queue.empty?
|
107
|
+
messages = get_next_message_array
|
108
|
+
|
109
|
+
rc = @socket.send_messages messages
|
110
|
+
|
111
|
+
if ZMQ::Util.resultcode_ok?(rc) # succeeded, so remove the message from the queue
|
112
|
+
@message_queue.shift
|
113
|
+
close_messages messages
|
114
|
+
elsif ZMQ::Util.errno == ZMQ::EAGAIN
|
115
|
+
# schedule another write attempt in 10 ms; break out of the loop
|
116
|
+
@reactor.log :debug, "#{self.class}#write_queue_to_socket, failed to write messages; scheduling next attempt"
|
117
|
+
@reactor.oneshot_timer 10, method(:write_queue_to_socket)
|
118
|
+
break
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_next_message_array
|
124
|
+
messages = @message_queue.at(0)
|
125
|
+
messages.each { |message| @reactor.log :write, message.copy_out_string } if @verbose
|
126
|
+
messages
|
127
|
+
end
|
128
|
+
|
129
|
+
def close_messages messages
|
130
|
+
messages.each { |message| message.close }
|
131
|
+
end
|
132
|
+
|
133
|
+
def allocate_socket() nil; end
|
134
|
+
|
135
|
+
end # module Base
|
136
|
+
|
137
|
+
end # module Server
|
138
|
+
|
139
|
+
end # ZMQMachine
|