bunny 0.4.4 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Rakefile +21 -3
  2. data/bunny.gemspec +34 -20
  3. data/examples/{simple.rb → simple_08.rb} +0 -0
  4. data/examples/simple_09.rb +30 -0
  5. data/examples/{simple_ack.rb → simple_ack_08.rb} +0 -0
  6. data/examples/simple_ack_09.rb +33 -0
  7. data/examples/{simple_consumer.rb → simple_consumer_08.rb} +0 -0
  8. data/examples/simple_consumer_09.rb +55 -0
  9. data/examples/{simple_fanout.rb → simple_fanout_08.rb} +0 -0
  10. data/examples/simple_fanout_09.rb +39 -0
  11. data/examples/{simple_headers.rb → simple_headers_08.rb} +0 -0
  12. data/examples/simple_headers_09.rb +40 -0
  13. data/examples/{simple_publisher.rb → simple_publisher_08.rb} +0 -0
  14. data/examples/simple_publisher_09.rb +27 -0
  15. data/examples/{simple_topic.rb → simple_topic_08.rb} +0 -0
  16. data/examples/simple_topic_09.rb +59 -0
  17. data/lib/bunny.rb +19 -14
  18. data/lib/bunny/channel08.rb +38 -0
  19. data/lib/bunny/channel09.rb +38 -0
  20. data/lib/bunny/client08.rb +167 -74
  21. data/lib/bunny/{client091.rb → client09.rb} +195 -92
  22. data/lib/bunny/{exchange091.rb → exchange09.rb} +12 -11
  23. data/lib/bunny/queue08.rb +1 -0
  24. data/lib/bunny/{queue091.rb → queue09.rb} +38 -28
  25. data/lib/qrack/client.rb +7 -0
  26. data/lib/qrack/protocol/{protocol.rb → protocol08.rb} +1 -4
  27. data/lib/qrack/protocol/protocol09.rb +133 -0
  28. data/lib/qrack/protocol/{spec091.rb → spec09.rb} +5 -5
  29. data/lib/qrack/qrack08.rb +2 -10
  30. data/lib/qrack/qrack09.rb +20 -0
  31. data/lib/qrack/transport/{buffer.rb → buffer08.rb} +0 -0
  32. data/lib/qrack/transport/buffer09.rb +276 -0
  33. data/lib/qrack/transport/{frame091.rb → frame09.rb} +8 -8
  34. data/spec/{bunny_spec.rb → spec_08/bunny_spec.rb} +4 -4
  35. data/spec/{exchange_spec.rb → spec_08/exchange_spec.rb} +3 -10
  36. data/spec/{queue_spec.rb → spec_08/queue_spec.rb} +1 -1
  37. data/spec/spec_09/bunny_spec.rb +40 -0
  38. data/spec/spec_09/exchange_spec.rb +131 -0
  39. data/spec/spec_09/queue_spec.rb +106 -0
  40. metadata +38 -22
  41. data/lib/qrack/qrack091.rb +0 -28
