Example #1
0
    def acquire_direct(self, address):
        """ Acquire a connection to a given address from the pool.
        The address supplied should always be an IP address, not
        a host name.

        This method is thread safe.
        """
        if self.closed():
            raise ServiceUnavailable("Connection pool closed")
        with self.lock:
            try:
                connections = self.connections[address]
            except KeyError:
                connections = self.connections[address] = deque()

            connection_acquisition_start_timestamp = perf_counter()
            while True:
                # try to find a free connection in pool
                for connection in list(connections):
                    if connection.closed() or connection.defunct(
                    ) or connection.timedout():
                        connections.remove(connection)
                        continue
                    if not connection.in_use:
                        connection.in_use = True
                        return connection
                # all connections in pool are in-use
                can_create_new_connection = self._max_connection_pool_size == INFINITE or len(
                    connections) < self._max_connection_pool_size
                if can_create_new_connection:
                    try:
                        connection = self.connector(
                            address,
                            error_handler=self.connection_error_handler)
                    except ServiceUnavailable:
                        self.remove(address)
                        raise
                    else:
                        connection.pool = self
                        connection.in_use = True
                        connections.append(connection)
                        return connection

                # failed to obtain a connection from pool because the pool is full and no free connection in the pool
                span_timeout = self._connection_acquisition_timeout - (
                    perf_counter() - connection_acquisition_start_timestamp)
                if span_timeout > 0:
                    self.cond.wait(span_timeout)
                    # if timed out, then we throw error. This time computation is needed, as with python 2.7, we cannot
                    # tell if the condition is notified or timed out when we come to this line
                    if self._connection_acquisition_timeout <= (
                            perf_counter() -
                            connection_acquisition_start_timestamp):
                        raise ClientError(
                            "Failed to obtain a connection from pool within {!r}s"
                            .format(self._connection_acquisition_timeout))
                else:
                    raise ClientError(
                        "Failed to obtain a connection from pool within {!r}s".
                        format(self._connection_acquisition_timeout))
Example #2
0
    def __init__(self, protocol_version, address, sock, **config):
        self.protocol_version = protocol_version
        self.address = address
        self.socket = sock
        self.error_handler = config.get("error_handler", ConnectionErrorHandler())
        self.server = ServerInfo(SocketAddress.from_socket(sock), protocol_version)
        self.input_buffer = ChunkedInputBuffer()
        self.output_buffer = ChunkedOutputBuffer()
        self.packer = Packer(self.output_buffer)
        self.unpacker = Unpacker()
        self.responses = deque()
        self._max_connection_lifetime = config.get("max_connection_lifetime", DEFAULT_MAX_CONNECTION_LIFETIME)
        self._creation_timestamp = perf_counter()

        # Determine the user agent and ensure it is a Unicode value
        user_agent = config.get("user_agent", DEFAULT_USER_AGENT)
        if isinstance(user_agent, bytes):
            user_agent = user_agent.decode("UTF-8")
        self.user_agent = user_agent

        # Determine auth details
        auth = config.get("auth")
        if not auth:
            self.auth_dict = {}
        elif isinstance(auth, tuple) and 2 <= len(auth) <= 3:
            self.auth_dict = vars(AuthToken("basic", *auth))
        else:
            try:
                self.auth_dict = vars(auth)
            except (KeyError, TypeError):
                raise TypeError("Cannot determine auth details from %r" % auth)

        # Pick up the server certificate, if any
        self.der_encoded_server_certificate = config.get("der_encoded_server_certificate")
Example #3
0
 def is_fresh(self, access_mode):
     """ Indicator for whether routing information is still usable.
     """
     expired = self.last_updated_time + self.ttl <= perf_counter()
     has_server_for_mode = (access_mode == READ_ACCESS and
                            self.readers) or (access_mode == WRITE_ACCESS
                                              and self.writers)
     return not expired and self.routers and has_server_for_mode
Example #4
0
 def update(self, new_routing_table):
     """ Update the current routing table with new routing information
     from a replacement table.
     """
     self.routers.replace(new_routing_table.routers)
     self.readers.replace(new_routing_table.readers)
     self.writers.replace(new_routing_table.writers)
     self.last_updated_time = perf_counter()
     self.ttl = new_routing_table.ttl
Example #5
0
 def timedout(self):
     return 0 <= self._max_connection_lifetime <= perf_counter(
     ) - self._creation_timestamp
Example #6
0
 def __init__(self, routers=(), readers=(), writers=(), ttl=0):
     self.routers = OrderedSet(routers)
     self.readers = OrderedSet(readers)
     self.writers = OrderedSet(writers)
     self.last_updated_time = perf_counter()
     self.ttl = ttl