bunny 0.5.2 → 0.5.3
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/bunny.gemspec +4 -2
- data/examples/simple_consumer_08.rb +6 -6
- data/examples/simple_consumer_09.rb +6 -6
- data/lib/bunny.rb +1 -1
- data/lib/bunny/channel08.rb +3 -8
- data/lib/bunny/channel09.rb +3 -8
- data/lib/bunny/client08.rb +217 -344
- data/lib/bunny/client09.rb +175 -301
- data/lib/bunny/exchange08.rb +6 -1
- data/lib/bunny/exchange09.rb +6 -1
- data/lib/bunny/queue08.rb +144 -170
- data/lib/bunny/queue09.rb +160 -185
- data/lib/qrack/channel.rb +18 -0
- data/lib/qrack/client.rb +175 -2
- data/lib/qrack/qrack08.rb +2 -0
- data/lib/qrack/qrack09.rb +2 -0
- data/lib/qrack/queue.rb +53 -0
- data/spec/spec_08/exchange_spec.rb +8 -1
- data/spec/spec_08/queue_spec.rb +26 -0
- data/spec/spec_09/exchange_spec.rb +8 -1
- data/spec/spec_09/queue_spec.rb +26 -0
- metadata +4 -2
    
        data/bunny.gemspec
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            Gem::Specification.new do |s|
         | 
| 2 2 | 
             
              s.name = %q{bunny}
         | 
| 3 | 
            -
              s.version = "0.5. | 
| 3 | 
            +
              s.version = "0.5.3"
         | 
| 4 4 | 
             
              s.authors = ["Chris Duncan"]
         | 
