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))