@@ -0,0 +1,38 @@
1
+ module Bunny
2
+ class Channel
3
+ attr_accessor :number, :active
4
+ attr_reader :client
5
+
6
+ def initialize(client, zero = false)
7
+ @client = client
8
+ zero ? @number = 0 : @number = client.channels.size
9
+ @active = false
10
+ client.channels[@number] ||= self
11
+ end
12
+
13
+ def open
14
+ client.channel = self
15
+ client.send_frame(Qrack::Protocol::Channel::Open.new)
16
+ raise Bunny::ProtocolError, "Cannot open channel #{number}" unless client.next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
17
+
18
+ @active = true
19
+ :open_ok
20
+ end
21
+
22
+ def close
23
+ client.channel = self
24
+ client.send_frame(
25
+ Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
26
+ )
27
+ raise Bunny::ProtocolError, "Error closing channel #{number}" unless client.next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
28
+
29
+ @active = false
30
+ :close_ok
31
+ end
32
+
33
+ def open?
34
+ active
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module Bunny
2
+ class Channel09
3
+ attr_accessor :number, :active
4
+ attr_reader :client
5
+
6
+ def initialize(client, zero = false)
7
+ @client = client
8
+ zero ? @number = 0 : @number = client.channels.size
9
+ @active = false
10
+ client.channels[@number] ||= self
11
+ end
12
+
13
+ def open
14
+ client.channel = self
15
+ client.send_frame(Qrack::Protocol09::Channel::Open.new)
16
+ raise Bunny::ProtocolError, "Cannot open channel #{number}" unless client.next_method.is_a?(Qrack::Protocol09::Channel::OpenOk)
17
+
18
+ @active = true
19
+ :open_ok
20
+ end
21
+
22
+ def close
23
+ client.channel = self
24
+ client.send_frame(
25
+ Qrack::Protocol09::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
26
+ )
27
+ raise Bunny::ProtocolError, "Error closing channel #{number}" unless client.next_method.is_a?(Qrack::Protocol09::Channel::CloseOk)
28
+
29
+ @active = false
30
+ :close_ok
31
+ end
32
+
33
+ def open?
34
+ active
35
+ end
36
+
37
+ end
38
+ end
@@ -9,11 +9,8 @@ The Client class provides the major Bunny API methods.
9
9
  =end
10
10
 
11
11
  class Client < Qrack::Client
12
- CONNECT_TIMEOUT = 1.0
13
- RETRY_DELAY = 10.0
14
-
15
- attr_reader :status, :host, :vhost, :port, :logging, :spec
16
- attr_accessor :channel, :logfile, :exchanges, :queues, :ticket
12
+
13
+ attr_accessor :ticket
17
14
 
18
15
  =begin rdoc
19
16
 
@@ -41,7 +38,7 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
41
38
  =end
42
39
 
43
40
  def initialize(opts = {})
44
- @spec = opts[:spec] || '08'
41
+ @spec = '0-8'
45
42
  @host = opts[:host] || 'localhost'
46
43
  @port = opts[:port] || Qrack::Protocol::PORT
47
44
  @user = opts[:user] || 'guest'
@@ -51,8 +48,12 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
51
48
  @logging = opts[:logging] || false
52
49
  @insist = opts[:insist]
53
50
  @status = :not_connected
51
+ @frame_max = opts[:frame_max] || 131072
52
+ @channel_max = opts[:channel_max] || 0
54
53
  @logger = nil
55
54
  create_logger if @logging
55
+ # Create channel 0
56
+ @channel = Bunny::Channel.new(self, true)
56
57
  end
57
58
 
58
59
  =begin rdoc
@@ -60,9 +61,8 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
60
61
  === DESCRIPTION:
61
62
 
62
63
  Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
63
- using the arguments passed in. If the exchange already exists, a reference to it is created, provided
64
- that the arguments passed in do not conflict with the existing attributes of the exchange. If an error
65
- occurs a _Bunny_::_ProtocolError_ is raised.
64
+ using the arguments passed in. If the exchange already exists, the existing object is returned.
65
+ If an error occurs a _Bunny_::_ProtocolError_ is raised.
66
66
 
67
67
  ==== OPTIONS:
68
68
 
@@ -83,7 +83,8 @@ Exchange
83
83
  =end
84
84
 
85
85
  def exchange(name, opts = {})
86
- exchanges[name] ||= Bunny::Exchange.new(self, name, opts)
86
+ return exchanges[name] if exchanges.has_key?(name)
87
+ Bunny::Exchange.new(self, name, opts)
87
88
  end
88
89
 
89
90
  =begin rdoc
@@ -141,7 +142,6 @@ Queue
141
142
  return queues[name] if queues.has_key?(name)
142
143
 
143
144
  queue = Bunny::Queue.new(self, name, opts)
144
- queues[queue.name] = queue
145
145
  end
146
146
 
147
147
  =begin rdoc
@@ -159,12 +159,13 @@ Returns hash of queues declared by Bunny.
159
159
  def send_frame(*args)
160
160
  args.each do |data|