| 5 | 
            -
              s.date = %q{2009- | 
| 5 | 
            +
              s.date = %q{2009-09-07}
         | 
| 6 6 | 
             
              s.description = %q{Another synchronous Ruby AMQP client}
         | 
| 7 7 | 
             
              s.email = %q{celldee@gmail.com}
         | 
| 8 8 | 
             
              s.rubyforge_project = %q{bunny-amqp}
         | 
| @@ -39,6 +39,8 @@ Gem::Specification.new do |s| | |
| 39 39 | 
             
            		"lib/bunny/queue08.rb",
         | 
| 40 40 | 
             
            		"lib/bunny/queue09.rb",
         | 
| 41 41 | 
             
            		"lib/qrack/client.rb",
         | 
| 42 | 
            +
            		"lib/qrack/channel.rb",
         | 
| 43 | 
            +
            		"lib/qrack/queue.rb",
         | 
| 42 44 | 
             
            		"lib/qrack/protocol/protocol08.rb",
         | 
| 43 45 | 
             
            		"lib/qrack/protocol/protocol09.rb",
         | 
| 44 46 | 
             
            		"lib/qrack/protocol/spec08.rb",
         | 
| @@ -48,12 +48,12 @@ q.bind(exch, :key => 'fred') | |
| 48 48 | 
             
            i = 1
         | 
| 49 49 |  | 
| 50 50 | 
             
            # subscribe to queue
         | 
| 51 | 
            -
             | 
| 52 | 
            -
            	 | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 51 | 
            +
            begin
         | 
| 52 | 
            +
            	ret = q.subscribe(:consumer_tag => 'testtag1', :timeout => 30) do |msg|
         | 
| 53 | 
            +
            		puts "#{i.to_s}: #{msg}"
         | 
| 54 | 
            +
            		i+=1
         | 
| 55 | 
            +
            	end
         | 
| 56 | 
            +
            rescue Qrack::ClientTimeout
         | 
| 57 57 | 
             
            	puts '==== simple_consumer_08.rb timed out - closing down ===='
         | 
| 58 58 | 
             
            	q.unsubscribe(:consumer_tag => 'testtag1')
         | 
| 59 59 | 
             
            	# close the connection
         | 
| @@ -48,12 +48,12 @@ q.bind(exch, :key => 'fred') | |
| 48 48 | 
             
            i = 1
         | 
| 49 49 |  | 
| 50 50 | 
             
            # subscribe to queue
         | 
| 51 | 
            -
             | 
| 52 | 
            -
            	 | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 51 | 
            +
            begin
         | 
| 52 | 
            +
            	ret = q.subscribe(:consumer_tag => 'testtag1', :timeout => 30) do |msg|
         | 
| 53 | 
            +
            		puts "#{i.to_s}: #{msg}"
         | 
| 54 | 
            +
            		i+=1
         | 
| 55 | 
            +
            	end
         | 
| 56 | 
            +
            rescue Qrack::ClientTimeout
         | 
| 57 57 | 
             
            	puts '==== simple_consumer_09.rb timed out - closing down ===='
         | 
| 58 58 | 
             
            	q.unsubscribe(:consumer_tag => 'testtag1')
         | 
| 59 59 | 
             
            	# close the connection
         | 
    
        data/lib/bunny.rb
    CHANGED
    
    
    
        data/lib/bunny/channel08.rb
    CHANGED
    
    | @@ -1,13 +1,8 @@ | |
| 1 1 | 
             
            module Bunny
         | 
| 2 | 
            -
            	class Channel
         | 
| 3 | 
            -
            		attr_accessor :number, :active
         | 
| 4 | 
            -
            		attr_reader :client
         | 
| 2 | 
            +
            	class Channel < Qrack::Channel
         | 
| 5 3 |  | 
| 6 | 
            -
            		def initialize(client | 
| 7 | 
            -
            			 | 
| 8 | 
            -
            			zero ? @number = 0 : @number = client.channels.size
         | 
| 9 | 
            -
            			@active = false
         | 
| 10 | 
            -
            			client.channels[@number] ||= self
         | 
| 4 | 
            +
            		def initialize(client)
         | 
| 5 | 
            +
            			super
         | 
| 11 6 | 
             
            		end
         | 
| 12 7 |  | 
| 13 8 | 
             
            		def open
         | 
    
        data/lib/bunny/channel09.rb
    CHANGED
    
    | @@ -1,13 +1,8 @@ | |
| 1 1 | 
             
            module Bunny
         | 
| 2 | 
            -
            	class Channel09
         | 
| 3 | 
            -
            		attr_accessor :number, :active
         | 
| 4 | 
            -
            		attr_reader :client
         | 
| 2 | 
            +
            	class Channel09 < Qrack::Channel
         | 
| 5 3 |  | 
| 6 | 
            -
            		def initialize(client | 
| 7 | 
            -
            			 | 
| 8 | 
            -
            			zero ? @number = 0 : @number = client.channels.size
         | 
| 9 | 
            -
            			@active = false
         | 
| 10 | 
            -
            			client.channels[@number] ||= self
         | 
| 4 | 
            +
            		def initialize(client)
         | 
| 5 | 
            +
            			super
         | 
| 11 6 | 
             
            		end
         | 
| 12 7 |  | 
| 13 8 | 
             
            		def open
         | 
    
        data/lib/bunny/client08.rb
    CHANGED
    
    | @@ -41,30 +41,30 @@ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_ | |
| 41 41 | 
             
            =end
         | 
| 42 42 |  | 
| 43 43 | 
             
                def initialize(opts = {})
         | 
| 44 | 
            +
            			super
         | 
| 44 45 | 
             
            			@spec = '0-8'
         | 
| 45 | 
            -
            			@host = opts[:host] || 'localhost'
         | 
| 46 46 | 
             
            			@port = opts[:port] || Qrack::Protocol::PORT
         | 
| 47 | 
            -
                  @user   = opts[:user]  || 'guest'
         | 
| 48 | 
            -
                  @pass   = opts[:pass]  || 'guest'
         | 
| 49 | 
            -
                  @vhost  = opts[:vhost] || '/'
         | 
| 50 | 
            -
            			@logfile = opts[:logfile] || nil
         | 
| 51 | 
            -
            			@logging = opts[:logging] || false
         | 
| 52 47 | 
             
                  @insist = opts[:insist]
         | 
| 53 | 
            -
                  @status = :not_connected
         | 
| 54 | 
            -
            			@frame_max = opts[:frame_max] || 131072
         | 
| 55 | 
            -
            			@channel_max = opts[:channel_max] || 0
         | 
| 56 | 
            -
            			@heartbeat = opts[:heartbeat] || 0
         | 
| 57 | 
            -
            			@logger = nil
         | 
| 58 | 
            -
            			create_logger if @logging
         | 
| 59 | 
            -
            			@channels = []
         | 
| 60 | 
            -
            			# Create channel 0
         | 
| 61 | 
            -
                  @channel = Bunny::Channel.new(self, true)
         | 
| 62 | 
            -
            			@exchanges = {}
         | 
| 63 | 
            -
            			@queues = {}
         | 
| 64 | 
            -
            			@heartbeat_in = false
         | 
| 65 | 
            -
            			@connecting = false
         | 
| 66 48 | 
             
                end
         | 
| 67 49 |  | 
| 50 | 
            +
            		def close_connection
         | 
| 51 | 
            +
            			# Set client channel to zero
         | 
| 52 | 
            +
                  switch_channel(0)
         | 
| 53 | 
            +
            		
         | 
| 54 | 
            +
            			send_frame(
         | 
| 55 | 
            +
            	      Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
         | 
| 56 | 
            +
            	    )
         | 
| 57 | 
            +
            	    raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            		def create_channel
         | 
| 61 | 
            +
            			channels.each do |c|
         | 
| 62 | 
            +
            				return c if (!c.open? and c.number != 0)
         | 
| 63 | 
            +
            			end
         | 
| 64 | 
            +
            			# If no channel to re-use instantiate new one
         | 
| 65 | 
            +
            			Bunny::Channel.new(self)
         | 
| 66 | 
            +
            		end
         | 
| 67 | 
            +
             | 
| 68 68 | 
             
            =begin rdoc
         | 
| 69 69 |  | 
| 70 70 | 
             
            === DESCRIPTION:
         | 
| @@ -95,6 +95,135 @@ Exchange | |
| 95 95 | 
             
            			return exchanges[name] if exchanges.has_key?(name)
         | 
| 96 96 | 
             
            			Bunny::Exchange.new(self, name, opts)
         | 
| 97 97 | 
             
            		end
         | 
| 98 | 
            +
            		
         | 
| 99 | 
            +
            		def init_connection
         | 
| 100 | 
            +
            			write(Qrack::Protocol::HEADER)
         | 
| 101 | 
            +
                  write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            			frame = next_frame
         | 
| 104 | 
            +
            			if frame.nil? or !frame.payload.is_a?(Qrack::Protocol::Connection::Start)
         | 
| 105 | 
            +
            				raise Bunny::ProtocolError, 'Connection initiation failed'
         | 
| 106 | 
            +
            			end
         | 
| 107 | 
            +
            		end
         | 
| 108 | 
            +
            		
         | 
| 109 | 
            +
            		def next_frame(opts = {})
         | 
| 110 | 
            +
                  frame = nil
         | 
| 111 | 
            +
            			
         | 
| 112 | 
            +
            			case
         | 
| 113 | 
            +
            				when channel.frame_buffer.size > 0
         | 
| 114 | 
            +
            					frame = channel.frame_buffer.shift
         | 
| 115 | 
            +
            				when opts.has_key?(:timeout)
         | 
| 116 | 
            +
            	        Timeout::timeout(opts[:timeout], Qrack::ClientTimeout) do
         | 
| 117 | 
            +
            	          frame = Qrack::Transport::Frame.parse(buffer)
         | 
| 118 | 
            +
            	        end
         | 
| 119 | 
            +
            	      else
         | 
| 120 | 
            +
            	        frame = Qrack::Transport::Frame.parse(buffer)
         | 
| 121 | 
            +
                  end
         | 
| 122 | 
            +
            			
         | 
| 123 | 
            +
            			@logger.info("received") { frame } if @logging
         | 
| 124 | 
            +
            						
         | 
| 125 | 
            +
            			raise Bunny::ConnectionError, 'No connection to server' if (frame.nil? and !connecting?)
         | 
| 126 | 
            +
            			
         | 
| 127 | 
            +
            			# Monitor server activity and discard heartbeats
         | 
| 128 | 
            +
            			@message_in = true
         | 
| 129 | 
            +
            			
         | 
| 130 | 
            +
            			case
         | 
| 131 | 
            +
            				when frame.is_a?(Qrack::Transport::Heartbeat)
         | 
| 132 | 
            +
            					next_frame(opts)
         | 
| 133 | 
            +
            				when frame.nil?
         | 
| 134 | 
            +
            					frame
         | 
| 135 | 
            +
            				when ((frame.channel != channel.number) and (frame.channel != 0))
         | 
| 136 | 
            +
            					channel.frame_buffer << frame
         | 
| 137 | 
            +
            					next_frame(opts)
         | 
| 138 | 
            +
            				else
         | 
| 139 | 
            +
            					frame
         | 
| 140 | 
            +
            			end
         | 
| 141 | 
            +
            			
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            		def open_connection
         | 
| 145 | 
            +
            			send_frame(
         | 
| 146 | 
            +
                    Qrack::Protocol::Connection::StartOk.new(
         | 
| 147 | 
            +
                      {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
         | 
| 148 | 
            +
                      'AMQPLAIN',
         | 
| 149 | 
            +
                      {:LOGIN => @user, :PASSWORD => @pass},
         | 
| 150 | 
            +
                      'en_US'
         | 
| 151 | 
            +
                    )
         | 
| 152 | 
            +
                  )
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  frame = next_frame
         | 
| 155 | 
            +
            			raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if frame.nil?
         | 
| 156 | 
            +
            			
         | 
| 157 | 
            +
            			method = frame.payload
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                  if method.is_a?(Qrack::Protocol::Connection::Tune)
         | 
| 160 | 
            +
                    send_frame(
         | 
| 161 | 
            +
                      Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => @heartbeat)
         | 
| 162 | 
            +
                    )
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  send_frame(
         | 
| 166 | 
            +
                    Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
         | 
| 167 | 
            +
                  )
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  case method = next_method
         | 
| 170 | 
            +
                  when Qrack::Protocol::Connection::OpenOk
         | 
| 171 | 
            +
                    return :ok
         | 
| 172 | 
            +
                  when Qrack::Protocol::Connection::Redirect
         | 
| 173 | 
            +
            				raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
         | 
| 174 | 
            +
            				
         | 
| 175 | 
            +
                    @host, @port = method.host.split(':')
         | 
| 176 | 
            +
                    close_socket
         | 
| 177 | 
            +
                  else
         | 
| 178 | 
            +
                    raise Bunny::ProtocolError, 'Cannot open connection'
         | 
| 179 | 
            +
                  end
         | 
| 180 | 
            +
            		end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            =begin rdoc
         | 
| 183 | 
            +
             | 
| 184 | 
            +
            === DESCRIPTION:
         | 
| 185 | 
            +
             | 
| 186 | 
            +
            Requests a specific quality of service. The QoS can be specified for the current channel
         | 
| 187 | 
            +
            or for all channels on the connection. The particular properties and semantics of a QoS
         | 
| 188 | 
            +
            method always depend on the content class semantics. Though the QoS method could in principle
         | 
| 189 | 
            +
            apply to both peers, it is currently meaningful only for the server.
         | 
| 190 | 
            +
             | 
| 191 | 
            +
            ==== Options:
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            * <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
         | 
| 194 | 
            +
            messages be sent in advance so that when the client finishes processing a message, the following
         | 
| 195 | 
            +
            message is already held locally, rather than needing to be sent down the channel. Prefetching gives
         | 
| 196 | 
            +
            a performance improvement. This field specifies the prefetch window size in octets. The server
         | 
| 197 | 
            +
            will send a message in advance if it is equal to or smaller in size than the available prefetch
         | 
| 198 | 
            +
            size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
         | 
| 199 | 
            +
            although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
         | 
| 200 | 
            +
            is set.
         | 
| 201 | 
            +
            * <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
         | 
| 202 | 
            +
            of whole messages. This field may be used in combination with the prefetch-size field; a message
         | 
| 203 | 
            +
            will only be sent in advance if both prefetch windows (and those at the channel and connection level)
         | 
| 204 | 
            +
            allow it. The prefetch-count is ignored if the no-ack option is set.
         | 
| 205 | 
            +
            * <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
         | 
| 206 | 
            +
            true, they are applied to the entire connection.
         | 
| 207 | 
            +
             | 
| 208 | 
            +
            ==== RETURNS:
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            <tt>:qos_ok</tt> if successful.
         | 
| 211 | 
            +
             | 
| 212 | 
            +
            =end
         | 
| 213 | 
            +
             | 
| 214 | 
            +
            		def qos(opts = {})
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                  send_frame(
         | 
| 217 | 
            +
                    Qrack::Protocol::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts))
         | 
| 218 | 
            +
                  )
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                  raise Bunny::ProtocolError,
         | 
| 221 | 
            +
                    "Error specifying Quality of Service" unless
         | 
| 222 | 
            +
             				next_method.is_a?(Qrack::Protocol::Basic::QosOk)
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                  # return confirmation
         | 
| 225 | 
            +
                  :qos_ok
         | 
| 226 | 
            +
                end
         | 
| 98 227 |  | 
| 99 228 | 
             
            =begin rdoc
         | 
| 100 229 |  | 
| @@ -140,131 +269,63 @@ Queue | |
| 140 269 |  | 
| 141 270 | 
             
                  Bunny::Queue.new(self, name, opts)
         | 
| 142 271 | 
             
            	  end
         | 
| 143 | 
            -
            		
         | 
| 144 | 
            -
            		def send_heartbeat
         | 
| 145 | 
            -
            			# Create a new heartbeat frame
         | 
| 146 | 
            -
            			hb = Qrack::Transport::Heartbeat.new('')		
         | 
| 147 | 
            -
            			# Channel 0 must be used
         | 
| 148 | 
            -
            			switch_channel(0) if @channel.number > 0			
         | 
| 149 | 
            -
            			# Send the heartbeat to server
         | 
| 150 | 
            -
            			send_frame(hb)
         | 
| 151 | 
            -
            		end
         | 
| 152 | 
            -
             | 
| 153 | 
            -
                def send_frame(*args)
         | 
| 154 | 
            -
                  args.each do |data|
         | 
| 155 | 
            -
                    data.ticket  = ticket if ticket and data.respond_to?(:ticket=)
         | 
| 156 | 
            -
                    data         = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport::Frame)
         | 
