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
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
|