Browse Source

[1427] Getting cached tokens

Michal 'vorner' Vaner 13 years ago
parent
commit
137abb7385

+ 24 - 3
src/lib/python/isc/bind10/socket_cache.py

@@ -18,6 +18,7 @@ Here's the cache for sockets from socket creator.
 """
 
 import os
+import random
 
 class SocketError(Exception):
     """
@@ -131,8 +132,8 @@ class Cache:
         # This is a dict from applications to set of tokens used by the
         # application, for the sockets already picked up by an application
         self._active_apps = {}
-        # The sockets live here to be indexed by address and subsequently
-        # by port
+        # The sockets live here to be indexed by protocol, address and
+        # subsequently by port
         self._sockets = {}
         # These are just the tokens actually in use, so we don't generate
         # dupes. If one is dropped, it can be potentially reclaimed.
@@ -173,7 +174,27 @@ class Cache:
         Note that it isn't guaranteed the tokens would be unique and they
         should be used as an opaque handle only.
         """
-        pass
+        addr_str = str(address)
+        try:
+            socket = self._sockets[protocol][addr_str][port]
+        except KeyError:
+            # Something in the dicts is not there, so socket is to be
+            # created
+            # TODO
+            pass
+        # Now we get the token, check it is compatible
+        if not socket.shareCompatible(share_mode, share_name):
+            raise ShareError("Cached socket not compatible with mode " +
+                             share_mode + " and name " + share_name)
+        # Grab yet unused token
+        token = 't' + str(random.randint(0, 2^32-1))
+        while token in self._live_tokens:
+            token = 't' + str(random.randint(0, 2^32-1))
+        self._waiting_tokens[token] = socket
+        self._live_tokens.add(token)
+        socket.shares[token] = (share_mode, share_name)
+        socket.waiting_tokens.add(token)
+        return token
 
     def get_socket(self, token, application):
         """

+ 35 - 0
src/lib/python/isc/bind10/tests/socket_cache_test.py

@@ -134,9 +134,14 @@ class SocketCacheTest(Test):
     def setUp(self):
         """
         Creates the cache for tests with us being the socket creator.
+
+        Also creates some more variables for testing.
         """
         Test.setUp(self)
         self.__cache = isc.bind10.socket_cache.Cache(self)
+        self.__address = IPAddr("192.0.2.1")
+        self.__socket = isc.bind10.socket_cache.Socket('Test', self.__address,
+                                                       1024, 42)
 
     def test_init(self):
         """
@@ -149,6 +154,36 @@ class SocketCacheTest(Test):
         self.assertEqual({}, self.__cache._sockets)
         self.assertEqual(set(), self.__cache._live_tokens)
 
+    def test_get_token_cached(self):
+        """
+        Check the behaviour of get_token when the requested socket is already
+        cached inside.
+        """
+        self.__cache._sockets = {
+            'UDP': {'192.0.2.1': {42: self.__socket}}
+        }
+        token = self.__cache.get_token('UDP', self.__address, 42, 'ANY',
+                                       'test')
+        # It returned something
+        self.assertIsNotNone(token)
+        # The token is both in the waiting sockets and the live tokens
+        self.assertEqual({token: self.__socket}, self.__cache._waiting_tokens)
+        self.assertEqual(set([token]), self.__cache._live_tokens)
+        # The token got the new share to block any relevant queries
+        self.assertEqual({token: ('ANY', 'test')}, self.__socket.shares)
+        # The socket knows the token is waiting in it
+        self.assertEqual(set([token]), self.__socket.waiting_tokens)
+
+        # If we request one more, with incompatible share, it is rejected
+        self.assertRaises(isc.bind10.socket_cache.ShareError,
+                          self.__cache.get_token, 'UDP', self.__address, 42,
+                          'NO', 'test')
+        # The internals are not changed, so the same checks
+        self.assertEqual({token: self.__socket}, self.__cache._waiting_tokens)
+        self.assertEqual(set([token]), self.__cache._live_tokens)
+        self.assertEqual({token: ('ANY', 'test')}, self.__socket.shares)
+        self.assertEqual(set([token]), self.__socket.waiting_tokens)
+
 if __name__ == '__main__':
     isc.log.init("bind10")
     isc.log.resetUnitTestRootLogger()