161
161
  data.ticket = ticket if ticket and data.respond_to?(:ticket=)
162
- data = data.to_frame(channel) unless data.is_a?(Qrack::Transport::Frame)
163
- data.channel = channel
162
+ data = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport::Frame)
163
+ data.channel = channel.number
164
164
 
165
165
  @logger.info("send") { data } if @logging
166
166
  write(data.to_s)
167
167
  end
168
+
168
169
  nil
169
170
  end
170
171
 
@@ -174,15 +175,13 @@ Returns hash of queues declared by Bunny.
174
175
  frame
175
176
  end
176
177
 
177
- def next_method
178
- next_payload
179
- end
180
-
181
178
  def next_payload
182
179
  frame = next_frame
183
- frame and frame.payload
180
+ frame.payload
184
181
  end
185
182
 
183
+ alias next_method next_payload
184
+
186
185
  =begin rdoc
187
186
 
188
187
  === DESCRIPTION:
@@ -197,17 +196,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
197
196
  =end
198
197
 
199
198
  def close
200
- send_frame(
201
- Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
202
- )
203
- raise Bunny::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
199
+ # Close all active channels
200
+ channels.each_value do |c|
201
+ c.close if c.open?
202
+ end
203
+
204
+ # Set client channel to zero
205
+ self.channel = channels[0]
204
206
 
205
- self.channel = 0
206
- send_frame(
207
- Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
208
- )
209
- raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
207
+ # Close connection to AMQP server
208
+ close_connection
210
209
 
210
+ # Close TCP Socket
211
211
  close_socket
212
212
  end
213
213
 
@@ -239,56 +239,19 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
239
239
  # Create/get socket
240
240
  socket
241
241
 
242
- @channel = 0
243
- write(Qrack::Protocol::HEADER)
244
- write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
245
- raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
242
+ # Initiate connection
243
+ init_connection
246
244
 
