def __socket(self, mongo): """Get a socket from the pool. If it's been > 1 second since the last time we checked out a socket, we also check to see if the socket has been closed - this let's us avoid seeing *some* :class:`~pymongo.errors.AutoReconnect` exceptions on server hiccups, etc. We only do this if it's been > 1 second since the last socket checkout, to keep performance reasonable - we can't avoid those completely anyway. """ sock, authset = mongo['pool'].get_socket() now = time.time() if now - mongo['last_checkout'] > 1: if _closed(sock): mongo['pool'] = pool.Pool(mongo['pool'].host, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl) sock, authset = mongo['pool'].get_socket() mongo['last_checkout'] = now if self.__auth_credentials or authset: self.__check_auth(sock, authset) return sock
def test_greenlet_sockets(self): # Check that Pool gives two sockets to two greenlets try: import greenlet except ImportError: raise SkipTest('greenlet not installed') cx_pool = pool.Pool(pair=(host, port), max_size=10, net_timeout=1000, conn_timeout=1000, use_ssl=False, use_greenlets=True) socks = [] def get_socket(): cx_pool.start_request() socks.append(cx_pool.get_socket()) looplet([ greenlet.greenlet(get_socket), greenlet.greenlet(get_socket), ]) self.assertEqual(2, len(socks)) self.assertNotEqual(socks[0], socks[1])
def __is_master(self, host): """Directly call ismaster. """ mongo = pool.Pool(host, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl) sock = mongo.get_socket()[0] response = self.__simple_command(sock, 'admin', {'ismaster': 1}) return response, mongo
def test_greenlet_sockets_with_request(self): # Verify two assumptions: that start_request() with two greenlets but # not use_greenlets fails, meaning that the two greenlets will # share one socket. Also check that start_request() with use_greenlets # succeeds, meaning that two greenlets will get different sockets. try: import greenlet except ImportError: raise SkipTest('greenlet not installed') pool_args = dict( pair=(host, port), max_size=10, net_timeout=1000, conn_timeout=1000, use_ssl=False, ) for use_greenlets, use_request, expect_success in [ (True, True, True), (True, False, False), (False, True, False), (False, False, False), ]: pool_args_cp = pool_args.copy() pool_args_cp['use_greenlets'] = use_greenlets cx_pool = pool.Pool(**pool_args_cp) # Map: greenlet -> socket greenlet2socks = {} main = greenlet.getcurrent() def get_socket_in_request(): # Get a socket from the pool twice, switching contexts each time if use_request: cx_pool.start_request() main.switch() for _ in range(2): sock = cx_pool.get_socket() cx_pool.maybe_return_socket(sock) greenlet2socks.setdefault(greenlet.getcurrent(), []).append(id(sock)) main.switch() cx_pool.end_request() greenlets = [ greenlet.greenlet(get_socket_in_request), greenlet.greenlet(get_socket_in_request), ] # Run both greenlets to completion looplet(greenlets) socks_for_gr0 = greenlet2socks[greenlets[0]] socks_for_gr1 = greenlet2socks[greenlets[1]] # Whether we expect requests to work or not, we definitely expect # greenlet2socks to have the same number of keys and values self.assertEqual(2, len(greenlet2socks)) self.assertEqual(2, len(socks_for_gr0)) self.assertEqual(2, len(socks_for_gr1)) # If we started a request, then there was a point at which we had # 2 active sockets, otherwise we always used one. if use_request and use_greenlets: self.assertEqual(2, len(cx_pool.sockets)) else: self.assertEqual(1, len(cx_pool.sockets)) # Again, regardless of whether requests work, a greenlet will get # the same socket each time it calls get_socket() within a request. # What we're really testing is that the two *different* greenlets # get *different* sockets from each other. self.assertEqual( socks_for_gr0[0], socks_for_gr0[1], "Expected greenlet 0 to get the same socket for each call " "to get_socket()") self.assertEqual( socks_for_gr1[0], socks_for_gr1[1], "Expected greenlet 1 to get the same socket for each call " "to get_socket()") if expect_success: # We passed use_greenlets=True, so start_request successfully # distinguished between the two greenlets. self.assertNotEqual( socks_for_gr0[0], socks_for_gr1[0], "Expected two greenlets to get two different sockets") else: # We passed use_greenlets=False, so start_request didn't # distinguish between the two greenlets, and it gave them both # the same socket. self.assertEqual(socks_for_gr0[0], socks_for_gr1[0], "Expected two greenlets to get same socket")