qpid_proton 0.9.0 → 0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/codec/data.rb +912 -0
- data/lib/codec/mapping.rb +169 -0
- data/lib/{qpid_proton/tracker.rb → core/base_handler.rb} +4 -15
- data/lib/core/connection.rb +328 -0
- data/lib/core/delivery.rb +271 -0
- data/lib/core/disposition.rb +158 -0
- data/lib/core/endpoint.rb +140 -0
- data/lib/{qpid_proton → core}/exceptions.rb +43 -2
- data/lib/core/link.rb +387 -0
- data/lib/core/message.rb +633 -0
- data/lib/core/receiver.rb +95 -0
- data/lib/core/sasl.rb +94 -0
- data/lib/core/selectable.rb +130 -0
- data/lib/core/sender.rb +76 -0
- data/lib/core/session.rb +163 -0
- data/lib/core/ssl.rb +164 -0
- data/lib/{qpid_proton/version.rb → core/ssl_details.rb} +7 -6
- data/lib/core/ssl_domain.rb +156 -0
- data/lib/core/terminus.rb +218 -0
- data/lib/core/transport.rb +411 -0
- data/lib/core/url.rb +77 -0
- data/lib/event/collector.rb +148 -0
- data/lib/event/event.rb +318 -0
- data/lib/event/event_base.rb +91 -0
- data/lib/event/event_type.rb +71 -0
- data/lib/handler/acking.rb +70 -0
- data/lib/handler/c_adaptor.rb +47 -0
- data/lib/handler/c_flow_controller.rb +33 -0
- data/lib/handler/endpoint_state_handler.rb +217 -0
- data/lib/handler/incoming_message_handler.rb +74 -0
- data/lib/handler/messaging_handler.rb +218 -0
- data/lib/handler/outgoing_message_handler.rb +98 -0
- data/lib/handler/wrapped_handler.rb +76 -0
- data/lib/messenger/messenger.rb +702 -0
- data/lib/messenger/subscription.rb +37 -0
- data/lib/messenger/tracker.rb +38 -0
- data/lib/messenger/tracker_status.rb +69 -0
- data/lib/qpid_proton.rb +106 -16
- data/lib/reactor/acceptor.rb +41 -0
- data/lib/reactor/backoff.rb +41 -0
- data/lib/reactor/connector.rb +98 -0
- data/lib/reactor/container.rb +272 -0
- data/lib/reactor/global_overrides.rb +44 -0
- data/lib/reactor/link_option.rb +90 -0
- data/lib/reactor/reactor.rb +198 -0
- data/lib/reactor/session_per_connection.rb +45 -0
- data/lib/reactor/ssl_config.rb +41 -0
- data/lib/reactor/task.rb +39 -0
- data/lib/{qpid_proton/subscription.rb → reactor/urls.rb} +12 -13
- data/lib/{qpid_proton → types}/array.rb +28 -29
- data/lib/types/described.rb +63 -0
- data/lib/{qpid_proton → types}/hash.rb +4 -3
- data/lib/types/strings.rb +62 -0
- data/lib/util/class_wrapper.rb +54 -0
- data/lib/util/condition.rb +45 -0
- data/lib/util/constants.rb +85 -0
- data/lib/util/engine.rb +82 -0
- data/lib/util/error_handler.rb +127 -0
- data/lib/util/handler.rb +41 -0
- data/lib/util/reactor.rb +32 -0
- data/lib/util/swig_helper.rb +114 -0
- data/lib/util/timeout.rb +50 -0
- data/lib/util/uuid.rb +32 -0
- data/lib/util/version.rb +30 -0
- data/lib/util/wrapper.rb +124 -0
- metadata +67 -21
- data/ext/cproton/cproton.c +0 -22196
- data/lib/qpid_proton/data.rb +0 -788
- data/lib/qpid_proton/described.rb +0 -66
- data/lib/qpid_proton/exception_handling.rb +0 -127
- data/lib/qpid_proton/filters.rb +0 -67
- data/lib/qpid_proton/mapping.rb +0 -170
- data/lib/qpid_proton/message.rb +0 -621
- data/lib/qpid_proton/messenger.rb +0 -702
- data/lib/qpid_proton/selectable.rb +0 -126
- data/lib/qpid_proton/strings.rb +0 -65
- data/lib/qpid_proton/tracker_status.rb +0 -73
@@ -0,0 +1,272 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton::Reactor
|
21
|
+
|
22
|
+
# @private
|
23
|
+
class InternalTransactionHandler < Qpid::Proton::Handler::OutgoingMessageHandler
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_settled(event)
|
30
|
+
if event.delivery.respond_to? :transaction
|
31
|
+
event.transaction = event.delivery.transaction
|
32
|
+
event.delivery.transaction.handle_outcome(event)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
# A representation of the AMQP concept of a container which, loosely
|
40
|
+
# speaking, is something that establishes links to or from another
|
41
|
+
# container on which messages are transferred.
|
42
|
+
#
|
43
|
+
# This is an extension to the Reactor classthat adds convenience methods
|
44
|
+
# for creating instances of Qpid::Proton::Connection, Qpid::Proton::Sender
|
45
|
+
# and Qpid::Proton::Receiver.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
#
|
49
|
+
class Container < Reactor
|
50
|
+
|
51
|
+
include Qpid::Proton::Util::Reactor
|
52
|
+
|
53
|
+
include Qpid::Proton::Util::UUID
|
54
|
+
|
55
|
+
attr_accessor :container_id
|
56
|
+
attr_accessor :global_handler
|
57
|
+
|
58
|
+
def initialize(handlers, options = {})
|
59
|
+
super(handlers, options)
|
60
|
+
|
61
|
+
# only do the following if we're creating a new instance
|
62
|
+
if !options.has_key?(:impl)
|
63
|
+
@ssl = SSLConfig.new
|
64
|
+
if options[:global_handler]
|
65
|
+
self.global_handler = GlobalOverrides.new(options[:global_handler])
|
66
|
+
else
|
67
|
+
# very ugly, but using self.global_handler doesn't work in the constructor
|
68
|
+
ghandler = Reactor.instance_method(:global_handler).bind(self).call
|
69
|
+
ghandler = GlobalOverrides.new(ghandler)
|
70
|
+
Reactor.instance_method(:global_handler=).bind(self).call(ghandler)
|
71
|
+
end
|
72
|
+
@trigger = nil
|
73
|
+
@container_id = generate_uuid
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Initiates the establishment of an AMQP connection.
|
78
|
+
#
|
79
|
+
# @param options [Hash] A hash of named arguments.
|
80
|
+
#
|
81
|
+
def connect(options = {})
|
82
|
+
conn = self.connection(options[:handler])
|
83
|
+
conn.container = self.container_id || generate_uuid
|
84
|
+
connector = Connector.new(conn)
|
85
|
+
conn.overrides = connector
|
86
|
+
if !options[:url].nil?
|
87
|
+
connector.address = URLs.new([options[:url]])
|
88
|
+
elsif !options[:urls].nil?
|
89
|
+
connector.address = URLs.new(options[:urls])
|
90
|
+
elsif !options[:address].nil?
|
91
|
+
connector.address = URLs.new([Qpid::Proton::URL.new(options[:address])])
|
92
|
+
else
|
93
|
+
raise ::ArgumentError.new("either :url or :urls or :address required")
|
94
|
+
end
|
95
|
+
|
96
|
+
connector.heartbeat = options[:heartbeat] if !options[:heartbeat].nil?
|
97
|
+
if !options[:reconnect].nil?
|
98
|
+
connector.reconnect = options[:reconnect]
|
99
|
+
else
|
100
|
+
connector.reconnect = Backoff.new()
|
101
|
+
end
|
102
|
+
|
103
|
+
connector.ssl_domain = SessionPerConnection.new # TODO seems this should be configurable
|
104
|
+
|
105
|
+
conn.open
|
106
|
+
|
107
|
+
return conn
|
108
|
+
end
|
109
|
+
|
110
|
+
def _session(context)
|
111
|
+
if context.is_a?(Qpid::Proton::URL)
|
112
|
+
return self._session(self.connect(:url => context))
|
113
|
+
elsif context.is_a?(Qpid::Proton::Session)
|
114
|
+
return context
|
115
|
+
elsif context.is_a?(Qpid::Proton::Connection)
|
116
|
+
if context.session_policy?
|
117
|
+
return context.session_policy.session(context)
|
118
|
+
else
|
119
|
+
return self.create_session(context)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
return context.session
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Initiates the establishment of a link over which messages can be sent.
|
127
|
+
#
|
128
|
+
# @param context [String, URL] The context.
|
129
|
+
# @param opts [Hash] Additional options.
|
130
|
+
# @param opts [String, Qpid::Proton::URL] The target address.
|
131
|
+
# @param opts [String] :source The source address.
|
132
|
+
# @param opts [Boolean] :dynamic
|
133
|
+
# @param opts [Object] :handler
|
134
|
+
# @param opts [Object] :tag_generator The tag generator.
|
135
|
+
# @param opts [Hash] :options Addtional link options
|
136
|
+
#
|
137
|
+
# @return [Sender] The sender.
|
138
|
+
#
|
139
|
+
def create_sender(context, opts = {})
|
140
|
+
if context.is_a?(::String)
|
141
|
+
context = Qpid::Proton::URL.new(context)
|
142
|
+
end
|
143
|
+
|
144
|
+
target = opts[:target]
|
145
|
+
if context.is_a?(Qpid::Proton::URL) && target.nil?
|
146
|
+
target = context.path
|
147
|
+
end
|
148
|
+
|
149
|
+
session = self._session(context)
|
150
|
+
|
151
|
+
sender = session.sender(opts[:name] ||
|
152
|
+
id(session.connection.container,
|
153
|
+
target, opts[:source]))
|
154
|
+
sender.source.address = opts[:source] if !opts[:source].nil?
|
155
|
+
sender.target.address = target if target
|
156
|
+
sender.handler = opts[:handler] if !opts[:handler].nil?
|
157
|
+
sender.tag_generator = opts[:tag_generator] if !opts[:tag_gnenerator].nil?
|
158
|
+
self._apply_link_options(opts[:options], sender)
|
159
|
+
sender.open
|
160
|
+
return sender
|
161
|
+
end
|
162
|
+
|
163
|
+
# Initiates the establishment of a link over which messages can be received.
|
164
|
+
#
|
165
|
+
# There are two accepted arguments for the context
|
166
|
+
# 1. If a Connection is supplied then the link is established using that
|
167
|
+
# object. The source, and optionally the target, address can be supplied
|
168
|
+
# 2. If it is a String or a URL then a new Connection is created on which
|
169
|
+
# the link will be attached. If a path is specified, but not the source
|
170
|
+
# address, then the path of the URL is used as the target address.
|
171
|
+
#
|
172
|
+
# The name will be generated for the link if one is not specified.
|
173
|
+
#
|
174
|
+
# @param context [Connection, URL, String] The connection or the address.
|
175
|
+
# @param opts [Hash] Additional otpions.
|
176
|
+
# @option opts [String, Qpid::Proton::URL] The source address.
|
177
|
+
# @option opts [String] :target The target address
|
178
|
+
# @option opts [String] :name The link name.
|
179
|
+
# @option opts [Boolean] :dynamic
|
180
|
+
# @option opts [Object] :handler
|
181
|
+
# @option opts [Hash] :options Additional link options.
|
182
|
+
#
|
183
|
+
# @return [Receiver
|
184
|
+
#
|
185
|
+
def create_receiver(context, opts = {})
|
186
|
+
if context.is_a?(::String)
|
187
|
+
context = Qpid::Proton::URL.new(context)
|
188
|
+
end
|
189
|
+
|
190
|
+
source = opts[:source]
|
191
|
+
if context.is_a?(Qpid::Proton::URL) && source.nil?
|
192
|
+
source = context.path
|
193
|
+
end
|
194
|
+
|
195
|
+
session = self._session(context)
|
196
|
+
|
197
|
+
receiver = session.receiver(opts[:name] ||
|
198
|
+
id(session.connection.container,
|
199
|
+
source, opts[:target]))
|
200
|
+
receiver.source.address = source if source
|
201
|
+
receiver.source.dynamic = true if opts.has_key?(:dynamic) && opts[:dynamic]
|
202
|
+
receiver.target.address = opts[:target] if !opts[:target].nil?
|
203
|
+
receiver.handler = opts[:handler] if !opts[:handler].nil?
|
204
|
+
self._apply_link_options(opts[:options], receiver)
|
205
|
+
receiver.open
|
206
|
+
return receiver
|
207
|
+
end
|
208
|
+
|
209
|
+
def declare_transaction(context, handler = nil, settle_before_discharge = false)
|
210
|
+
if context.respond_to? :txn_ctl && !context.__send__(:txn_ctl).nil?
|
211
|
+
class << context
|
212
|
+
attr_accessor :txn_ctl
|
213
|
+
end
|
214
|
+
context.txn_ctl = self.create_sender(context, nil, "txn-ctl",
|
215
|
+
InternalTransactionHandler.new())
|
216
|
+
end
|
217
|
+
return Transaction.new(context.txn_ctl, handler, settle_before_discharge)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Initiates a server socket, accepting incoming AMQP connections on the
|
221
|
+
# interface and port specified.
|
222
|
+
#
|
223
|
+
# @param url []
|
224
|
+
# @param ssl_domain []
|
225
|
+
#
|
226
|
+
def listen(url, ssl_domain = nil)
|
227
|
+
url = Qpid::Proton::URL.new(url)
|
228
|
+
acceptor = self.acceptor(url.host, url.port)
|
229
|
+
ssl_config = ssl_domain
|
230
|
+
if ssl_config.nil? && (url.scheme == 'amqps') && @ssl
|
231
|
+
ssl_config = @ssl.server
|
232
|
+
end
|
233
|
+
if !ssl_config.nil?
|
234
|
+
acceptor.ssl_domain(ssl_config)
|
235
|
+
end
|
236
|
+
return acceptor
|
237
|
+
end
|
238
|
+
|
239
|
+
def do_work(timeout = nil)
|
240
|
+
self.timeout = timeout unless timeout.nil?
|
241
|
+
self.process
|
242
|
+
end
|
243
|
+
|
244
|
+
def id(container, remote, local)
|
245
|
+
if !local.nil? && !remote.nil?
|
246
|
+
"#{container}-#{remote}-#{local}"
|
247
|
+
elsif !local.nil?
|
248
|
+
"#{container}-#{local}"
|
249
|
+
elsif !remote.nil?
|
250
|
+
"#{container}-#{remote}"
|
251
|
+
else
|
252
|
+
"#{container}-#{generate_uuid}"
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
def _apply_link_options(options, link)
|
257
|
+
if !options.nil? && !options.empty?
|
258
|
+
if !options.is_a?(::List)
|
259
|
+
options = [Options].flatten
|
260
|
+
end
|
261
|
+
|
262
|
+
options.each {|option| o.apply(link) if o.test(link)}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def to_s
|
267
|
+
"#{self.class}<@impl=#{Cproton.pni_address_of(@impl)}>"
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton::Reactor
|
21
|
+
|
22
|
+
class GlobalOverrides
|
23
|
+
|
24
|
+
def initialize(base)
|
25
|
+
@base = base
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_unhandled(name, event)
|
29
|
+
event.dispatch(@base) unless self.override?(event)
|
30
|
+
end
|
31
|
+
|
32
|
+
def override?(event)
|
33
|
+
conn = event.connection
|
34
|
+
if !conn.nil? && conn.overrides?
|
35
|
+
overrides = conn.overrides
|
36
|
+
result = event.dispatch(overrides)
|
37
|
+
return result
|
38
|
+
end
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton::Reactor
|
21
|
+
|
22
|
+
class LinkOption
|
23
|
+
def apply(link)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Subclasses should override this to selectively apply an option.
|
27
|
+
def test(link)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class AtMostOne < LinkOption
|
33
|
+
def apply(link)
|
34
|
+
link.snd_settle_mod = Link::SND_SETTLED
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class AtLeastOnce < LinkOption
|
39
|
+
def apply(link)
|
40
|
+
link.snd_settle_mode = Link::SND_UNSETTLED
|
41
|
+
link.rcv_settle_mode = Link::RCV_FIRST
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class SenderOption < LinkOption
|
46
|
+
def test(link)
|
47
|
+
link.sender?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ReceiverOption < LinkOption
|
52
|
+
def test(link)
|
53
|
+
link.receiver?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class DynamicNodeProperties < LinkOption
|
58
|
+
def initialize(properties = {})
|
59
|
+
@properties = []
|
60
|
+
properties.each do |property|
|
61
|
+
@properties << property.to_sym
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def apply(link)
|
66
|
+
if link.receiver?
|
67
|
+
link.source.properties.dict = @properties
|
68
|
+
else
|
69
|
+
link.target.properties.dict = @properties
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class Filter < ReceiverOption
|
75
|
+
def initialize(filter_set = {})
|
76
|
+
@filter_set = filter_set
|
77
|
+
end
|
78
|
+
|
79
|
+
def apply(receiver)
|
80
|
+
receiver.source.filter.dict = @filter_set
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
#class Selector < Filter
|
85
|
+
# def initialize(value, name = 'selector')
|
86
|
+
#
|
87
|
+
# end
|
88
|
+
#end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton::Reactor
|
21
|
+
|
22
|
+
class Reactor
|
23
|
+
|
24
|
+
include Qpid::Proton::Util::Handler
|
25
|
+
|
26
|
+
# @private
|
27
|
+
include Qpid::Proton::Util::SwigHelper
|
28
|
+
|
29
|
+
# @private
|
30
|
+
PROTON_METHOD_PREFIX = "pn_reactor"
|
31
|
+
|
32
|
+
proton_caller :yield
|
33
|
+
|
34
|
+
proton_caller :mark
|
35
|
+
|
36
|
+
proton_caller :start
|
37
|
+
|
38
|
+
proton_caller :stop
|
39
|
+
|
40
|
+
# @private
|
41
|
+
include Qpid::Proton::Util::Timeout
|
42
|
+
|
43
|
+
include Qpid::Proton::Util::Wrapper
|
44
|
+
|
45
|
+
attr_reader :errors
|
46
|
+
|
47
|
+
def self.wrap(impl)
|
48
|
+
return nil if impl.nil?
|
49
|
+
|
50
|
+
self.fetch_instance(impl, :pn_reactor_attachments) || Reactor.new(nil, :impl => impl)
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(handlers, options = {})
|
54
|
+
@impl = options[:impl]
|
55
|
+
if @impl.nil?
|
56
|
+
@impl = Cproton.pn_reactor
|
57
|
+
end
|
58
|
+
if !handlers.nil?
|
59
|
+
[handlers].flatten.each {|handler| self.handler.add(handler)}
|
60
|
+
end
|
61
|
+
@errors = []
|
62
|
+
@handlers = []
|
63
|
+
self.class.store_instance(self, :pn_reactor_attachments)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns whether the reactor has any unbuffered data.
|
67
|
+
#
|
68
|
+
# @return [Boolean] True if there is no unbuffered data.
|
69
|
+
#
|
70
|
+
def quiesced?
|
71
|
+
Cproton.pn_reactor_quiesced(@impl)
|
72
|
+
end
|
73
|
+
|
74
|
+
def on_error(info)
|
75
|
+
self.errors << info
|
76
|
+
self.yield
|
77
|
+
end
|
78
|
+
|
79
|
+
def global_handler
|
80
|
+
impl = Cproton.pn_reactor_get_global_handler(@impl)
|
81
|
+
Qpid::Proton::Handler::WrappedHandler.wrap(impl, self.method(:on_error))
|
82
|
+
end
|
83
|
+
|
84
|
+
def global_handler=(handler)
|
85
|
+
impl = chandler(handler, self.method(:on_error))
|
86
|
+
Cproton.pn_reactor_set_global_handler(@impl, impl)
|
87
|
+
Cproton.pn_decref(impl)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns the timeout period.
|
91
|
+
#
|
92
|
+
# @return [Fixnum] The timeout period, in seconds.
|
93
|
+
#
|
94
|
+
def timeout
|
95
|
+
millis_to_timeout(Cproton.pn_reactor_get_timeout(@impl))
|
96
|
+
end
|
97
|
+
|
98
|
+
# Sets the timeout period.
|
99
|
+
#
|
100
|
+
# @param timeout [Fixnum] The timeout, in seconds.
|
101
|
+
#
|
102
|
+
def timeout=(timeout)
|
103
|
+
Cproton.pn_reactor_set_timeout(@impl, timeout_to_millis(timeout))
|
104
|
+
end
|
105
|
+
|
106
|
+
def handler
|
107
|
+
impl = Cproton.pn_reactor_get_handler(@impl)
|
108
|
+
Qpid::Proton::Handler::WrappedHandler.wrap(impl, self.method(:on_error))
|
109
|
+
end
|
110
|
+
|
111
|
+
def handler=(handler)
|
112
|
+
impl = chandler(handler, set.method(:on_error))
|
113
|
+
Cproton.pn_reactor_set_handler(@impl, impl)
|
114
|
+
Cproton.pn_decref(impl)
|
115
|
+
end
|
116
|
+
|
117
|
+
def run(&block)
|
118
|
+
self.timeout = 3.14159265359
|
119
|
+
self.start
|
120
|
+
while self.process do
|
121
|
+
if block_given?
|
122
|
+
yield
|
123
|
+
end
|
124
|
+
end
|
125
|
+
self.stop
|
126
|
+
end
|
127
|
+
|
128
|
+
def wakeup
|
129
|
+
n = Cproton.pn_reactor_wakeup(@impl)
|
130
|
+
unless n.zero?
|
131
|
+
io = Cproton.pn_reactor_io(@impl)
|
132
|
+
raise IOError.new(Cproton.pn_io_error(io))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def process
|
137
|
+
result = Cproton.pn_reactor_process(@impl)
|
138
|
+
if !self.errors.nil? && !self.errors.empty?
|
139
|
+
(0...self.errors.size).each do |index|
|
140
|
+
error_set = self.errors[index]
|
141
|
+
print error.backtrace.join("\n")
|
142
|
+
end
|
143
|
+
raise self.errors.last
|
144
|
+
end
|
145
|
+
return result
|
146
|
+
end
|
147
|
+
|
148
|
+
def schedule(delay, task)
|
149
|
+
impl = chandler(task, self.method(:on_error))
|
150
|
+
task = Task.wrap(Cproton.pn_reactor_schedule(@impl, sec_to_millis(delay), impl))
|
151
|
+
Cproton.pn_decref(impl)
|
152
|
+
return task
|
153
|
+
end
|
154
|
+
|
155
|
+
def acceptor(host, port, handler = nil)
|
156
|
+
impl = chandler(handler, self.method(:on_error))
|
157
|
+
aimpl = Cproton.pn_reactor_acceptor(@impl, host, "#{port}", impl)
|
158
|
+
Cproton.pn_decref(impl)
|
159
|
+
if !aimpl.nil?
|
160
|
+
return Acceptor.new(aimpl)
|
161
|
+
else
|
162
|
+
io = Cproton.pn_reactor_io(@impl)
|
163
|
+
io_error = Cproton.pn_io_error(io)
|
164
|
+
error_text = Cproton.pn_error_text(io_error)
|
165
|
+
text = "(#{Cproton.pn_error_text(io_error)} (#{host}:#{port}))"
|
166
|
+
raise IOError.new(text)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def connection(handler = nil)
|
171
|
+
impl = chandler(handler, self.method(:on_error))
|
172
|
+
conn = Qpid::Proton::Connection.wrap(Cproton.pn_reactor_connection(@impl, impl))
|
173
|
+
Cproton.pn_decref(impl)
|
174
|
+
return conn
|
175
|
+
end
|
176
|
+
|
177
|
+
def selectable(handler = nil)
|
178
|
+
impl = chandler(handler, self.method(:on_error))
|
179
|
+
result = Selectable.wrap(Cproton.pn_reactor_selectable(@impl))
|
180
|
+
if !impl.nil?
|
181
|
+
record = Cproton.pn_selectable_attachments(result.impl)
|
182
|
+
Cproton.pn_record_set_handler(record, impl)
|
183
|
+
Cproton.pn_decref(impl)
|
184
|
+
end
|
185
|
+
return result
|
186
|
+
end
|
187
|
+
|
188
|
+
def update(sel)
|
189
|
+
Cproton.pn_reactor_update(@impl, sel.impl)
|
190
|
+
end
|
191
|
+
|
192
|
+
def push_event(obj, etype)
|
193
|
+
Cproton.pn_collector_put(Cproton.pn_reactor_collector(@impl), Qpid::Proton::Util::RBCTX, Cproton.pn_py2void(obj), etype.number)
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|