def __init__(self, parameters): """ Initialize the dispatcher, socket and our defaults. We turn of nageling in the socket to allow for faster throughput. """ asyncore.dispatcher.__init__(self) # Carry the parameters for this as well self.parameters = parameters # Setup defaults self.connecting = True self.connection = None self._timeouts = dict() self.map = None # Set our remaining attempts to the value or True if it's none remaining_attempts = self.parameters.connection_attempts or True # Loop while we have remaining attempts while remaining_attempts: try: return self._socket_connect() except socket.error, err: remaining_attempts -= 1 if not remaining_attempts: break log.warning( "Could not connect: %s. Retrying in %i seconds \ with %i retry(s) left", err[-1], self.parameters.retry_delay, remaining_attempts) self.socket.close() time.sleep(self.parameters.retry_delay)
def close(self, code=200, text='Normal shutdown'): """ Disconnect from RabbitMQ. If there are any open channels, it will attempt to close them prior to fully disconnecting. Channels which have active consumers will attempt to send a Basic.Cancel to RabbitMQ to cleanly stop the delivery of messages prior to closing the channel. """ if self.closing or self.closed: log.warning("%s.Close invoked while closing or closed", self.__class__.__name__) return # Carry our code and text around with us self.closing = code, text # Remove the reconnection strategy callback for when we close self.callbacks.remove(0, '_on_connection_close', self.reconnection.on_connection_closed) # If we're not already closed for channel_number in self._channels.keys(): self._channels[channel_number].close(code, text) # If we already dont have any channels, close out if not self._channels: self._on_close_ready()
def __init__(self, parameters): """ Initialize the dispatcher, socket and our defaults. We turn of nageling in the socket to allow for faster throughput. """ asyncore.dispatcher.__init__(self) # Carry the parameters for this as well self.parameters = parameters # Setup defaults self.connecting = True self.connection = None self._timeouts = dict() self.writable_ = False self.map = None # Set our remaining attempts to the value or True if it's none remaining_attempts = self.parameters.connection_attempts or True # Loop while we have remaining attempts while remaining_attempts: try: return self._socket_connect() except socket.error, err: remaining_attempts -= 1 if not remaining_attempts: break log.warning("Could not connect: %s. Retrying in %i seconds \ with %i retry(s) left", err[-1], self.parameters.retry_delay, remaining_attempts) self.socket.close() sleep(self.parameters.retry_delay)
def _adapter_disconnect(self): # Remove from the IOLoop self.ioloop.remove_handler(self.socket.fileno()) # Close our socket since the Connection class told us to do so self.socket.close() msg = "Tornado IOLoop may be running but Pika has shutdown." log.warning(msg)
def _send_frame(self, frame): """ This appends the fully generated frame to send to the broker to the output buffer which will be then sent via the connection adapter """ marshalled_frame = frame.marshal() self.bytes_sent += len(marshalled_frame) self.frames_sent += 1 self.outbound_buffer.write(marshalled_frame) self._flush_outbound() avg_frame_size = self.bytes_sent / self.frames_sent if self.outbound_buffer.size > (avg_frame_size * self._backpressure): est_frames_behind = self.outbound_buffer.size / avg_frame_size message = "Pika: Write buffer exceeded warning threshold" + " at %i bytes and an estimated %i frames behind" log.warning(message, self.outbound_buffer.size, est_frames_behind) self.callbacks.process(0, "backpressure", self)
def _adapter_connect(self): """ Base connection function to be extended as needed """ # Set our remaining attempts to the value or True if it's none remaining_attempts = self.parameters.connection_attempts or True # Loop while we have remaining attempts while remaining_attempts: try: return self._socket_connect() except socket.error, err: remaining_attempts -= 1 if not remaining_attempts: break log.warning("Could not connect: %s. Retrying in %i seconds \ with %i retry(s) left", err[-1], self.parameters.retry_delay, remaining_attempts) self.socket.close() sleep(self.parameters.retry_delay)
def add(self, prefix, key, callback, one_shot=True, only_caller=None): """ Add a callback to the stack for the specified key. If the call is specified as one_shot, it will be removed after being fired The prefix is usually the channel number but the class is generic and prefix and key may be any value. If you pass in only_caller CallbackManager will restrict processing of the callback to only the calling function/object that you specify. """ # Lets not use objects, since we could have object/class issues key = self.sanitize(key) # Make sure we've seen the prefix before if prefix not in self._callbacks: self._callbacks[prefix] = dict() # If we don't have the key in our callbacks, add it if key not in self._callbacks[prefix]: self._callbacks[prefix][key] = list() # Our callback info we need elsewhere in the class callback_dict = {'handle': callback, 'one_shot': one_shot} if only_caller: callback_dict['only'] = only_caller # If we passed in that we do not want duplicates, check and keep us # from adding it a second time if callback_dict in self._callbacks[prefix][key]: log.warning('%s.add: Duplicate callback found for "%s:%s"', self.__class__.__name__, prefix, key) return # Append the callback to our key list self._callbacks[prefix][key].append(callback_dict) log.debug('%s: Added "%s:%s" with callback: %s', self.__class__.__name__, prefix, key, callback) return prefix, key
class BaseConnection(Connection): def __init__(self, parameters=None, on_open_callback=None, reconnection_strategy=None): # Let the developer know we could not import SSL if parameters.ssl and not SSL: raise Exception("SSL specified but it is not available") # Call our parent's __init__ Connection.__init__(self, parameters, on_open_callback, reconnection_strategy) def _init_connection_state(self): Connection._init_connection_state(self) # Set our defaults self.fd = None self.ioloop = None # Event states (base and current) self.base_events = READ | ERROR self.event_state = self.base_events self.socket = None self.write_buffer = None self._ssl_connecting = False self._ssl_handshake = False def _socket_connect(self): """Create socket and connect to it, using SSL if enabled.""" # Create our socket and set our socket options self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) # Wrap the SSL socket if we SSL turned on ssl_text = "" if self.parameters.ssl: ssl_text = " with SSL" if self.parameters.ssl_options: # Always overwrite this value self.parameters.ssl_options['do_handshake_on_connect'] = \ self._ssl_handshake self.socket = ssl.wrap_socket(self.socket, **self.parameters.ssl_options) else: self.socket = ssl.wrap_socket(self.socket, do_handshake_on_connect= \ self._ssl_handshake) # Flags for SSL handshake negotiation self._ssl_connecting = True # Try and connect log.info("Connecting fd %d to %s:%i%s", self.socket.fileno(), self.parameters.host, self.parameters.port, ssl_text) self.socket.settimeout(CONNECTION_TIMEOUT) self.socket.connect((self.parameters.host, self.parameters.port)) # Set the socket to non-blocking self.socket.setblocking(0) def _adapter_connect(self): """ Base connection function to be extended as needed. """ # Set our remaining attempts to the initial value from sys import maxint remaining_attempts = self.parameters.connection_attempts or maxint # Loop while we have remaining attempts while remaining_attempts: remaining_attempts -= 1 try: return self._socket_connect() except socket.timeout, timeout: reason = "timeout" except socket.error, err: reason = err[-1] self.socket.close() retry = '' if remaining_attempts: retry = "Retrying in %i seconds with %i retry(s) left" % \ (self.parameters.retry_delay, remaining_attempts) log.warning("Could not connect: %s. %s", reason, retry) if remaining_attempts: time.sleep(self.parameters.retry_delay)
def on_connect_attempt_failure(self, conn, err): """Called by the connection on failure to establish initial connection""" warning( "Connection failure (attempt %s): %s", self.attempts_since_last_success, err )