| 157 | 
            -
                    data.channel = channel.number
         | 
| 158 | 
            -
             | 
| 159 | 
            -
                    @logger.info("send") { data } if @logging
         | 
| 160 | 
            -
                    write(data.to_s)
         | 
| 161 | 
            -
                  end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
                  nil
         | 
| 164 | 
            -
                end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                def next_frame(opts = {})
         | 
| 167 | 
            -
            			secs = opts[:timeout] || 0
         | 
| 168 | 
            -
            			
         | 
| 169 | 
            -
            			begin
         | 
| 170 | 
            -
            				Timeout::timeout(secs) do
         | 
| 171 | 
            -
            					@frame = Qrack::Transport::Frame.parse(buffer)
         | 
| 172 | 
            -
            				end
         | 
| 173 | 
            -
            			rescue Timeout::Error
         | 
| 174 | 
            -
            				return :timed_out
         | 
| 175 | 
            -
            			end
         | 
| 176 | 
            -
            			
         | 
| 177 | 
            -
            			@logger.info("received") { @frame } if @logging
         | 
| 178 | 
            -
            						
         | 
| 179 | 
            -
            			raise Bunny::ConnectionError, 'No connection to server' if (@frame.nil? and !connecting?)
         | 
| 180 | 
            -
             | 