247
- send_frame(
248
- Qrack::Protocol::Connection::StartOk.new(
249
- {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
250
- 'AMQPLAIN',
251
- {:LOGIN => @user, :PASSWORD => @pass},
252
- 'en_US'
253
- )
254
- )
255
-
256
- method = next_method
257
- raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
258
-
259
- if method.is_a?(Qrack::Protocol::Connection::Tune)
260
- send_frame(
261
- Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
262
- )
263
- end
264
-
265
- send_frame(
266
- Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
267
- )
268
-
269
- case method = next_method
270
- when Qrack::Protocol::Connection::OpenOk
271
- break
272
- when Qrack::Protocol::Connection::Redirect
273
- raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
274
-
275
- @host, @port = method.host.split(':')
276
- close_socket
277
- else
278
- raise Bunny::ProtocolError, 'Cannot open connection'
279
- end
245
+ # Open connection
246
+ break if open_connection == :ok
280
247
  end
281
248
 
282
- @channel = 1
283
- send_frame(Qrack::Protocol::Channel::Open.new)
284
- raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
285
-
286
- send_frame(
287
- Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
288
- )
289
- method = next_method
290
- raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
291
- self.ticket = method.ticket
249
+ # Open a channel
250
+ self.channel = get_channel
251
+ channel.open
252
+
253
+ # Get access ticket
254
+ request_access
292
255
 
293
256
  # return status
294
257
  status
@@ -360,11 +323,141 @@ true, they are applied to the entire connection.
360
323
  # return confirmation
361
324
  :qos_ok
362
325
  end
326
+
327
+ =begin rdoc
328
+
329
+ === DESCRIPTION:
330
+ This method sets the channel to use standard transactions. The
331
+ client must use this method at least once on a channel before
332
+ using the Commit or Rollback methods.
333
+
334
+ =end
335
+
336
+ def tx_select
337
+ send_frame(Qrack::Protocol::Tx::Select.new())
338
+
339
+ raise Bunny::ProtocolError,
340
+ "Error initiating transactions for current channel" unless
341
+ next_method.is_a?(Qrack::Protocol::Tx::SelectOk)
342
+
343
+ # return confirmation
344
+ :select_ok
345
+ end
346
+
347
+ =begin rdoc
348
+
349
+ === DESCRIPTION:
350
+ This method commits all messages published and acknowledged in
351
+ the current transaction. A new transaction starts immediately
352
+ after a commit.
353
+
354
+ =end
355
+
356
+ def tx_commit
357
+ send_frame(Qrack::Protocol::Tx::Commit.new())
358
+
359
+ raise Bunny::ProtocolError,
360
+ "Error commiting transaction" unless
361
+ next_method.is_a?(Qrack::Protocol::Tx::CommitOk)
362
+
363
+ # return confirmation
364
+ :commit_ok
365
+ end
366
+
367
+ =begin rdoc
368
+
369
+ === DESCRIPTION:
370
+ This method abandons all messages published and acknowledged in
371
+ the current transaction. A new transaction starts immediately
372
+ after a rollback.
373
+
374
+ =end
375
+
376
+ def tx_rollback
377
+ send_frame(Qrack::Protocol::Tx::Rollback.new())
378
+
379
+ raise Bunny::ProtocolError,
380
+ "Error rolling back transaction" unless
381
+ next_method.is_a?(Qrack::Protocol::Tx::RollbackOk)
382
+
383
+ # return confirmation
384
+ :rollback_ok
385
+ end
363
386
 
364
387
  def logging=(bool)
365
388
  @logging = bool
366
389
  create_logger if @logging
367
390
  end
391
+
392
+ def channels
393
+ @channels ||= {}
394
+ end
395
+
396
+ def get_channel
397
+ channels.each_value do |c|
398
+ return c if (!c.open? and c.number != 0)
399
+ end
400
+ # If no channel to re-use instantiate new one
401
+ Bunny::Channel.new(self)
402
+ end
403
+
404
+ def init_connection
405
+ write(Qrack::Protocol::HEADER)
406
+ write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
407
+ raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
408
+ end
409
+
410
+ def open_connection
411
+ send_frame(
412
+ Qrack::Protocol::Connection::StartOk.new(
413
+ {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
414
+ 'AMQPLAIN',
415
+ {:LOGIN => @user, :PASSWORD => @pass},
416
+ 'en_US'
417
+ )
418
+ )
419
+
420
+ method = next_method
421
+ raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
422
+
423
+ if method.is_a?(Qrack::Protocol::Connection::Tune)
424
+ send_frame(
425
+ Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => 0)
426
+ )
427
+ end
428
+
429
+ send_frame(
430
+ Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
431
+ )
432
+
433
+ case method = next_method
434
+ when Qrack::Protocol::Connection::OpenOk
435
+ return :ok
436
+ when Qrack::Protocol::Connection::Redirect
437
+ raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
438
+
439
+ @host, @port = method.host.split(':')
440
+ close_socket
441
+ else
442
+ raise Bunny::ProtocolError, 'Cannot open connection'
443
+ end
444
+ end
445
+
446
+ def close_connection
447
+ send_frame(
448
+ Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
449
+ )
450
+ raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
451
+ end
452
+
453
+ def request_access
454
+ send_frame(
455
+ Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
456
+ )
457
+ method = next_method
458
+ raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
459
+ self.ticket = method.ticket
460
+ end
368
461
 
369
462
  private
370
463
 
@@ -8,12 +8,7 @@ The Client class provides the major Bunny API methods.
8
8
 
9
9
  =end
10
10
 
11
- class Client < Qrack::Client
12
- CONNECT_TIMEOUT = 1.0
13
- RETRY_DELAY = 10.0
14
-
15
- attr_reader :status, :host, :vhost, :port, :logging, :spec
16
- attr_accessor :channel, :logfile, :exchanges, :queues, :ticket
11
+ class Client09 < Qrack::Client
17
12
 
18
13
  =begin rdoc
19
14
 
@@ -33,26 +28,25 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_
33
28
  * <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
34
29
  to STDOUT if <tt>:logfile</tt> has not been specified. Otherwise, session information is written to
35
30
  <tt>:logfile</tt>.
36
- * <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
37
- servers, the server may respond to a Connection::Open method with a Connection::Redirect. The insist
38
- option, if set to _true_, tells the server that the client is insisting on a connection to the
39
- specified server.
40
31
 
41
32
  =end
42
33
 
43
34
  def initialize(opts = {})
44
- @spec = opts[:spec] || '0-8'
35
+ @spec = '0-9-1'
45
36
  @host = opts[:host] || 'localhost'
46
- @port = opts[:port] || Qrack::Protocol::PORT
37
+ @port = opts[:port] || Qrack::Protocol09::PORT
47
38
  @user = opts[:user] || 'guest'
48
39
  @pass = opts[:pass] || 'guest'
49
40
  @vhost = opts[:vhost] || '/'
41
+ @frame_max = opts[:frame_max] || 131072
42
+ @channel_max = opts[:channel_max] || 5
50
43
  @logfile = opts[:logfile] || nil
51
44
  @logging = opts[:logging] || false
52
- @insist = opts[:insist]
53
45
  @status = :not_connected
54
46
  @logger = nil
55
47
  create_logger if @logging
48
+ # Create channel 0
49
+ @channel = Bunny::Channel09.new(self, true)
56
50
  end
57
51
 
58
52
  =begin rdoc
@@ -83,7 +77,8 @@ Exchange
83
77
  =end
84
78
 
85
79
  def exchange(name, opts = {})
86
- exchanges[name] ||= Bunny::Exchange.new(self, name, opts)
80
+ return exchanges[name] if exchanges.has_key?(name)
81
+ exchanges[name] ||= Bunny::Exchange09.new(self, name, opts)
87
82
  end
88
83
 
89
84
  =begin rdoc
@@ -140,8 +135,7 @@ Queue
140
135
 
141
136
  return queues[name] if queues.has_key?(name)
142
137
 
143
- queue = Bunny::Queue.new(self, name, opts)
144
- queues[queue.name] = queue
138
+ queue = Bunny::Queue09.new(self, name, opts)
145
139
  end
146
140
 
147
141
  =begin rdoc
@@ -158,9 +152,8 @@ Returns hash of queues declared by Bunny.
158
152
 
159
153
  def send_frame(*args)
160
154
  args.each do |data|
161
- data.ticket = ticket if ticket and data.respond_to?(:ticket=)
162
- data = data.to_frame(channel) unless data.is_a?(Qrack::Transport::Frame)
163
- data.channel = channel
155
+ data = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport09::Frame)
156
+ data.channel = channel.number
164
157
 
