def test_queue_threadlocal_failover(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool(pool_size=1, max_overflow=0, recycle=10000, prefill=True, timeout=0.05, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=True, server_list=['localhost:9160', 'localhost:9160']) cf = ColumnFamily(pool, 'Standard1') for i in range(1, 5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() # The first insert attempt should fail, but failover should occur # and the insert should succeed cf.insert('key', {'col': 'val%d' % i, 'col2': 'val'}) assert_equal(stats_logger.stats['failed'], i) assert_equal(cf.get('key'), {'col': 'val%d' % i, 'col2': 'val'}) pool.dispose() stats_logger.reset() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, timeout=0.05, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=True, server_list=['localhost:9160', 'localhost:9160']) cf = ColumnFamily(pool, 'Standard1') for i in range(5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() threads = [] args = ('key', {'col': 'val', 'col2': 'val'}) for i in range(5): threads.append(threading.Thread(target=cf.insert, args=args)) threads[-1].start() for thread in threads: thread.join() assert_equal(stats_logger.stats['failed'], 5) pool.dispose()
def test_queue_pool_recycle(self): listener = _TestListener() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=1, prefill=True, pool_timeout=0.5, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[listener], use_threadlocal=False) cf = ColumnFamily(pool, 'Standard1') columns = {'col1': 'val', 'col2': 'val'} for i in range(10): cf.insert('key', columns) assert_equal(listener.recycle_count, 5) pool.dispose() listener.reset() # Try with threadlocal=True pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=1, prefill=False, pool_timeout=0.5, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[listener], use_threadlocal=True) cf = ColumnFamily(pool, 'Standard1') for i in range(10): cf.insert('key', columns) pool.dispose() assert_equal(listener.recycle_count, 5)
def test_pool_connection_failure(self): stats_logger = StatsLoggerWithListStorage() def get_extra(): """Make failure count adjustments based on whether or not the permuted list starts with a good host:port""" if stats_logger.serv_list[0] == 'localhost:9160': return 0 else: return 1 pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, keyspace='PycassaTestKeyspace', credentials=_credentials, pool_timeout=0.01, timeout=0.05, listeners=[stats_logger], use_threadlocal=False, server_list=['localhost:9160', 'foobar:1']) assert_equal(stats_logger.stats['failed'], 4 + get_extra()) for i in range(0, 7): pool.get() assert_equal(stats_logger.stats['failed'], 6 + get_extra()) pool.dispose() stats_logger.reset() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, keyspace='PycassaTestKeyspace', credentials=_credentials, pool_timeout=0.01, timeout=0.05, listeners=[stats_logger], use_threadlocal=True, server_list=['localhost:9160', 'foobar:1']) assert_equal(stats_logger.stats['failed'], 4 + get_extra()) threads = [] for i in range(0, 7): threads.append(threading.Thread(target=pool.get)) threads[-1].start() for thread in threads: thread.join() assert_equal(stats_logger.stats['failed'], 6 + get_extra()) pool.dispose()
def test_queue_threadlocal_retry_limit(self): listener = _TestListener() pool = ConnectionPool( pool_size=5, max_overflow=5, recycle=10000, prefill=True, max_retries=3, # allow 3 retries keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[listener], use_threadlocal=True, server_list=['localhost:9160', 'localhost:9160']) # Corrupt all of the connections for i in range(5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() cf = ColumnFamily(pool, 'Standard1') assert_raises(MaximumRetryException, cf.insert, 'key', { 'col': 'val', 'col2': 'val' }) assert_equal(listener.failure_count, 4) # On the 4th failure, didn't retry pool.dispose()
def _get_connection(retry=None, wait_between_retry=None): """ Creates a connection to Cassandra. Returs: pool """ num = 0 if retry is None: retry = settings.CASSANDRA_CONNECT_RETRY_COUNT if wait_between_retry is None: wait_between_retry = settings.CASSANDRA_CONNECT_RETRY_WAIT while True: try: pool = ConnectionPool( settings.KEYSPACE, server_list=settings.CASSANDRA_HOSTS, timeout=settings.CASSANDRA_CONNECTION_POOL_TIMEOUT) return pool except AllServersUnavailable: num += 1 if num >= retry: logger.exception("Giving up after many retries....") raise logger.warn( "AllServersUnavailable detected. Retrying (%d of %d)...", num, retry) time.sleep(wait_between_retry)
def test_queue_failure_with_no_retries(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool( pool_size=5, max_overflow=5, recycle=10000, prefill=True, max_retries=3, # allow 3 retries keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=False, server_list=['localhost:9160', 'localhost:9160']) # Corrupt all of the connections for i in range(5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() cf = ColumnFamily(pool, 'Counter1') assert_raises(MaximumRetryException, cf.insert, 'key', { 'col': 2, 'col2': 2 }) assert_equal(stats_logger.stats['failed'], 1) # didn't retry at all pool.dispose()
def __call__(self, uuids=None, cassandra_servers=None, force=False, **kwargs): super(CheckBadRefs, self).__call__(**kwargs) self.force = force pool = ConnectionPool('config_db_uuid', server_list=cassandra_servers) uuid_cf = ColumnFamily(pool, 'obj_uuid_table') if uuids: def uuids_g(): for uuid in uuids: yield uuid else: def uuids_g(): for k, v in uuid_cf.get_range(column_count=1, filter_empty=True): yield k for uuid in uuids_g(): values = dict(uuid_cf.xget(uuid)) res = self._get_current_resource(uuid, values) bad_refs = self._check_resource_refs(uuid, values) if not res or bad_refs: printo(self._props_to_json(values)) if not res and not self.check: if self.force or continue_prompt(message="Delete ?"): self._delete(uuid_cf, uuid)
def test_failure_connection_info(self): stats_logger = StatsLoggerRequestInfo() pool = ConnectionPool(pool_size=1, max_overflow=0, recycle=10000, prefill=True, max_retries=0, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=True, server_list=['localhost:9160']) cf = ColumnFamily(pool, 'Counter1') # Corrupt the connection conn = pool.get() setattr(conn, 'send_get', conn._fail_once) conn._should_fail = True conn.return_to_pool() assert_raises(MaximumRetryException, cf.get, 'greunt', columns=['col']) assert_true('request' in stats_logger.failure_dict['connection'].info) request = stats_logger.failure_dict['connection'].info['request'] assert_equal(request['method'], 'get') assert_equal(request['args'], ('greunt', ColumnPath('Counter1', None, 'col'), 1)) assert_equal(request['kwargs'], {})
def create_cfs(self): """ Creates the Cassandra Column Families (if not exist) """ sys_mgr = None pool = None try: sys_mgr = SystemManager() pool = ConnectionPool(settings.KEYSPACE, server_list=settings.CASSANDRA_HOSTS) for cf_name in [ CF_LOGS, CF_LOGS_BY_APP, CF_LOGS_BY_HOST, CF_LOGS_BY_SEVERITY ]: try: cf = ColumnFamily(pool, cf_name) except: logger.info("create_cfs(): Creating column family %s", cf_name) sys_mgr.create_column_family( settings.KEYSPACE, cf_name, comparator_type=TimeUUIDType()) cf = ColumnFamily(pool, cf_name) cf.get_count(str(uuid.uuid4())) finally: if pool: pool.dispose() if sys_mgr: sys_mgr.close()
def test_queue_failover(self): for prefill in (True, False): listener = _TestListener() pool = ConnectionPool( pool_size=1, max_overflow=0, recycle=10000, prefill=prefill, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[listener], use_threadlocal=False, server_list=['localhost:9160', 'localhost:9160']) cf = ColumnFamily(pool, 'Standard1') for i in range(1, 5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() # The first insert attempt should fail, but failover should occur # and the insert should succeed cf.insert('key', {'col': 'val%d' % i, 'col2': 'val'}) assert_equal(listener.failure_count, i) assert_equal(cf.get('key'), { 'col': 'val%d' % i, 'col2': 'val' }) pool.dispose()
def setup_module(): global pool, sys_man credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials, timeout=1.0) sys_man = SystemManager()
def setup_module(): global pool, cf, scf credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials) cf = ColumnFamily(pool, 'Standard1') scf = ColumnFamily(pool, 'Super1')
def test_queue_pool(self): listener = _TestListener() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, pool_timeout=0.1, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[listener], use_threadlocal=False) conns = [] for i in range(10): conns.append(pool.get()) assert_equal(listener.connect_count, 10) assert_equal(listener.checkout_count, 10) # Pool is maxed out now assert_raises(NoConnectionAvailable, pool.get) assert_equal(listener.connect_count, 10) assert_equal(listener.max_count, 1) for i in range(0, 5): pool.return_conn(conns[i]) assert_equal(listener.close_count, 0) assert_equal(listener.checkin_count, 5) for i in range(5, 10): pool.return_conn(conns[i]) assert_equal(listener.close_count, 5) assert_equal(listener.checkin_count, 10) conns = [] # These connections should come from the pool for i in range(5): conns.append(pool.get()) assert_equal(listener.connect_count, 10) assert_equal(listener.checkout_count, 15) # But these will need to be made for i in range(5): conns.append(pool.get()) assert_equal(listener.connect_count, 15) assert_equal(listener.checkout_count, 20) assert_equal(listener.close_count, 5) for i in range(10): conns[i].return_to_pool() assert_equal(listener.checkin_count, 20) assert_equal(listener.close_count, 10) assert_raises(InvalidRequestError, conns[0].return_to_pool) assert_equal(listener.checkin_count, 20) assert_equal(listener.close_count, 10) print "in test:", id(conns[-1]) assert_raises(InvalidRequestError, conns[-1].return_to_pool) assert_equal(listener.checkin_count, 20) assert_equal(listener.close_count, 10) pool.dispose() assert_equal(listener.dispose_count, 1)
def setup_module(): global pool, cf, scf, indexed_cf, sys_man credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials) cf = ColumnFamily(pool, 'Standard1', dict_class=TestDict) scf = ColumnFamily(pool, 'Super1', dict_class=dict) indexed_cf = ColumnFamily(pool, 'Indexed1') sys_man = SystemManager()
def set_keyspace(self, keyspace): try: self.pool = ConnectionPool(keyspace, server_list=[self.manager._conn.server], credentials=self.credentials, timeout=self.timeout) except InvalidRequestException: raise CCliClientKeyspaceError("Unknown keyspace '%s'" % keyspace)
def test_basic_pools(self): pool = ConnectionPool('PycassaTestKeyspace', credentials=_credentials) pool.dispose() pool = pool.recreate() cf = ColumnFamily(pool, 'Standard1') cf.insert('key1', {'col':'val'}) pool.status() pool.dispose()
def setup_module(): global pool, cf, scf, counter_cf, super_counter_cf, sysman credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials) cf = ColumnFamily(pool, 'Standard1') scf = ColumnFamily(pool, 'Super1') sysman = SystemManager() counter_cf = ColumnFamily(pool, 'Counter1') super_counter_cf = ColumnFamily(pool, 'SuperCounter1')
def test_server_list_func(self): listener = _TestListener() pool = ConnectionPool('PycassaTestKeyspace', server_list=_get_list, listeners=[listener], prefill=False) assert_equal(listener.serv_list, ['foo:bar']) assert_equal(listener.list_count, 1) pool.dispose()
def test_server_list_func(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool('PycassaTestKeyspace', server_list=_get_list, listeners=[stats_logger], prefill=False) assert_equal(stats_logger.serv_list, ['foo:bar']) assert_equal(stats_logger.stats['list'], 1) pool.dispose()
def setup_module(): global pool, cf, scf, indexed_cf, counter_cf, counter_scf, sys_man, have_counters credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials) cf = ColumnFamily(pool, 'Standard1', dict_class=TestDict) scf = ColumnFamily(pool, 'Super1', dict_class=dict) indexed_cf = ColumnFamily(pool, 'Indexed1') sys_man = SystemManager() have_counters = sys_man._conn.version != CASSANDRA_07 if have_counters: counter_cf = ColumnFamily(pool, 'Counter1') counter_scf = ColumnFamily(pool, 'SuperCounter1')
def setup_module(): global pool, cf, indexed_cf, pool_stub, indexed_cf_stub, cf_stub credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(keyspace='PycassaTestKeyspace', credentials=credentials, timeout=1.0) cf = ColumnFamily(pool, 'Standard1', dict_class=TestDict) indexed_cf = ColumnFamily(pool, 'Indexed1') pool_stub = ConnectionPoolStub(keyspace='PycassaTestKeyspace', credentials=credentials, timeout=1.0) cf_stub = ColumnFamilyStub(pool_stub, 'Standard1', dict_class=TestDict) indexed_cf_stub = ColumnFamilyStub(pool_stub, 'Indexed1')
def __call__(self, force=False, parent_type=None, cassandra_servers=None): valid_acl = [] parents = Collection(parent_type, fetch=True, recursive=2) for parent in parents: if 'access_control_lists' in parent.keys(): valid_acl += [ acl['uuid'] for acl in parent['access_control_lists'] ] valid_acl = list(set(valid_acl)) orphaned_acls = set([]) # Due to a bug in contrail API, we cannot list more than 10000 elements # on a resource and there is no way to list ACL by tenant. # So that ugly hack directly fetch all ACL UUIDs from the cassandra database :( pool = ConnectionPool('config_db_uuid', server_list=cassandra_servers) fqname_cf = ColumnFamily(pool, 'obj_fq_name_table') for key, value in fqname_cf.xget('access_control_list'): acl_uuid = decode_string(key).split(':')[-1] if acl_uuid in valid_acl: continue acl = Resource('access-control-list', uuid=acl_uuid, fetch=True) if ('parent_uuid' in acl.keys() and 'parent_type' in acl.keys() and acl['parent_type'] == parent_type and acl.uuid not in valid_acl): try: parent_acl = acl.parent except ResourceNotFound: msg = ("The %s parent ACL %s was not found." % (parent_type.replace('-', ' '), acl['parent_uuid'])) if force: msg = msg + " Delete orphan ACL %s." % acl.uuid acl.delete() logger.debug(msg) orphaned_acls.add(acl['uuid']) else: logger.debug( "The ACL %(acl)s have a %(parent_type)s %(parent_acl)s which exists but \ was not found in the precedent %(parent_type)s list. Not delete it." % { 'acl': acl, 'parent_type': parent_type.replace('-', ' '), 'parent_acl': parent_acl }) if force: logger.debug("%d orphaned ACL were deleted" % len(orphaned_acls)) else: logger.debug("Found %d orphaned ACL to delete" % len(orphaned_acls))
def test_pool_invalid_request(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool(pool_size=1, max_overflow=0, recycle=10000, prefill=True, max_retries=3, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=False, server_list=['localhost:9160']) cf = ColumnFamily(pool, 'Standard1') # Make sure the pool doesn't hide and retries invalid requests assert_raises(InvalidRequestException, cf.add, 'key', 'col') assert_raises(NotFoundException, cf.get, 'none') pool.dispose()
def __init__(self, root, keyspace, server_list, read_consistency_level=ConsistencyLevel.ONE, write_consistency_level=ConsistencyLevel.ONE, localDCName=None, credentials=None, pool_size=5, max_overflow=0, timeout=0.5): self.cassandra_connection = ConnectionPool(keyspace, server_list, credentials=credentials, pool_size=pool_size, max_overflow=max_overflow, timeout=timeout) self.cfCache = ColumnFamilyCache(self.cassandra_connection, read_consistency_level, write_consistency_level, credentials) self.root = root self._nodeCache = NodeCache() self.localDCName = localDCName self.credentials = credentials self.read_consistency_level = read_consistency_level
def test_queue_failure_on_retry(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool( pool_size=5, max_overflow=5, recycle=10000, prefill=True, max_retries=3, # allow 3 retries keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=False, server_list=['localhost:9160', 'localhost:9160']) def raiser(): raise IOError # Replace wrapper will open a connection to get the version, so if it # fails we need to retry as with any other connection failure pool._replace_wrapper = raiser # Corrupt all of the connections for i in range(5): conn = pool.get() setattr(conn, 'send_batch_mutate', conn._fail_once) conn._should_fail = True conn.return_to_pool() cf = ColumnFamily(pool, 'Standard1') assert_raises(MaximumRetryException, cf.insert, 'key', { 'col': 'val', 'col2': 'val' }) assert_equal(stats_logger.stats['failed'], 4) # On the 4th failure, didn't retry pool.dispose()
def setup_module(): global pool credentials = {'username': '******', 'password': '******'} pool = ConnectionPool(TEST_KS, pool_size=10, credentials=credentials)
def test_queue_pool(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, pool_timeout=0.1, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=False) conns = [] for i in range(10): conns.append(pool.get()) assert_equal(stats_logger.stats['created']['success'], 10) assert_equal(stats_logger.stats['checked_out'], 10) # Pool is maxed out now assert_raises(NoConnectionAvailable, pool.get) assert_equal(stats_logger.stats['created']['success'], 10) assert_equal(stats_logger.stats['at_max'], 1) for i in range(0, 5): pool.return_conn(conns[i]) assert_equal(stats_logger.stats['disposed']['success'], 0) assert_equal(stats_logger.stats['checked_in'], 5) for i in range(5, 10): pool.return_conn(conns[i]) assert_equal(stats_logger.stats['disposed']['success'], 5) assert_equal(stats_logger.stats['checked_in'], 10) conns = [] # These connections should come from the pool for i in range(5): conns.append(pool.get()) assert_equal(stats_logger.stats['created']['success'], 10) assert_equal(stats_logger.stats['checked_out'], 15) # But these will need to be made for i in range(5): conns.append(pool.get()) assert_equal(stats_logger.stats['created']['success'], 15) assert_equal(stats_logger.stats['checked_out'], 20) assert_equal(stats_logger.stats['disposed']['success'], 5) for i in range(10): conns[i].return_to_pool() assert_equal(stats_logger.stats['checked_in'], 20) assert_equal(stats_logger.stats['disposed']['success'], 10) assert_raises(InvalidRequestError, conns[0].return_to_pool) assert_equal(stats_logger.stats['checked_in'], 20) assert_equal(stats_logger.stats['disposed']['success'], 10) print "in test:", id(conns[-1]) assert_raises(InvalidRequestError, conns[-1].return_to_pool) assert_equal(stats_logger.stats['checked_in'], 20) assert_equal(stats_logger.stats['disposed']['success'], 10) pool.dispose()
def db_export(self): db_contents = {'cassandra': {}, 'zookeeper': {}} cassandra_contents = db_contents['cassandra'] creds = None if self._api_args.cassandra_user and self._api_args.cassandra_password: creds = {'username': self._api_args.cassandra_user, 'password': self._api_args.cassandra_password} socket_factory = default_socket_factory if ('cassandra_use_ssl' in self._api_args and self._api_args.cassandra_use_ssl): socket_factory = self._make_ssl_socket_factory( self._api_args.cassandra_ca_certs, validate=False) sys_mgr = SystemManager( self._api_args.cassandra_server_list[0], credentials=creds, socket_factory=socket_factory) existing_keyspaces = sys_mgr.list_keyspaces() for ks_name in set(KEYSPACES) - set(self._args.omit_keyspaces or []): if self._api_args.cluster_id: full_ks_name = '%s_%s' %(self._api_args.cluster_id, ks_name) else: full_ks_name = ks_name if full_ks_name not in existing_keyspaces: continue cassandra_contents[ks_name] = {} pool = ConnectionPool( full_ks_name, self._api_args.cassandra_server_list, pool_timeout=120, max_retries=-1, timeout=5, socket_factory=socket_factory, credentials=creds) for cf_name in sys_mgr.get_keyspace_column_families(full_ks_name): cassandra_contents[ks_name][cf_name] = {} cf = ColumnFamily(pool, cf_name, buffer_size=self._args.buffer_size) for r,c in cf.get_range(column_count=10000000, include_timestamp=True): cassandra_contents[ks_name][cf_name][r] = c logger.info("Cassandra DB dumped") def get_nodes(path): if path[:-1].rpartition('/')[-1] in self._zk_ignore_list: return [] try: if not zk.get_children(path): return [(path, zk.get(path))] except kazoo.exceptions.NoNodeError: return [] nodes = [] for child in zk.get_children(path): nodes.extend(get_nodes('%s%s/' %(path, child))) return nodes zk = kazoo.client.KazooClient(self._api_args.zk_server_ip) zk.start() nodes = get_nodes(self._api_args.cluster_id+'/') zk.stop() db_contents['zookeeper'] = json.dumps(nodes) logger.info("Zookeeper DB dumped") f = open(self._args.export_to, 'w') try: f.write(json.dumps(db_contents)) finally: f.close() logger.info("DB dump wrote to file %s" % self._args.export_to)
def tearDown(self): pool = ConnectionPool('PycassaTestKeyspace') cf = ColumnFamily(pool, 'Standard1') for key, cols in cf.get_range(): cf.remove(key)
def test_queue_pool_threadlocal(self): stats_logger = StatsLoggerWithListStorage() pool = ConnectionPool(pool_size=5, max_overflow=5, recycle=10000, prefill=True, pool_timeout=0.01, timeout=1, keyspace='PycassaTestKeyspace', credentials=_credentials, listeners=[stats_logger], use_threadlocal=True) conns = [] assert_equal(stats_logger.stats['created']['success'], 5) # These connections should all be the same for i in range(10): conns.append(pool.get()) assert_equal(stats_logger.stats['created']['success'], 5) assert_equal(stats_logger.stats['checked_out'], 1) for i in range(0, 5): pool.return_conn(conns[i]) assert_equal(stats_logger.stats['checked_in'], 1) for i in range(5, 10): pool.return_conn(conns[i]) assert_equal(stats_logger.stats['checked_in'], 1) conns = [] assert_equal(stats_logger.stats['created']['success'], 5) # A single connection should come from the pool for i in range(5): conns.append(pool.get()) assert_equal(stats_logger.stats['created']['success'], 5) assert_equal(stats_logger.stats['checked_out'], 2) for conn in conns: pool.return_conn(conn) conns = [] threads = [] stats_logger.reset() def checkout_return(): conn = pool.get() time.sleep(1) pool.return_conn(conn) for i in range(5): threads.append(threading.Thread(target=checkout_return)) threads[-1].start() for thread in threads: thread.join() assert_equal(stats_logger.stats['created']['success'], 0) # Still 5 connections in pool assert_equal(stats_logger.stats['checked_out'], 5) assert_equal(stats_logger.stats['checked_in'], 5) # These should come from the pool threads = [] for i in range(5): threads.append(threading.Thread(target=checkout_return)) threads[-1].start() for thread in threads: thread.join() assert_equal(stats_logger.stats['created']['success'], 0) assert_equal(stats_logger.stats['checked_out'], 10) assert_equal(stats_logger.stats['checked_in'], 10) pool.dispose()