| 181 | 
            -
            			if @frame.is_a?(Qrack::Transport::Heartbeat)
         | 
| 182 | 
            -
            				@heartbeat_in = true
         | 
| 183 | 
            -
            				next_frame
         | 
| 184 | 
            -
            			end
         | 
| 185 | 
            -
            			
         | 
| 186 | 
            -
            			@frame
         | 
| 187 | 
            -
                end
         | 
| 188 | 
            -
             | 
| 189 | 
            -
                def next_payload
         | 
| 190 | 
            -
                  frame = next_frame			
         | 
| 191 | 
            -
            			frame.payload
         | 
| 192 | 
            -
                end
         | 
| 193 | 
            -
             | 
| 194 | 
            -
            		alias next_method next_payload
         | 
| 195 | 
            -
            		
         | 
| 196 | 
            -
            =begin rdoc
         | 
| 197 | 
            -
             | 
| 198 | 
            -
            === DESCRIPTION:
         | 
| 199 | 
            -
             | 
| 200 | 
            -
            Checks to see whether or not an undeliverable message has been returned as a result of a publish
         | 
| 201 | 
            -
            with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
         | 
| 202 | 
            -
             | 
| 203 | 
            -
            ==== OPTIONS:
         | 
| 204 | 
            -
             | 
| 205 | 
            -
            * <tt>:timeout => number of seconds (default = 0.1) - The method will wait for a return
         | 
| 206 | 
            -
              message until this timeout interval is reached.
         | 
| 207 | 
            -
             | 
| 208 | 
            -
            ==== RETURNS:
         | 
| 209 | 
            -
             | 
| 210 | 
            -
            <tt>:no_return</tt> if message was not returned before timeout .
         | 
| 211 | 
            -
            <tt>{:header, :return_details, :payload}</tt> if message is returned. <tt>:return_details</tt> is
         | 
| 212 | 
            -
            a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
         | 
| 213 | 
            -
             | 
| 214 | 
            -
            =end
         | 
| 215 | 
            -
            		
         | 
| 216 | 
            -
            		def returned_message(opts = {})
         | 
| 217 | 
            -
            			secs = opts[:timeout] || 0.1		
         | 
| 218 | 
            -
            			frame = next_frame(:timeout => secs)
         | 
| 219 | 
            -
            			
         | 
| 220 | 
            -
            			if frame.is_a?(Symbol)
         | 
