class EventTransport(Transport): ''' Transport using libevent-based EventSocket. ''' def __init__(self, *args): super(EventTransport,self).__init__(*args) self._synchronous = False ### ### EventSocket callbacks ### def _sock_close_cb(self, sock): self._connection.transport_closed( msg='socket to %s closed unexpectedly'%(self._host), ) def _sock_error_cb(self, sock, msg, exception=None): self._connection.transport_closed( msg='error on connection to %s: %s'%(self._host, msg) ) def _sock_read_cb(self, sock): self.connection.read_frames() ### ### Transport API ### def connect(self, (host,port)): ''' Connect assuming a host and port tuple. Implemented as non-blocking, and will close the transport if there's an error ''' self._host = "%s:%s"%(host,port) self._sock = EventSocket( read_cb=self._sock_read_cb, close_cb=self._sock_close_cb, error_cb=self._sock_error_cb, debug=self.connection.debug, logger=self.connection.logger ) if self.connection._sock_opts: for k,v in self.connection._sock_opts.iteritems(): family,type = k self._sock.setsockopt(family, type, v) self._sock.setblocking( False ) self._sock.connect( (host,port), timeout=self.connection._connect_timeout ) self._heartbeat_timeout = None
def connect(self, host, port): ''' Connect to a host and port. Can be called directly, or is called by the strategy as it tries to find and connect to hosts. ''' # Clear the connect state immediately since we're no longer connected # at this point. self._connected = False # NOTE: purposefully leave output_frame_buffer alone so that pending writes can # still occur. this allows the reconnect to occur silently without # completely breaking any pending data on, say, a channel that was just # opened. self._sock = EventSocket(read_cb=self._sock_read_cb, close_cb=self._sock_close_cb, error_cb=self._sock_error_cb, debug=self._debug, logger=self._logger) self._sock.settimeout(self._connect_timeout) if self._sock_opts: for k, v in self._sock_opts.iteritems(): family, type = k self._sock.setsockopt(family, type, v) self._sock.connect((host, port)) self._sock.setblocking(False) # Only after the socket has connected do we clear this state; closed must # be False so that writes can be buffered in writePacket(). The closed # state might have been set to True due to a socket error or a redirect. self._host = "%s:%d" % (host, port) self._closed = False self._close_info = { 'reply_code': 0, 'reply_text': 'failed to connect to %s' % (self._host), 'class_id': 0, 'method_id': 0 } self._sock.write(PROTOCOL_HEADER)