def _test_max_pool_size(self, c, start_request, end_request): threads = [] for i in range(40): t = CreateAndReleaseSocket(c, start_request, end_request) t.start() threads.append(t) for t in threads: t.join() for t in threads: self.assertTrue(t.passed) # Critical: release refs to threads, so SocketInfo.__del__() executes del threads t = None cx_pool = c._Connection__pool force_reclaim_sockets(cx_pool, 4) # There's a race condition, so be lenient nsock = len(cx_pool.sockets) self.assertTrue( abs(4 - nsock) < 4, "Expected about 4 sockets in the pool, got %d" % nsock )
def test_pool_reuses_open_socket(self): # Test Pool's _check_closed() method doesn't close a healthy socket cx_pool = Pool((host,port), 10, None, None, False) sock_info = cx_pool.get_socket() cx_pool.return_socket(sock_info) # trigger _check_closed, which only runs on sockets that haven't been # used in a second time.sleep(1) new_sock_info = cx_pool.get_socket() self.assertEqual(sock_info, new_sock_info) del sock_info, new_sock_info # Assert sock_info was returned to the pool *once* force_reclaim_sockets(cx_pool, 1) self.assertEqual(1, len(cx_pool.sockets))
def test_pool_removes_dead_socket(self): # Test that Pool removes dead socket and the socket doesn't return # itself PYTHON-344 cx_pool = Pool((host,port), 10, None, None, False) sock_info = cx_pool.get_socket() # Simulate a closed socket without telling the SocketInfo it's closed sock_info.sock.close() self.assertTrue(pymongo.pool._closed(sock_info.sock)) cx_pool.return_socket(sock_info) time.sleep(1) # trigger _check_closed new_sock_info = cx_pool.get_socket() self.assertEqual(0, len(cx_pool.sockets)) self.assertNotEqual(sock_info, new_sock_info) del sock_info, new_sock_info # new_sock_info returned to the pool, but not the closed sock_info force_reclaim_sockets(cx_pool, 1) self.assertEqual(1, len(cx_pool.sockets))
def test_socket_reclamation(self): # Check that if a thread starts a request and dies without ending # the request, that the socket is reclaimed into the pool. cx_pool = Pool( pair=(host,port), max_size=10, net_timeout=1000, conn_timeout=1000, use_ssl=False, ) self.assertEqual(0, len(cx_pool.sockets)) lock = thread.allocate_lock() lock.acquire() the_sock = [None] def leak_request(): self.assertEqual(NO_REQUEST, cx_pool.local.sock_info) cx_pool.start_request() self.assertEqual(NO_SOCKET_YET, cx_pool.local.sock_info) sock_info = cx_pool.get_socket() self.assertEqual(sock_info, cx_pool.local.sock_info) the_sock[0] = id(sock_info.sock) lock.release() # Start a thread WITHOUT a threading.Thread - important to test that # Pool can deal with primitive threads. thread.start_new_thread(leak_request, ()) # Join thread acquired = lock.acquire(1) self.assertTrue(acquired, "Thread is hung") force_reclaim_sockets(cx_pool, 1) # Pool reclaimed the socket self.assertEqual(1, len(cx_pool.sockets)) self.assertEqual(the_sock[0], id((iter(cx_pool.sockets).next()).sock))
def test_socket_reclamation(self): try: import greenlet except ImportError: raise SkipTest('greenlet not installed') # Check that if a greenlet starts a request and dies without ending # the request, that the socket is reclaimed cx_pool = pool.GreenletPool( pair=(host,port), max_size=10, net_timeout=1000, conn_timeout=1000, use_ssl=False, ) self.assertEqual(0, len(cx_pool.sockets)) the_sock = [None] def leak_request(): cx_pool.start_request() sock_info = cx_pool.get_socket() the_sock[0] = id(sock_info.sock) # Run the greenlet to completion gr = greenlet.greenlet(leak_request) gr.switch() # Cause greenlet to be garbage-collected del gr force_reclaim_sockets(cx_pool, 1) # Pool reclaimed the socket self.assertEqual(1, len(cx_pool.sockets)) sock_info = iter(cx_pool.sockets).next() self.assertEqual(the_sock[0], id(sock_info.sock))