| 221 | 
            -
            				return :no_return if frame == :timed_out
         | 
| 222 | 
            -
            			end
         | 
| 223 | 
            -
             | 
| 224 | 
            -
            			method = frame.payload
         | 
| 225 | 
            -
            			header = next_payload
         | 
| 226 | 
            -
            	    msg = next_payload
         | 
| 227 | 
            -
            	    raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
         | 
| 228 | 
            -
            			
         | 
| 229 | 
            -
            			# Return the message and related info
         | 
| 230 | 
            -
            			{:header => header, :payload => msg, :return_details => method.arguments}
         | 
| 231 | 
            -
            		end
         | 
| 232 272 |  | 
| 233 273 | 
             
            =begin rdoc
         | 
| 234 274 |  | 
| 235 275 | 
             
            === DESCRIPTION:
         | 
| 236 276 |  | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 277 | 
            +
            Asks the broker to redeliver all unacknowledged messages on a specified channel. Zero or
         | 
| 278 | 
            +
            more messages may be redelivered.
         | 
| 239 279 |  | 
| 240 | 
            -
            ====  | 
| 280 | 
            +
            ==== Options:
         | 
| 241 281 |  | 
| 242 | 
            -
            <tt>: | 
| 282 | 
            +
            * <tt>:requeue => true or false (_default_)</tt> - If set to _false_, the message will be
         | 
| 283 | 
            +
            redelivered to the original recipient. If set to _true_, the server will attempt to requeue
         | 
| 284 | 
            +
            the message, potentially then delivering it to an alternative subscriber.
         | 
| 243 285 |  | 
| 244 286 | 
             
            =end
         | 
| 245 287 |  | 
| 246 | 
            -
             | 
| 247 | 
            -
            			# Close all active channels
         | 
| 248 | 
            -
            			channels.each do |c|
         | 
| 249 | 
            -
            				c.close if c.open?
         | 
| 250 | 
            -
            			end
         | 
| 288 | 
            +
            		def recover(opts = {})
         | 
| 251 289 |  | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 290 | 
            +
            	    send_frame(
         | 
| 291 | 
            +
            	      Qrack::Protocol::Basic::Recover.new({ :requeue => false }.merge(opts))
         | 
| 292 | 
            +
            	    )
         | 
| 254 293 |  | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 294 | 
            +
            	  end
         | 
| 295 | 
            +
            	
         | 
| 296 | 
            +
            		def request_access
         | 
| 297 | 
            +
            			send_frame(
         | 
| 298 | 
            +
                    Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
         | 
| 299 | 
            +
                  )
         | 
| 300 | 
            +
                  method = next_method
         | 
| 301 | 
            +
                  raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
         | 
| 302 | 
            +
                  self.ticket = method.ticket
         | 
| 303 | 
            +
            		end
         | 
| 304 | 
            +
            	
         | 
| 305 | 
            +
            		def send_frame(*args)
         | 
| 306 | 
            +
                  args.each do |data|
         | 
| 307 | 
            +
                    data.ticket  = ticket if ticket and data.respond_to?(:ticket=)
         | 
| 308 | 
            +
                    data         = data.to_frame(channel.number) unless data.is_a?(Qrack::Transport::Frame)
         | 
| 309 | 
            +
                    data.channel = channel.number
         | 
| 258 310 |  | 
| 259 | 
            -
             | 
| 311 | 
            +
                    @logger.info("send") { data } if @logging
         | 
| 312 | 
            +
                    write(data.to_s)
         | 
| 260 313 |  | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 314 | 
            +
            				# Monitor client activity for heartbeat purposes
         | 
| 315 | 
            +
            				@message_out = true
         | 
| 316 | 
            +
                  end
         | 
| 264 317 |  | 
| 265 | 
            -
             | 
| 266 | 
            -
                  send_command(:write, *args)
         | 
| 318 | 
            +
                  nil
         | 
| 267 319 | 
             
                end
         | 
| 320 | 
            +
            		
         | 
| 321 | 
            +
            		def send_heartbeat
         | 
| 322 | 
            +
            			# Create a new heartbeat frame
         | 
| 323 | 
            +
            			hb = Qrack::Transport::Heartbeat.new('')		
         | 
| 324 | 
            +
            			# Channel 0 must be used
         | 
| 325 | 
            +
            			switch_channel(0) if @channel.number > 0			
         | 
| 326 | 
            +
            			# Send the heartbeat to server
         | 
| 327 | 
            +
            			send_frame(hb)
         | 
| 328 | 
            +
            		end
         | 
| 268 329 |  | 
| 269 330 | 
             
            =begin rdoc
         | 
| 270 331 |  | 
| @@ -310,101 +371,20 @@ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to < | |
| 310 371 |  | 
| 311 372 | 
             
            =begin rdoc
         | 
| 312 373 |  | 
| 313 | 
            -
            === DESCRIPTION:
         | 
| 314 | 
            -
             | 
| 315 | 
            -
            Asks the broker to redeliver all unacknowledged messages on a specified channel. Zero or
         | 
| 316 | 
            -
            more messages may be redelivered.
         | 
| 317 | 
            -
             | 
| 318 | 
            -
            ==== Options:
         | 
| 319 | 
            -
             | 
| 320 | 
            -
            * <tt>:requeue => true or false (_default_)</tt> - If set to _false_, the message will be
         | 
| 321 | 
            -
            redelivered to the original recipient. If set to _true_, the server will attempt to requeue
         | 
| 322 | 
            -
            the message, potentially then delivering it to an alternative subscriber.
         | 