165
158
  @logger.info("send") { data } if @logging
166
159
  write(data.to_s)
@@ -169,20 +162,18 @@ Returns hash of queues declared by Bunny.
169
162
  end
170
163
 
171
164
  def next_frame
172
- frame = Qrack::Transport::Frame.parse(buffer)
165
+ frame = Qrack::Transport09::Frame.parse(buffer)
173
166
  @logger.info("received") { frame } if @logging
174
167
  frame
175
168
  end
176
169
 
177
- def next_method
178
- next_payload
179
- end
180
-
181
170
  def next_payload
182
171
  frame = next_frame
183
- frame and frame.payload
172
+ frame.payload
184
173
  end
185
174
 
175
+ alias next_method next_payload
176
+
186
177
  =begin rdoc
187
178
 
188
179
  === DESCRIPTION:
@@ -197,17 +188,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
197
188
  =end
198
189
 
199
190
  def close
200
- send_frame(
201
- Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
202
- )
203
- raise Bunny::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
204
-
205
- self.channel = 0
206
- send_frame(
207
- Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
208
- )
209
- raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
210
-
191
+ # Close all active channels
192
+ channels.each_value do |c|
193
+ c.close if c.open?
194
+ end
195
+
196
+ # Set client channel to zero
197
+ self.channel = channels[0]
198
+
199
+ # Close connection to AMQP server
200
+ close_connection
201
+
202
+ # Close TCP socket
211
203
  close_socket
212
204
  end
213
205
 
