def borrow_connection(self, timeout): if self.is_shutdown: raise ConnectionException( "Pool for %s is shutdown" % (self.host, ), self.host) conns = self._connections if not conns: # handled specially just for simpler code log.debug("Detected empty pool, opening core conns to %s", self.host) core_conns = self._session.cluster.get_core_connections_per_host( self.host_distance) with self._lock: # we check the length of self._connections again # along with self._scheduled_for_creation while holding the lock # in case multiple threads hit this condition at the same time to_create = core_conns - (len(self._connections) + self._scheduled_for_creation) for i in range(to_create): self._scheduled_for_creation += 1 self._session.submit(self._create_new_connection) # in_flight is incremented by wait_for_conn conn = self._wait_for_conn(timeout) return conn else: # note: it would be nice to push changes to these config settings # to pools instead of doing a new lookup on every # borrow_connection() call max_reqs = self._session.cluster.get_max_requests_per_connection( self.host_distance) max_conns = self._session.cluster.get_max_connections_per_host( self.host_distance) least_busy = min(conns, key=lambda c: c.in_flight) # to avoid another thread closing this connection while # trashing it (through the return_connection process), hold # the connection lock from this point until we've incremented # its in_flight count need_to_wait = False with least_busy.lock: if least_busy.in_flight >= MAX_STREAM_PER_CONNECTION: # once we release the lock, wait for another connection need_to_wait = True else: least_busy.in_flight += 1 if need_to_wait: # wait_for_conn will increment in_flight on the conn least_busy = self._wait_for_conn(timeout) # if we have too many requests on this connection but we still # have space to open a new connection against this host, go ahead # and schedule the creation of a new connection if least_busy.in_flight >= max_reqs and len( self._connections) < max_conns: self._maybe_spawn_new_connection() return least_busy
def borrow_connection(self, timeout, routing_key=None): if self.is_shutdown: raise ConnectionException( "Pool for %s is shutdown" % (self.host, ), self.host) if not self._connections: raise NoConnectionsAvailable() shard_id = None if self.host.sharding_info and routing_key: t = self._session.cluster.metadata.token_map.token_class.from_key( routing_key) shard_id = self.host.sharding_info.shard_id_from_token(t) conn = self._connections.get(shard_id) # missing shard aware connection to shard_id, let's schedule an # optimistic try to connect to it if shard_id is not None: if conn: log.debug( "Using connection to shard_id=%i on host %s for routing_key=%s", shard_id, self.host, routing_key) elif shard_id not in self._connecting: # rate controlled optimistic attempt to connect to a missing shard self._connecting.add(shard_id) self._session.submit(self._open_connection_to_missing_shard, shard_id) log.debug( "Trying to connect to missing shard_id=%i on host %s (%s/%i)", shard_id, self.host, len(self._connections.keys()), self.host.sharding_info.shards_count) # we couldn't find a shard aware connection, let's pick a random one # from our pool if not conn: conn = self._connections.get( random.choice(list(self._connections.keys()))) start = time.time() remaining = timeout while True: with conn.lock: if conn.in_flight <= conn.max_request_id: conn.in_flight += 1 return conn, conn.get_request_id() if timeout is not None: remaining = timeout - time.time() + start if remaining < 0: break with self._stream_available_condition: self._stream_available_condition.wait(remaining) raise NoConnectionsAvailable("All request IDs are currently in use")
def borrow_connection(self, timeout): if self.is_shutdown: raise ConnectionException( "Pool for %s is shutdown" % (self.host, ), self.host) conn = self._connection if not conn: raise NoConnectionsAvailable() with conn.lock: if conn.in_flight < conn.max_request_id: conn.in_flight += 1 return conn, conn.get_request_id() raise NoConnectionsAvailable("All request IDs are currently in use")
def connect(self, address): # this is copied directly from asyncore.py, except that # a timeout is set before connecting self.connected = False self.connecting = True self.socket.settimeout(1.0) err = self.socket.connect_ex(address) if err in (EINPROGRESS, EALREADY, EWOULDBLOCK) \ or err == EINVAL and os.name in ('nt', 'ce'): raise ConnectionException("Timed out connecting to %s" % (address[0])) if err in (0, EISCONN): self.addr = address self.setblocking(0) self.handle_connect_event() else: raise socket.error(err, errorcode[err])
def _wait_for_conn(self, timeout): start = time.time() remaining = timeout while remaining > 0: # wait on our condition for the possibility that a connection # is useable self._await_available_conn(remaining) # self.shutdown() may trigger the above Condition if self.is_shutdown: raise ConnectionException("Pool is shutdown") conns = self._connections if conns: least_busy = min(conns, key=lambda c: c.in_flight) with least_busy.lock: if least_busy.in_flight < least_busy.max_request_id: least_busy.in_flight += 1 return least_busy, least_busy.get_request_id() remaining = timeout - (time.time() - start) raise NoConnectionsAvailable()
def borrow_connection(self, timeout): if self.is_shutdown: raise ConnectionException( "Pool for %s is shutdown" % (self.host, ), self.host) conn = self._connection if not conn: raise NoConnectionsAvailable() start = time.time() remaining = timeout while True: with conn.lock: if conn.in_flight <= conn.max_request_id: conn.in_flight += 1 return conn, conn.get_request_id() if timeout is not None: remaining = timeout - time.time() + start if remaining < 0: break with self._stream_available_condition: self._stream_available_condition.wait(remaining) raise NoConnectionsAvailable("All request IDs are currently in use")
def info_callback(self, connection, where, ret): if where & SSL.SSL_CB_HANDSHAKE_DONE: if self.check_hostname and self.endpoint.address != connection.get_peer_certificate().get_subject().commonName: transport = connection.get_app_data() transport.failVerification(Failure(ConnectionException("Hostname verification failed", self.endpoint)))