| 323 | 
            -
             | 
| 324 | 
            -
            =end
         | 
| 325 | 
            -
             | 
| 326 | 
            -
            		def recover(opts = {})
         | 
| 327 | 
            -
             | 
| 328 | 
            -
            	    send_frame(
         | 
| 329 | 
            -
            	      Qrack::Protocol::Basic::Recover.new({ :requeue => false }.merge(opts))
         | 
| 330 | 
            -
            	    )
         | 
| 331 | 
            -
             | 
| 332 | 
            -
            	  end
         | 
| 333 | 
            -
             | 
| 334 | 
            -
            =begin rdoc
         | 
| 335 | 
            -
             | 
| 336 | 
            -
            === DESCRIPTION:
         | 
| 337 | 
            -
             | 
| 338 | 
            -
            Requests a specific quality of service. The QoS can be specified for the current channel
         | 
| 339 | 
            -
            or for all channels on the connection. The particular properties and semantics of a QoS
         | 
| 340 | 
            -
            method always depend on the content class semantics. Though the QoS method could in principle
         | 
| 341 | 
            -
            apply to both peers, it is currently meaningful only for the server.
         | 
| 342 | 
            -
             | 
| 343 | 
            -
            ==== Options:
         | 
| 344 | 
            -
             | 
| 345 | 
            -
            * <tt>:prefetch_size => size in no. of octets (default = 0)</tt> - The client can request that
         | 
| 346 | 
            -
            messages be sent in advance so that when the client finishes processing a message, the following
         | 
| 347 | 
            -
            message is already held locally, rather than needing to be sent down the channel. Prefetching gives
         | 
| 348 | 
            -
            a performance improvement. This field specifies the prefetch window size in octets. The server
         | 
| 349 | 
            -
            will send a message in advance if it is equal to or smaller in size than the available prefetch
         | 
| 350 | 
            -
            size (and also falls into other prefetch limits). May be set to zero, meaning "no specific limit",
         | 
| 351 | 
            -
            although other prefetch limits may still apply. The prefetch-size is ignored if the no-ack option
         | 
| 352 | 
            -
            is set.
         | 
| 353 | 
            -
            * <tt>:prefetch_count => no. messages (default = 1)</tt> - Specifies a prefetch window in terms
         | 
| 354 | 
            -
            of whole messages. This field may be used in combination with the prefetch-size field; a message
         | 
| 355 | 
            -
            will only be sent in advance if both prefetch windows (and those at the channel and connection level)
         | 
| 356 | 
            -
            allow it. The prefetch-count is ignored if the no-ack option is set.
         | 
| 357 | 
            -
            * <tt>:global => true or false (_default_)</tt> - By default the QoS settings apply to the current channel only. If set to
         | 
| 358 | 
            -
            true, they are applied to the entire connection.
         | 
| 359 | 
            -
             | 
| 360 | 
            -
            =end
         | 
| 361 | 
            -
            			
         | 
| 362 | 
            -
            		def qos(opts = {})
         | 
| 363 | 
            -
                  
         | 
| 364 | 
            -
                  send_frame(
         | 
| 365 | 
            -
                    Qrack::Protocol::Basic::Qos.new({ :prefetch_size => 0, :prefetch_count => 1, :global => false }.merge(opts))
         | 
| 366 | 
            -
                  )
         | 
| 367 | 
            -
             | 
| 368 | 
            -
                  raise Bunny::ProtocolError,
         | 
| 369 | 
            -
                    "Error specifying Quality of Service" unless
         | 
| 370 | 
            -
             				next_method.is_a?(Qrack::Protocol::Basic::QosOk)
         | 
| 371 | 
            -
                  
         | 
| 372 | 
            -
                  # return confirmation
         | 
| 373 | 
            -
                  :qos_ok
         | 
| 374 | 
            -
                end
         | 
| 375 | 
            -
             | 
| 376 | 
            -
            =begin rdoc
         | 
| 377 | 
            -
             | 
| 378 | 
            -
            === DESCRIPTION:
         | 
| 379 | 
            -
            This method sets the channel to use standard transactions. The
         | 
| 380 | 
            -
            client must use this method at least once on a channel before
         | 
| 381 | 
            -
            using the Commit or Rollback methods.
         | 
| 382 | 
            -
             | 
| 383 | 
            -
            =end
         | 
| 384 | 
            -
             | 
| 385 | 
            -
            		def tx_select
         | 
| 386 | 
            -
            			send_frame(Qrack::Protocol::Tx::Select.new())
         | 
| 387 | 
            -
            			
         | 
| 388 | 
            -
            			raise Bunny::ProtocolError,
         | 
| 389 | 
            -
                    "Error initiating transactions for current channel" unless
         | 
| 390 | 
            -
             				next_method.is_a?(Qrack::Protocol::Tx::SelectOk)
         | 
| 391 | 
            -
             | 
| 392 | 
            -
            			# return confirmation
         | 
| 393 | 
            -
            			:select_ok
         | 
| 394 | 
            -
            		end
         | 
| 395 | 
            -
            		
         | 
| 396 | 
            -
            =begin rdoc
         | 
| 397 | 
            -
             | 
| 398 374 | 
             
            === DESCRIPTION:
         | 
| 399 375 | 
             
            This method commits all messages published and acknowledged in
         | 
| 400 376 | 
             
            the current transaction. A new transaction starts immediately
         | 
| 401 377 | 
             
            after a commit.
         | 
| 402 378 |  | 
| 379 | 
            +
            ==== RETURNS:
         | 
| 380 | 
            +
             | 
| 381 | 
            +
            <tt>:commit_ok</tt> if successful.
         | 
