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
data/.gitignore
ADDED
data/AUTHORS.txt
ADDED
data/History.txt
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
== 0.7.1 / 2011-11-30
|
2
|
+
* Updated the Devices to use a Device::Configuration instance
|
3
|
+
for configuration rather than that long method signature.
|
4
|
+
Makes all components conform to this new configuration
|
5
|
+
mechanism consistently.
|
6
|
+
|
7
|
+
== 0.7.0 / 2011-10-28
|
8
|
+
* Created a class for holding Reactor and Server configurations.
|
9
|
+
This is much nicer than passing in individual args or a hash.
|
10
|
+
|
11
|
+
* Added the ZM::Servers module to make building servers a little
|
12
|
+
easier. The biggest improvement is for making servers that
|
13
|
+
utilize XREP/ROUTER sockets since the module handles the
|
14
|
+
splitting of the routing envelope messages from the body.
|
15
|
+
|
16
|
+
* Fixed a bug where a timer that raises an exception prevented
|
17
|
+
other periodical timers from renewing. Thanks to Tim
|
18
|
+
Carey-Smith for the bug report!
|
19
|
+
|
1
20
|
== 0.6.0 / 2011-10-04
|
2
21
|
* Compatibility with ffi-rzmq 0.9.0 and added some conditional
|
3
22
|
logic to support 0mq 2.1.x and 3.x APIs.
|
data/examples/fake_ftp.rb
CHANGED
@@ -93,6 +93,10 @@ class FTPControlClient
|
|
93
93
|
|
94
94
|
@data_client.should_expect reply['total_chunks']
|
95
95
|
end
|
96
|
+
|
97
|
+
def on_readable_error socket, error
|
98
|
+
puts "on_readable_error, error [#{error}], descr [#{ZMQ::Util.error_string}]"
|
99
|
+
end
|
96
100
|
|
97
101
|
def get filename, &blk
|
98
102
|
sub_address = ZM::Address.new @address.host, 5556, @address.transport
|
@@ -204,6 +208,10 @@ class FTPControlServer
|
|
204
208
|
@pub_handler = nil
|
205
209
|
end
|
206
210
|
end
|
211
|
+
|
212
|
+
def on_readable_error socket, error
|
213
|
+
puts "on_readable_error, error [#{error}], descr [#{ZMQ::Util.error_string}]"
|
214
|
+
end
|
207
215
|
|
208
216
|
def on_writable socket
|
209
217
|
puts "#{self.class.name}#on_writable ERROR, should never be called"
|
@@ -223,7 +231,7 @@ end
|
|
223
231
|
|
224
232
|
|
225
233
|
# Run both handlers within the same reactor context
|
226
|
-
ctx1 = ZM::Reactor.new
|
234
|
+
ctx1 = ZM::Reactor.new.run do |context|
|
227
235
|
|
228
236
|
@request_server = FTPControlServer.new context, server_address
|
229
237
|
context.rep_socket @request_server
|
@@ -29,6 +29,7 @@ class PingPongHandler
|
|
29
29
|
when :request
|
30
30
|
rc = socket.connect address
|
31
31
|
@context.register_readable socket
|
32
|
+
@context.register_writable socket
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
@@ -57,7 +58,7 @@ end
|
|
57
58
|
|
58
59
|
handler = nil
|
59
60
|
# Run both handlers within the same reactor context
|
60
|
-
ctx1 = ZM::Reactor.new
|
61
|
+
ctx1 = ZM::Reactor.new.run do |context|
|
61
62
|
handler = PingPongHandler.new context
|
62
63
|
|
63
64
|
context.rep_socket handler
|
data/examples/ping_pong.rb
CHANGED
@@ -60,7 +60,7 @@ class PingHandler
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# Run both handlers within the same reactor context
|
63
|
-
ctx1 = ZM::Reactor.new
|
63
|
+
ctx1 = ZM::Reactor.new.run do |context|
|
64
64
|
@pong_handler = PongHandler.new context
|
65
65
|
context.rep_socket @pong_handler
|
66
66
|
|
@@ -76,7 +76,7 @@ end
|
|
76
76
|
|
77
77
|
# Or, run each handler in separate contexts each with its
|
78
78
|
# own thread.
|
79
|
-
#ctx2 = ZM::Reactor.new
|
79
|
+
#ctx2 = ZM::Reactor.new.run do |context|
|
80
80
|
# @ping_handler = PingHandler.new context
|
81
81
|
# context.req_socket @ping_handler
|
82
82
|
#end
|
data/examples/pub_sub.rb
CHANGED
@@ -79,8 +79,14 @@ end
|
|
79
79
|
# handler is only getting instantiated and run in one reactor at a time. The subscriber
|
80
80
|
# handlers can be instantiated multiple times in each reactor if you so choose.
|
81
81
|
|
82
|
+
configuration = ZM::Configuration.new do
|
83
|
+
name 'publisher reactor'
|
84
|
+
poll_interval 3
|
85
|
+
exception_handler Proc.new { |exc| raise(exc) }
|
86
|
+
end
|
87
|
+
|
82
88
|
# Run all handlers within the same reactor context
|
83
|
-
ctx1 = ZM::Reactor.new(
|
89
|
+
ctx1 = ZM::Reactor.new(configuration).run do |context|
|
84
90
|
@pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
|
85
91
|
context.pub_socket @pub1_handler
|
86
92
|
|
@@ -105,7 +111,7 @@ end
|
|
105
111
|
|
106
112
|
# Or, run each handler in separate contexts each with its
|
107
113
|
# own thread.
|
108
|
-
ctx2 = ZM::Reactor.new
|
114
|
+
ctx2 = ZM::Reactor.new.run do |context|
|
109
115
|
# @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
|
110
116
|
# context.pub_socket @pub1_handler
|
111
117
|
|
@@ -128,7 +134,7 @@ ctx2 = ZM::Reactor.new(:B).run do |context|
|
|
128
134
|
# context.sub_socket @sub5_handler
|
129
135
|
end
|
130
136
|
|
131
|
-
ctx3 = ZM::Reactor.new
|
137
|
+
ctx3 = ZM::Reactor.new.run do |context|
|
132
138
|
# @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
|
133
139
|
# context.pub_socket @pub1_handler
|
134
140
|
#
|
@@ -151,7 +157,7 @@ ctx3 = ZM::Reactor.new(:C).run do |context|
|
|
151
157
|
# context.sub_socket @sub5_handler
|
152
158
|
end
|
153
159
|
|
154
|
-
ctx4 = ZM::Reactor.new
|
160
|
+
ctx4 = ZM::Reactor.new.run do |context|
|
155
161
|
# @pub1_handler = PublisherHandler.new context, 5555, ['futures.us.es.m.10', 'futures.us.es.u.10']
|
156
162
|
# context.pub_socket @pub1_handler
|
157
163
|
#
|
@@ -78,17 +78,22 @@ sleep_time = 10
|
|
78
78
|
# Run the forwarder device in a separate context. *Could* be run from
|
79
79
|
# the same context as the publishers and subscribers too.
|
80
80
|
#
|
81
|
-
ctx1 = ZM::Reactor.new
|
81
|
+
ctx1 = ZM::Reactor.new.run do |context|
|
82
82
|
incoming = ZM::Address.new '127.0.0.1', 5555, :tcp
|
83
83
|
outgoing = "tcp://127.0.0.1:5556"
|
84
|
+
|
85
|
+
config = ZM::Device::Configuration.new
|
86
|
+
config.reactor = context
|
87
|
+
config.incoming_endpoint = incoming
|
88
|
+
config.outgoing_endpoint = outgoing
|
84
89
|
|
85
|
-
forwarder = ZM::Device::Forwarder.new
|
90
|
+
forwarder = ZM::Device::Forwarder.new(config)
|
86
91
|
puts "forwarder started"
|
87
92
|
end
|
88
93
|
|
89
94
|
# Or, run each handler in separate contexts each with its
|
90
95
|
# own thread.
|
91
|
-
ctx2 = ZM::Reactor.new
|
96
|
+
ctx2 = ZM::Reactor.new.run do |context|
|
92
97
|
# start the publishers and subscribers after a 1 sec delay; give time
|
93
98
|
# to the forwarder device to start up and get ready
|
94
99
|
context.oneshot_timer(1000) do
|
@@ -75,7 +75,7 @@ end
|
|
75
75
|
|
76
76
|
|
77
77
|
# Run both handlers within the same reactor context
|
78
|
-
ctx1 = ZM::Reactor.new
|
78
|
+
ctx1 = ZM::Reactor.new.run do |context|
|
79
79
|
@pong_handler = PongHandler.new context
|
80
80
|
context.pair_socket @pong_handler
|
81
81
|
|
@@ -87,7 +87,7 @@ end
|
|
87
87
|
|
88
88
|
# Or, run each handler in separate contexts each with its
|
89
89
|
# own thread.
|
90
|
-
ctx2 = ZM::Reactor.new
|
90
|
+
ctx2 = ZM::Reactor.new.run do |context|
|
91
91
|
@ping_handler = PingHandler.new context
|
92
92
|
context.pair_socket @ping_handler
|
93
93
|
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module ZMQMachine
|
4
|
+
module ConfigClassMaker
|
5
|
+
module MethodMaker
|
6
|
+
|
7
|
+
# Helper to create some accessor methods. We have a standard one where it returns
|
8
|
+
# the value with no arg, or sets the value with an arg. Then we create a second
|
9
|
+
# method with the explicit '=' on it to allow directly setting the value.
|
10
|
+
#
|
11
|
+
# This let's us do nice things like eval a block and set the instance vars.
|
12
|
+
# e.g.
|
13
|
+
# SomeClass.new do
|
14
|
+
# field1 'set to this string'
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# or
|
18
|
+
#
|
19
|
+
# some_class = SomeClass.new
|
20
|
+
# some_class.field1 = 'set to this string'
|
21
|
+
# puts some_class.field1 # => set to this string
|
22
|
+
#
|
23
|
+
# or
|
24
|
+
#
|
25
|
+
# some_class = SomeClass.new
|
26
|
+
# some_class.field1('set to this string')
|
27
|
+
# puts some_class.field1 # => set to this string
|
28
|
+
#
|
29
|
+
def self.create_accessors(mod, fields)
|
30
|
+
fields.each do |field_name|
|
31
|
+
code = <<-code
|
32
|
+
def #{ field_name } (value = nil)
|
33
|
+
if value
|
34
|
+
@#{field_name} = value
|
35
|
+
else
|
36
|
+
@#{field_name}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def #{ field_name }=(value)
|
41
|
+
@#{field_name} = value
|
42
|
+
end
|
43
|
+
code
|
44
|
+
|
45
|
+
mod.class_eval code
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end # module MethodMaker
|
50
|
+
|
51
|
+
# Dynamically generates Configuration classes. It can also create subclasses.
|
52
|
+
# Allows us to easily build subclasses of Configuration within the library. This
|
53
|
+
# functionality is *also* provided for users of this library to create their
|
54
|
+
# own Configuration classes when writing client/server programs. All of the
|
55
|
+
# inheritance is taken care of.
|
56
|
+
#
|
57
|
+
# +klass_name+ - should usually be 'Configuration'
|
58
|
+
# +fields+ - an array of strings corresponding to the accessor names
|
59
|
+
# +parent+ - the parent of this subclass (Object at the top level)
|
60
|
+
# +mod+ - the module under which this subclass should be placed
|
61
|
+
#
|
62
|
+
# module ZMQMachine
|
63
|
+
# ZMQMachine::ConfigClassMaker.create_class('Configuration', %w( one two three), Object, ZMQMachine)
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# OR for a subclass
|
67
|
+
#
|
68
|
+
# module ZMQMachine
|
69
|
+
# module Server
|
70
|
+
# ZMQMachine::ConfigClassMaker.create_class('Configuration', %w( one two three), ZMQMachine::Configuration, ZMQMachine::Server)
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
def self.create_class(klass_name, fields, parent, mod)
|
75
|
+
# the "here doc" usage here confuses the syntax beautifier so the indentation
|
76
|
+
# is wrong
|
77
|
+
klass = <<-KLASS
|
78
|
+
#{klass_name} = Class.new(#{parent}) do
|
79
|
+
|
80
|
+
Fields = #{fields.inspect}
|
81
|
+
|
82
|
+
# Creates a Configuration object from another object that conforms
|
83
|
+
# to the Configuration protocol.
|
84
|
+
#
|
85
|
+
def self.create_from(other_config)
|
86
|
+
config = new
|
87
|
+
Fields.each do |name|
|
88
|
+
config.send(name, other_config.send(name.to_sym)) if config.respond_to?(name.to_sym)
|
89
|
+
end
|
90
|
+
config
|
91
|
+
end
|
92
|
+
|
93
|
+
def initialize(&blk)
|
94
|
+
instance_eval(&blk) if block_given?
|
95
|
+
end
|
96
|
+
|
97
|
+
ZMQMachine::ConfigClassMaker::MethodMaker.create_accessors(self, Fields)
|
98
|
+
end
|
99
|
+
KLASS
|
100
|
+
|
101
|
+
mod.module_eval(klass)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
module ZMQMachine
|
107
|
+
|
108
|
+
ZMQMachine::ConfigClassMaker.create_class('Configuration', %w( name poll_interval context log_endpoint exception_handler ), Object, ZMQMachine)
|
109
|
+
end # ZMQMachine
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
# TEST
|
114
|
+
if $0 == __FILE__
|
115
|
+
ZMQMachine::ConfigClassMaker.create_class('Configuration', %w( name context log_endpoint exception_handler ), Object, ZMQMachine)
|
116
|
+
|
117
|
+
p (ZMQMachine::Configuration.methods - Object.methods).sort
|
118
|
+
puts "\n\n"
|
119
|
+
p (ZMQMachine::Configuration.new.methods - Object.new.methods).sort
|
120
|
+
|
121
|
+
module ZMQMachine
|
122
|
+
module Server
|
123
|
+
ZMQMachine::ConfigClassMaker.create_class('Configuration', %w( bind connect endpoint ), ZMQMachine::Configuration, ZMQMachine::Server)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
puts "\n\n"
|
128
|
+
p (ZMQMachine::Server::Configuration.new.methods - Object.new.methods).sort
|
129
|
+
end
|
data/lib/zm/device.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
module Device
|
4
|
+
ZMQMachine::ConfigClassMaker.create_class('Configuration',
|
5
|
+
%w( reactor incoming_endpoint outgoing_endpoint topic hwm linger verbose ),
|
6
|
+
ZMQMachine::Configuration,
|
7
|
+
ZMQMachine::Device)
|
8
|
+
|
9
|
+
class Configuration
|
10
|
+
|
11
|
+
def initialize(&blk)
|
12
|
+
instance_eval(&blk) if block_given?
|
13
|
+
|
14
|
+
# set defaults
|
15
|
+
self.verbose ||= false
|
16
|
+
self.hwm ||= 1
|
17
|
+
self.linger ||= 0
|
18
|
+
self.topic ||= ''
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -35,10 +35,8 @@
|
|
35
35
|
#
|
36
36
|
|
37
37
|
module ZMQMachine
|
38
|
-
|
39
38
|
module Device
|
40
39
|
|
41
|
-
|
42
40
|
# Used in conjunction with PUB/SUB sockets to allow multiple publishers to
|
43
41
|
# all publish to the same "bus."
|
44
42
|
#
|
@@ -51,108 +49,112 @@ module ZMQMachine
|
|
51
49
|
#
|
52
50
|
# # the queue creates sockets and binds to both given addresses; all messages get
|
53
51
|
# # republished from +incoming+ to +outgoing+
|
54
|
-
#
|
52
|
+
# config = ZM::Device::Configuration.new
|
53
|
+
# config.reactor = reactor
|
54
|
+
# config.incoming_endpoint = "tcp://192.168.0.100:5050"
|
55
|
+
# config.outgoing_endpoint = "tcp://192.168.0.100:5051"
|
56
|
+
# config.verbose = false
|
57
|
+
# config.linger = 10 # ms
|
58
|
+
# config.hwm = 0
|
59
|
+
# config.topic = '' # get everything
|
60
|
+
# forwarder = ZM::Device::Forwarder.new(config)
|
55
61
|
#
|
56
62
|
# # the +pub_handler+ internally calls "connect" to the incoming address given above
|
57
|
-
# pub1 = reactor.pub_socket
|
58
|
-
# pub2 = reactor.pub_socket
|
63
|
+
# pub1 = reactor.pub_socket(pub_handler)
|
64
|
+
# pub2 = reactor.pub_socket(pub_handler)
|
59
65
|
#
|
60
66
|
# # the +sub_handler+ internally calls "connect" to the outgoing address given above
|
61
|
-
# subscriber = reactor.sub_socket
|
67
|
+
# subscriber = reactor.sub_socket(sub_handler)
|
62
68
|
#
|
63
69
|
class Forwarder
|
64
70
|
|
65
71
|
class Handler
|
66
72
|
attr_accessor :socket_out
|
67
73
|
|
68
|
-
def initialize
|
69
|
-
@reactor = reactor
|
74
|
+
def initialize(config, address)
|
75
|
+
@reactor = config.reactor
|
70
76
|
@address = address
|
71
|
-
@verbose =
|
72
|
-
@
|
77
|
+
@verbose = config.verbose
|
78
|
+
@config = config
|
73
79
|
|
74
80
|
@messages = []
|
75
81
|
end
|
76
82
|
|
77
|
-
def on_attach
|
78
|
-
set_options
|
79
|
-
rc = socket.bind
|
83
|
+
def on_attach(socket)
|
84
|
+
set_options(socket)
|
85
|
+
rc = socket.bind(@address)
|
80
86
|
error_check(rc)
|
81
|
-
|
87
|
+
|
82
88
|
error_check(socket.subscribe_all) if :sub == socket.kind
|
83
89
|
end
|
84
90
|
|
85
|
-
def on_writable
|
86
|
-
@reactor.deregister_writable
|
91
|
+
def on_writable(socket)
|
92
|
+
@reactor.deregister_writable(socket)
|
87
93
|
end
|
88
94
|
|
89
|
-
def on_readable
|
95
|
+
def on_readable(socket, messages)
|
90
96
|
messages.each { |msg| @reactor.log(:device, "[fwd] [#{msg.copy_out_string}]") } if @verbose
|
91
97
|
|
92
98
|
if @socket_out
|
93
|
-
rc = socket_out.send_messages
|
99
|
+
rc = socket_out.send_messages(messages)
|
94
100
|
error_check(rc)
|
95
101
|
messages.each { |message| message.close }
|
96
102
|
end
|
97
103
|
end
|
98
104
|
|
99
|
-
def on_readable_error
|
100
|
-
|
105
|
+
def on_readable_error(socket, return_code)
|
106
|
+
@reactor.log(:error, "#{self.class}#on_readable_error, rc [#{return_code}], errno [#{ZMQ::Util.errno}], descr [#{ZMQ::Util.error_string}]")
|
101
107
|
end
|
102
108
|
|
103
|
-
if LibZMQ.version2?
|
109
|
+
if ZMQ::LibZMQ.version2?
|
104
110
|
|
105
|
-
def set_options
|
106
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::HWM,
|
107
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER,
|
111
|
+
def set_options(socket)
|
112
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::HWM, @config.hwm))
|
113
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER, @config.linger))
|
108
114
|
end
|
109
115
|
|
110
|
-
elsif LibZMQ.version3?
|
116
|
+
elsif ZMQ::LibZMQ.version3?
|
111
117
|
|
112
|
-
def set_options
|
113
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::SNDHWM,
|
114
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::RCVHWM,
|
115
|
-
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER,
|
118
|
+
def set_options(socket)
|
119
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::SNDHWM, @config.hwm))
|
120
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::RCVHWM, @config.hwm))
|
121
|
+
error_check(socket.raw_socket.setsockopt(ZMQ::LINGER, @config.linger))
|
116
122
|
end
|
117
123
|
|
118
124
|
end
|
119
125
|
|
120
|
-
def error_check
|
126
|
+
def error_check(rc)
|
121
127
|
if ZMQ::Util.resultcode_ok?(rc)
|
122
128
|
false
|
123
129
|
else
|
124
|
-
|
125
|
-
caller(1).each { |callstack|
|
130
|
+
@reactor.log(:error, "Operation failed, errno [#{ZMQ::Util.errno}] description [#{ZMQ::Util.error_string}]")
|
131
|
+
caller(1).each { |callstack| @reactor.log(:callstack, callstack) }
|
126
132
|
true
|
127
133
|
end
|
128
134
|
end
|
129
|
-
|
130
135
|
end # class Handler
|
131
136
|
|
132
137
|
|
133
|
-
# Takes either a properly formatted string that can be converted into a ZM::Address
|
134
|
-
# or takes a ZM::Address directly.
|
135
|
-
#
|
136
138
|
# Forwards all messages received by the +incoming+ address to the +outgoing+ address.
|
137
139
|
#
|
138
|
-
def initialize
|
139
|
-
|
140
|
-
|
140
|
+
def initialize(config)
|
141
|
+
@reactor = config.reactor
|
142
|
+
incoming = Address.from_string(config.incoming_endpoint.to_s)
|
143
|
+
outgoing = Address.from_string(config.outgoing_endpoint.to_s)
|
141
144
|
|
142
145
|
# setup the handlers for processing messages
|
143
|
-
@handler_in = Handler.new
|
144
|
-
@handler_out = Handler.new
|
146
|
+
@handler_in = Handler.new(config, incoming)
|
147
|
+
@handler_out = Handler.new(config, outgoing)
|
145
148
|
|
146
149
|
# create each socket and pass in the appropriate handler
|
147
|
-
@
|
148
|
-
@
|
150
|
+
@incoming_sock = @reactor.sub_socket(@handler_in)
|
151
|
+
@outgoing_sock = @reactor.pub_socket(@handler_out)
|
149
152
|
|
150
153
|
# set each handler's outgoing socket
|
151
|
-
@handler_in.socket_out = @
|
152
|
-
@handler_out.socket_out = @
|
154
|
+
@handler_in.socket_out = @outgoing_sock
|
155
|
+
@handler_out.socket_out = @incoming_sock
|
153
156
|
end
|
154
157
|
end # class Forwarder
|
155
158
|
|
156
159
|
end # module Device
|
157
|
-
|
158
160
|
end # module ZMQMachine
|