zmqmachine 0.6.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|