@@ -235,60 +227,18 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <
235
227
  =end
236
228
 
237
229
  def start_session
238
- loop do
239
- # Create/get socket
240
- socket
241
-
242
- @channel = 0
243
- write(Qrack::Protocol::HEADER)
244
- write([1, 1, Qrack::Protocol::VERSION_MINOR, Qrack::Protocol::VERSION_MAJOR].pack('C4'))
245
- raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
246
-
247
- send_frame(
248
- Qrack::Protocol::Connection::StartOk.new(
249
- {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
250
- 'AMQPLAIN',
251
- {:LOGIN => @user, :PASSWORD => @pass},
252
- 'en_US'
253
- )
254
- )
255
-
256
- method = next_method
257
- raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
258
-
259
- if method.is_a?(Qrack::Protocol::Connection::Tune)
260
- send_frame(
261
- Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
262
- )
263
- end
264
-
265
- send_frame(
266
- Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
267
- )
268
-
269
- case method = next_method
270
- when Qrack::Protocol::Connection::OpenOk
271
- break
272
- when Qrack::Protocol::Connection::Redirect
273
- raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
274
-
275
- @host, @port = method.host.split(':')
276
- close_socket
277
- else
278
- raise Bunny::ProtocolError, 'Cannot open connection'
279
- end
280
- end
281
-
282
- @channel = 1
283
- send_frame(Qrack::Protocol::Channel::Open.new)
284
- raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
285
-
286
- send_frame(
287
- Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
288
- )
289
- method = next_method
290
- raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
291
- self.ticket = method.ticket
230
+ # Create/get socket
231
+ socket
232
+
233
+ # Initiate connection
234
+ init_connection
235
+
236
+ # Open connection
237
+ open_connection
238
+
239
+ # Open a channel
240
+ self.channel = get_channel
241
+ channel.open
292
242
 
293
243
  # return status
294
244
  status
@@ -314,20 +264,173 @@ the message, potentially then delivering it to an alternative subscriber.
314
264
  def recover(opts = {})
315
265
 
316
266
  send_frame(
317
- Qrack::Protocol::Basic::Recover.new({ :requeue => false }.merge(opts))
267
+ Qrack::Protocol09::Basic::Recover.new({ :requeue => false }.merge(opts))
318
268
  )
319
269
 
320
270
  end
321
271
 
272
+ =begin rdoc
273
+
274
+ === DESCRIPTION:
275
+
276
+ Requests a specific quality of service. The QoS can be specified for the current channel
277
+ or for all channels on the connection. The particular properties and semantics of a QoS
278
+ method always depend on the content class semantics. Though the QoS method could in principle
279
+ apply to both peers, it is currently meaningful only for the server.
280
+
281
+ ==== Options:
282
+
283
+ * <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
284
+ messages be sent in advance so that when the client finishes processing a message, the following
285
+ message is already held locally, rather than needing to be sent down the channel. Prefetching gives
286
+ a performance improvement. This field specifies the prefetch window size in octets. The server
287
+ will send a message in advance if it is equal to or smaller in size than the available prefetch
288
+ size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
289
+ although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
290
+ is set.
291
+ * <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
292
+ of whole messages. This field may be used in combination with the prefetch-size field; a message
293
+ will only be sent in advance if both prefetch windows (and those at the channel and connection level)
294
+ allow it. The prefetch-count is ignored if the no-ack option is set.
295
+ * <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
296
+ true, they are applied to the entire connection.
297
+
298
+ =end
299
+
300
+ def qos(opts = {})
301
+
302
+ send_frame(
303
+ Qrack::Protocol09::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts))
304
+ )
305
+
306
+ raise Bunny::ProtocolError,
307
+ "Error specifying Quality of Service" unless
308
+ next_method.is_a?(Qrack::Protocol09::Basic::QosOk)
309
+
310
+ # return confirmation
311
+ :qos_ok
312
+ end
313
+
314
+ =begin rdoc
315
+
316
+ === DESCRIPTION:
317
+ This method sets the channel to use standard transactions. The
318
+ client must use this method at least once on a channel before
319
+ using the Commit or Rollback methods.
320
+
321
+ =end
322
+
323
+ def tx_select
324
+ send_frame(Qrack::Protocol09::Tx::Select.new())
325
+
326
+ raise Bunny::ProtocolError,
327
+ "Error initiating transactions for current channel" unless
328
+ next_method.is_a?(Qrack::Protocol09::Tx::SelectOk)
329
+
330
+ # return confirmation
331
+ :select_ok
332
+ end
333
+
334
+ =begin rdoc
335
+
336
+ === DESCRIPTION:
337
+ This method commits all messages published and acknowledged in
338
+ the current transaction. A new transaction starts immediately
339
+ after a commit.
340
+
341
+ =end
342
+
343
+ def tx_commit
344
+ send_frame(Qrack::Protocol09::Tx::Commit.new())
345
+
346
+ raise Bunny::ProtocolError,
347
+ "Error commiting transaction" unless
348
+ next_method.is_a?(Qrack::Protocol09::Tx::CommitOk)
349
+
350
+ # return confirmation
351
+ :commit_ok
352
+ end
353
+
354
+ =begin rdoc
355
+
356
+ === DESCRIPTION:
357
+ This method abandons all messages published and acknowledged in
358
+ the current transaction. A new transaction starts immediately
359
+ after a rollback.
360
+
361
+ =end
362
+
363
+ def tx_rollback
364
+ send_frame(Qrack::Protocol09::Tx::Rollback.new())
365
+
366
+ raise Bunny::ProtocolError,
367
+ "Error rolling back transaction" unless
368
+ next_method.is_a?(Qrack::Protocol09::Tx::RollbackOk)
369
+
370
+ # return confirmation
371
+ :rollback_ok
372
+ end
373
+
322
374
  def logging=(bool)
