def _read_socket(self, read_timeout): """Called when there's something to read on the socket""" client = self.client header, buffer, offset = self._read_header(read_timeout) if header.xid == PING_XID: self.logger.log(BLATHER, 'Received Ping') self.ping_outstanding.clear() elif header.xid == AUTH_XID: self.logger.log(BLATHER, 'Received AUTH') request, async_object, xid = client._pending.popleft() if header.err: async_object.set_exception(AuthFailedError()) client._session_callback(KeeperState.AUTH_FAILED) else: async_object.set(True) elif header.xid == WATCH_XID: self._read_watch_event(buffer, offset) else: self.logger.log(BLATHER, 'Reading for header %r', header) return self._read_response(header, buffer, offset)
def _connect(self, host, hostip, port): client = self.client self.logger.info('Connecting to %s(%s):%s, use_ssl: %r', host, hostip, port, self.client.use_ssl) self.logger.log(BLATHER, ' Using session_id: %r session_passwd: %s', client._session_id, hexlify(client._session_passwd)) with self._socket_error_handling(): self._socket = self.handler.create_connection( address=(hostip, port), timeout=client._session_timeout / 1000.0, use_ssl=self.client.use_ssl, keyfile=self.client.keyfile, certfile=self.client.certfile, ca=self.client.ca, keyfile_password=self.client.keyfile_password, verify_certs=self.client.verify_certs, ) self._socket.setblocking(0) connect = Connect(0, client.last_zxid, client._session_timeout, client._session_id or 0, client._session_passwd, client.read_only) connect_result, zxid = self._invoke( client._session_timeout / 1000.0 / len(client.hosts), connect) if connect_result.time_out <= 0: raise SessionExpiredError("Session has expired") if zxid: client.last_zxid = zxid # Load return values client._session_id = connect_result.session_id client._protocol_version = connect_result.protocol_version negotiated_session_timeout = connect_result.time_out connect_timeout = negotiated_session_timeout / len(client.hosts) read_timeout = negotiated_session_timeout * 2.0 / 3.0 client._session_passwd = connect_result.passwd self.logger.log( BLATHER, 'Session created, session_id: %r session_passwd: %s\n' ' negotiated session timeout: %s\n' ' connect timeout: %s\n' ' read timeout: %s', client._session_id, hexlify(client._session_passwd), negotiated_session_timeout, connect_timeout, read_timeout) if connect_result.read_only: client._session_callback(KeeperState.CONNECTED_RO) self._ro_mode = iter(self._server_pinger()) else: client._session_callback(KeeperState.CONNECTED) self._ro_mode = None if self.sasl_options is not None: self._authenticate_with_sasl(host, connect_timeout / 1000.0) # Get a copy of the auth data before iterating, in case it is # changed. client_auth_data_copy = copy.copy(client.auth_data) for scheme, auth in client_auth_data_copy: ap = Auth(0, scheme, auth) zxid = self._invoke(connect_timeout / 1000.0, ap, xid=AUTH_XID) if zxid: client.last_zxid = zxid return read_timeout, connect_timeout
def _connect_attempt(self, host, hostip, port, retry): client = self.client KazooTimeoutError = self.handler.timeout_exception close_connection = False self._socket = None # Were we given a r/w server? If so, use that instead if self._rw_server: self.logger.log(BLATHER, "Found r/w server to use, %s:%s", host, port) host, port = self._rw_server self._rw_server = None if client._state != KeeperState.CONNECTING: client._session_callback(KeeperState.CONNECTING) try: self._xid = 0 read_timeout, connect_timeout = self._connect(host, hostip, port) read_timeout = read_timeout / 1000.0 connect_timeout = connect_timeout / 1000.0 retry.reset() self.ping_outstanding.clear() with self._socket_error_handling(): while not close_connection: # Watch for something to read or send jitter_time = random.randint(0, 40) / 100.0 # Ensure our timeout is positive timeout = max( [read_timeout / 2.0 - jitter_time, jitter_time]) s = self.handler.select([self._socket, self._read_sock], [], [], timeout)[0] if not s: if self.ping_outstanding.is_set(): self.ping_outstanding.clear() raise ConnectionDropped( "outstanding heartbeat ping not received") self._send_ping(connect_timeout) elif s[0] == self._socket: response = self._read_socket(read_timeout) close_connection = response == CLOSE_RESPONSE else: self._send_request(read_timeout, connect_timeout) self.logger.info('Closing connection to %s:%s', host, port) client._session_callback(KeeperState.CLOSED) return STOP_CONNECTING except (ConnectionDropped, KazooTimeoutError) as e: if isinstance(e, ConnectionDropped): self.logger.warning('Connection dropped: %s', e) else: self.logger.warning('Connection time-out: %s', e) if client._state != KeeperState.CONNECTING: self.logger.warning("Transition to CONNECTING") client._session_callback(KeeperState.CONNECTING) except AuthFailedError as err: retry.reset() self.logger.warning('AUTH_FAILED closing: %s', err) client._session_callback(KeeperState.AUTH_FAILED) return STOP_CONNECTING except SessionExpiredError: retry.reset() self.logger.warning('Session has expired') client._session_callback(KeeperState.EXPIRED_SESSION) except RWServerAvailable: retry.reset() self.logger.warning('Found a RW server, dropping connection') client._session_callback(KeeperState.CONNECTING) except Exception: self.logger.exception('Unhandled exception in connection loop') raise finally: if self._socket is not None: self._socket.close()
def _connect_attempt(self, host, hostip, port, retry): client = self.client KazooTimeoutError = self.handler.timeout_exception self._socket = None # Were we given a r/w server? If so, use that instead if self._rw_server: self.logger.log(BLATHER, "Found r/w server to use, %s:%s", host, port) host, port = self._rw_server self._rw_server = None if client._state != KeeperState.CONNECTING: client._session_callback(KeeperState.CONNECTING) try: self._xid = 0 read_timeout, connect_timeout = self._connect(host, hostip, port) read_timeout = read_timeout / 1000.0 connect_timeout = connect_timeout / 1000.0 retry.reset() self.ping_outstanding.clear() last_send = time.time() with self._socket_error_handling(): while True: # Watch for something to read or send jitter_time = random.randint(1, 40) / 100.0 deadline = last_send + read_timeout / 2.0 - jitter_time # Ensure our timeout is positive timeout = max([deadline - time.time(), jitter_time]) s = self.handler.select([self._socket, self._read_sock], [], [], timeout)[0] if not s: if self.ping_outstanding.is_set(): self.ping_outstanding.clear() raise ConnectionDropped( "outstanding heartbeat ping not received") else: if self._socket in s: response = self._read_socket(read_timeout) if response == CLOSE_RESPONSE: break # Check if any requests need sending before proceeding # to process more responses. Otherwise the responses # may choke out the requests. See PR#633. if self._read_sock in s: self._send_request(read_timeout, connect_timeout) # Requests act as implicit pings. last_send = time.time() continue if time.time() >= deadline: self._send_ping(connect_timeout) last_send = time.time() self.logger.info('Closing connection to %s:%s', host, port) client._session_callback(KeeperState.CLOSED) return STOP_CONNECTING except (ConnectionDropped, KazooTimeoutError) as e: if isinstance(e, ConnectionDropped): self.logger.warning('Connection dropped: %s', e) else: self.logger.warning('Connection time-out: %s', e) if client._state != KeeperState.CONNECTING: self.logger.warning("Transition to CONNECTING") client._session_callback(KeeperState.CONNECTING) except AuthFailedError as err: retry.reset() self.logger.warning('AUTH_FAILED closing: %s', err) client._session_callback(KeeperState.AUTH_FAILED) return STOP_CONNECTING except SessionExpiredError: retry.reset() self.logger.warning('Session has expired') client._session_callback(KeeperState.EXPIRED_SESSION) except RWServerAvailable: retry.reset() self.logger.warning('Found a RW server, dropping connection') client._session_callback(KeeperState.CONNECTING) except Exception: self.logger.exception('Unhandled exception in connection loop') raise finally: if self._socket is not None: self._socket.close()