| 382 | 
            +
             | 
| 403 383 | 
             
            =end
         | 
| 404 | 
            -
             | 
| 384 | 
            +
             | 
| 405 385 | 
             
            		def tx_commit
         | 
| 406 386 | 
             
            			send_frame(Qrack::Protocol::Tx::Commit.new())
         | 
| 407 | 
            -
             | 
| 387 | 
            +
             | 
| 408 388 | 
             
            			raise Bunny::ProtocolError,
         | 
| 409 389 | 
             
                    "Error commiting transaction" unless
         | 
| 410 390 | 
             
             				next_method.is_a?(Qrack::Protocol::Tx::CommitOk)
         | 
| @@ -420,11 +400,15 @@ This method abandons all messages published and acknowledged in | |
| 420 400 | 
             
            the current transaction. A new transaction starts immediately
         | 
| 421 401 | 
             
            after a rollback.
         | 
| 422 402 |  | 
| 403 | 
            +
            ==== RETURNS:
         | 
| 404 | 
            +
             | 
| 405 | 
            +
            <tt>:rollback_ok</tt> if successful.
         | 
| 406 | 
            +
             | 
| 423 407 | 
             
            =end
         | 
| 424 | 
            -
             | 
| 408 | 
            +
             | 
| 425 409 | 
             
            		def tx_rollback
         | 
| 426 410 | 
             
            			send_frame(Qrack::Protocol::Tx::Rollback.new())
         | 
| 427 | 
            -
             | 
| 411 | 
            +
             | 
| 428 412 | 
             
            			raise Bunny::ProtocolError,
         | 
| 429 413 | 
             
                    "Error rolling back transaction" unless
         | 
| 430 414 | 
             
             				next_method.is_a?(Qrack::Protocol::Tx::RollbackOk)
         | 
| @@ -432,98 +416,29 @@ after a rollback. | |
| 432 416 | 
             
            			# return confirmation
         | 
| 433 417 | 
             
            			:rollback_ok
         | 
| 434 418 | 
             
            		end
         | 
| 435 | 
            -
            	
         | 
| 436 | 
            -
            		def logging=(bool)
         | 
| 437 | 
            -
            			@logging = bool
         | 
| 438 | 
            -
            			create_logger if @logging
         | 
| 439 | 
            -
            		end
         | 
| 440 | 
            -
            		
         | 
| 441 | 
            -
            		def create_channel
         | 
| 442 | 
            -
            			channels.each do |c|
         | 
| 443 | 
            -
            				return c if (!c.open? and c.number != 0)
         | 
| 444 | 
            -
            			end
         | 
| 445 | 
            -
            			# If no channel to re-use instantiate new one
         | 
| 446 | 
            -
            			Bunny::Channel.new(self)
         | 
| 447 | 
            -
            		end
         | 
| 448 | 
            -
            		
         | 
| 449 | 
            -
            		def switch_channel(chann)
         | 
| 450 | 
            -
            			if (0...channels.size).include? chann
         | 
| 451 | 
            -
            				@channel = channels[chann]
         | 
| 452 | 
            -
            				chann
         | 
| 453 | 
            -
            			else
         | 
| 454 | 
            -
            				raise RuntimeError, "Invalid channel number - #{chann}"
         | 
| 455 | 
            -
            			end
         | 
| 456 | 
            -
            		end
         | 
| 457 | 
            -
            		
         | 
| 458 | 
            -
            		def connecting?
         | 
| 459 | 
            -
            			connecting
         | 
| 460 | 
            -
            		end
         | 
| 461 | 
            -
            		
         | 
| 462 | 
            -
            		def init_connection
         | 
| 463 | 
            -
            			write(Qrack::Protocol::HEADER)
         | 
| 464 | 
            -
                  write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
         | 
| 465 419 |  | 
| 466 | 
            -
             | 
| 467 | 
            -
            			if frame.nil? or !frame.payload.is_a?(Qrack::Protocol::Connection::Start)
         | 
| 468 | 
            -
            				raise Bunny::ProtocolError, 'Connection initiation failed'
         | 
| 469 | 
            -
            			end
         | 
| 470 | 
            -
            		end
         | 
| 471 | 
            -
            		
         | 
| 472 | 
            -
            		def open_connection
         | 
| 473 | 
            -
            			send_frame(
         | 
| 474 | 
            -
                    Qrack::Protocol::Connection::StartOk.new(
         | 
| 475 | 
            -
                      {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
         | 
| 476 | 
            -
                      'AMQPLAIN',
         | 
| 477 | 
            -
                      {:LOGIN => @user, :PASSWORD => @pass},
         | 
| 478 | 
            -
                      'en_US'
         | 
| 479 | 
            -
                    )
         | 
| 480 | 
            -
                  )
         | 
| 420 | 
            +
            =begin rdoc
         | 
| 481 421 |  | 
| 482 | 
            -
             | 
| 483 | 
            -
             | 
| 484 | 
            -
             | 
| 485 | 
            -
             | 
| 422 | 
            +
            === DESCRIPTION:
         | 
| 423 | 
            +
            This method sets the channel to use standard transactions. The
         | 
| 424 | 
            +
            client must use this method at least once on a channel before
         | 
| 425 | 
            +
            using the Commit or Rollback methods.
         | 
| 486 426 |  | 
| 487 | 
            -
             | 
| 488 | 
            -
                    send_frame(
         | 
| 489 | 
            -
                      Qrack::Protocol::Connection::TuneOk.new( :channel_max => @channel_max, :frame_max => @frame_max, :heartbeat => @heartbeat)
         | 
| 490 | 
            -
                    )
         | 
| 491 | 
            -
                  end
         | 
| 427 | 
            +
            ==== RETURNS:
         | 
| 492 428 |  | 
| 493 | 
            -
             | 
| 494 | 
            -
                    Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
         | 
| 495 | 
            -
                  )
         | 