323
375
  @logging = bool
324
376
  create_logger if @logging
325
377
  end
378
+
379
+ def channels
380
+ @channels ||= {}
381
+ end
382
+
383
+ def get_channel
384
+ channels.each_value do |c|
385
+ return c if (!c.open? and c.number != 0)
386
+ end
387
+ # If no channel to re-use instantiate new one
388
+ Bunny::Channel09.new(self)
389
+ end
390
+
391
+ def init_connection
392
+ write(Qrack::Protocol09::HEADER)
393
+ write([0, Qrack::Protocol09::VERSION_MAJOR, Qrack::Protocol09::VERSION_MINOR, Qrack::Protocol09::REVISION].pack('C4'))
394
+ raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol09::Connection::Start)
395
+ end
396
+
397
+ def open_connection
398
+ send_frame(
399
+ Qrack::Protocol09::Connection::StartOk.new(
400
+ :client_properties => {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
401
+ :mechanism => 'PLAIN',
402
+ :response => "\0" + @user + "\0" + @pass,
403
+ :locale => 'en_US'
404
+ )
405
+ )
406
+
407
+ method = next_method
408
+ raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
409
+
410
+ if method.is_a?(Qrack::Protocol09::Connection::Tune)
411
+ send_frame(
412
+ Qrack::Protocol09::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => 0)
413
+ )
414
+ end
415
+
416
+ send_frame(
417
+ Qrack::Protocol09::Connection::Open.new(:virtual_host => @vhost, :reserved_1 => 0, :reserved_2 => false)
418
+ )
419
+
420
+ raise Bunny::ProtocolError, 'Cannot open connection' unless next_method.is_a?(Qrack::Protocol09::Connection::OpenOk)
421
+ end
422
+
423
+ def close_connection
424
+ send_frame(
425
+ Qrack::Protocol09::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
426
+ )
427
+ raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol09::Connection::CloseOk)
428
+ end
326
429
 
327
430
  private
328
431
 
329
432
  def buffer
330
- @buffer ||= Qrack::Transport::Buffer.new(self)
433
+ @buffer ||= Qrack::Transport09::Buffer.new(self)
331
434
  end
332
435
 
333
436
  def send_command(cmd, *args)