| 429 | 
            +
            <tt>:select_ok</tt> if successful.
         | 
| 496 430 |  | 
| 497 | 
            -
             | 
| 498 | 
            -
                  when Qrack::Protocol::Connection::OpenOk
         | 
| 499 | 
            -
                    return :ok
         | 
| 500 | 
            -
                  when Qrack::Protocol::Connection::Redirect
         | 
| 501 | 
            -
            				raise Bunny::ConnectionError, "Cannot connect to the specified server - host: #{@host}, port: #{@port}" if @insist
         | 
| 502 | 
            -
            				
         | 
| 503 | 
            -
                    @host, @port = method.host.split(':')
         | 
| 504 | 
            -
                    close_socket
         | 
| 505 | 
            -
                  else
         | 
| 506 | 
            -
                    raise Bunny::ProtocolError, 'Cannot open connection'
         | 
| 507 | 
            -
                  end
         | 
| 508 | 
            -
            		end
         | 
| 431 | 
            +
            =end
         | 
| 509 432 |  | 
| 510 | 
            -
            		def  | 
| 511 | 
            -
            			 | 
| 512 | 
            -
             | 
| 513 | 
            -
             | 
| 514 | 
            -
             | 
| 515 | 
            -
             | 
| 516 | 
            -
            	    )
         | 
| 517 | 
            -
            	    raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
         | 
| 518 | 
            -
                end
         | 
| 433 | 
            +
            		def tx_select
         | 
| 434 | 
            +
            			send_frame(Qrack::Protocol::Tx::Select.new())
         | 
| 435 | 
            +
            			
         | 
| 436 | 
            +
            			raise Bunny::ProtocolError,
         | 
| 437 | 
            +
                    "Error initiating transactions for current channel" unless
         | 
| 438 | 
            +
             				next_method.is_a?(Qrack::Protocol::Tx::SelectOk)
         | 
| 519 439 |  | 
| 520 | 
            -
             | 
| 521 | 
            -
            			 | 
| 522 | 
            -
                    Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
         | 
| 523 | 
            -
                  )
         | 
| 524 | 
            -
                  method = next_method
         | 
| 525 | 
            -
                  raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
         | 
| 526 | 
            -
                  self.ticket = method.ticket
         | 
| 440 | 
            +
            			# return confirmation
         | 
| 441 | 
            +
            			:select_ok
         | 
| 527 442 | 
             
            		end
         | 
| 528 443 |  | 
| 529 444 | 
             
              private
         | 
| @@ -532,47 +447,5 @@ after a rollback. | |
| 532 447 | 
             
                  @buffer ||= Qrack::Transport::Buffer.new(self)
         | 
| 533 448 | 
             
                end
         | 
| 534 449 |  | 
| 535 | 
            -
                def send_command(cmd, *args)
         | 
| 536 | 
            -
                  begin
         | 
| 537 | 
            -
            				raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
         | 
| 538 | 
            -
                    @socket.__send__(cmd, *args)
         | 
| 539 | 
            -
                  rescue Errno::EPIPE, IOError => e
         | 
| 540 | 
            -
                    raise Bunny::ServerDownError, e.message
         | 
| 541 | 
            -
                  end
         | 
| 542 | 
            -
                end
         | 
| 543 | 
            -
             | 
| 544 | 
            -
                def socket
         | 
| 545 | 
            -
                  return @socket if @socket and (@status == :connected) and not @socket.closed?
         | 
| 546 | 
            -
             | 
| 547 | 
            -
                  begin  
         | 
| 548 | 
            -
                    # Attempt to connect.
         | 
| 549 | 
            -
                    @socket = timeout(CONNECT_TIMEOUT) do
         | 
| 550 | 
            -
                      TCPSocket.new(host, port)
         | 
| 551 | 
            -
                    end
         | 
| 552 | 
            -
             | 
| 553 | 
            -
                    if Socket.constants.include? 'TCP_NODELAY'
         | 
| 554 | 
            -
                      @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
         | 
| 555 | 
            -
                    end
         | 
| 556 | 
            -
                  rescue => e
         | 
| 557 | 
            -
                    @status = :not_connected
         | 
| 558 | 
            -
                    raise Bunny::ServerDownError, e.message
         | 
| 559 | 
            -
                  end
         | 
| 560 | 
            -
             | 
| 561 | 
            -
                  @socket
         | 
| 562 | 
            -
                end
         | 
| 563 | 
            -
             | 
| 564 | 
            -
                def close_socket(reason=nil)
         | 
| 565 | 
            -
                  # Close the socket. The server is not considered dead.
         | 
| 566 | 
            -
                  @socket.close if @socket and not @socket.closed?
         | 
| 567 | 
            -
                  @socket   = nil
         | 
| 568 | 
            -
                  @status   = :not_connected
         | 
| 569 | 
            -
                end
         | 
| 570 | 
            -
             | 
| 571 | 
            -
                def create_logger
         | 
| 572 | 
            -
            			@logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
         | 
| 573 | 
            -
            			@logger.level = Logger::INFO
         | 
| 574 | 
            -
            			@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
         | 
| 575 | 
            -
                end
         | 
| 576 | 
            -
             | 
| 577 450 | 
             
              end
         | 
| 578 451 | 
             
            end
         |