[CalendarServer-changes] [2468] CalendarServer/branches/unified-cache/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Fri May 23 16:46:12 PDT 2008


Revision: 2468
          http://trac.macosforge.org/projects/calendarserver/changeset/2468
Author:   dreid at apple.com
Date:     2008-05-23 16:46:11 -0700 (Fri, 23 May 2008)

Log Message:
-----------
Add a very hacky MemcacheChangeNotifier

Modified Paths:
--------------
    CalendarServer/branches/unified-cache/twistedcaldav/cache.py
    CalendarServer/branches/unified-cache/twistedcaldav/test/test_cache.py
    CalendarServer/branches/unified-cache/twistedcaldav/test/util.py

Modified: CalendarServer/branches/unified-cache/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/unified-cache/twistedcaldav/cache.py	2008-05-23 23:45:33 UTC (rev 2467)
+++ CalendarServer/branches/unified-cache/twistedcaldav/cache.py	2008-05-23 23:46:11 UTC (rev 2468)
@@ -40,8 +40,8 @@
 
 from twistedcaldav.log import LoggingMixIn
 from twistedcaldav.memcache import MemCacheProtocol
+from twistedcaldav.config import config
 
-
 class CacheTokensProperty(davxml.WebDAVTextElement):
     namespace = davxml.twisted_private_namespace
     name = "cacheTokens"
@@ -71,6 +71,55 @@
         return succeed(True)
 
 
+
+class MemcacheChangeNotifier(LoggingMixIn):
+    def __init__(self, propertyStore):
+        self._path = propertyStore.resource.fp.path
+        self._host = config.Memcached['BindAddress']
+        self._port = config.Memcached['Port']
+
+        from twisted.internet import reactor
+        self._reactor = reactor
+
+        self._memcacheProtocol =  None
+
+
+    def _newCacheToken(self):
+        return uuid.uuid4()
+
+
+    def _getMemcacheProtocol(self):
+        if self._memcacheProtocol is not None:
+            return succeed(self._memcacheProtocol)
+
+        d = ClientCreator(self._reactor, MemCacheProtocol).connectTCP(
+            self._host,
+            self._port)
+
+        def _cacheProtocol(proto):
+            self._memcacheProtocol = proto
+            return proto
+
+        return d.addCallback(_cacheProtocol)
+
+
+    def changed(self):
+        """
+        Change the cache token for a resource
+
+        return: A L{Deferred} that fires when the token has been changed.
+        """
+        def _updateCacheToken(proto):
+            return proto.set('cacheToken:%s' % (self._path,),
+                             self._newCacheToken())
+
+        self.log_debug("Changing Cache Token for %r" % (self._path,))
+        d = self._getMemcacheProtocol()
+        d.addCallback(_updateCacheToken)
+        return d
+
+
+
 class BaseResponseCache(LoggingMixIn):
     """
     A base class which provides some common operations
@@ -318,6 +367,37 @@
         self._memcacheProtocol = None
 
 
+    def _tokenForURI(self, uri):
+        """
+        Get a property store for the given C{uri}.
+
+        @param uri: The URI we'd like the token for.
+        @return: A C{str} representing the token for the URI.
+        """
+
+        class __FauxStaticResource(object):
+            def __init__(self, fp):
+                self.fp = fp
+
+
+        fp = self._docroot
+        for childPath in uri.split('/')[:4]:
+            fp = fp.child(childPath)
+
+        return self._getMemcacheProtocol().get('cacheToken:%s' % (fp.path,))
+
+
+    def _getTokens(self, principalURI, requestURI):
+        def _getSecondToken(pToken):
+            d1 = self._tokenForURI(requestURI)
+            d1.addCallback(lambda uToken: (pToken, uToken))
+            return d1
+
+        d = self._tokenForURI(principalURI)
+        d.addCallback(_getSecondToken)
+        return d
+
+
     def _getMemcacheProtocol(self):
         if self._memcacheProtocol is not None:
             return succeed(self._memcacheProtocol)
@@ -382,7 +462,7 @@
             (principalToken, uriToken,
              resp) = cPickle.loads(value)
 
-            d2 = self._getTokensInThread(self._principalURI(request.authnUser),
+            d2 = self._getTokens(self._principalURI(request.authnUser),
                                          request.uri)
 
             d2.addCallback(_checkTokens, (principalToken, uriToken), resp)
@@ -408,22 +488,26 @@
             return proto.set(key, cacheEntry).addCallback(
                 lambda _: response)
 
+        def _makeCacheEntry((pToken, uToken), (key, responseBody)):
+            cacheEntry = cPickle.dumps(
+                (pToken,
+                 uToken,
+                 (response.code,
+                  dict(list(response.headers.getAllRawHeaders())),
+                  responseBody)))
+
+            d2 = self._getMemcacheProtocol()
+            d2.addCallback(_setCacheEntry, key, cacheEntry)
+            return d2
+
         def _cacheResponse((key, responseBody)):
             principalURI = self._principalURI(request.authnUser)
 
             response.headers.removeHeader('date')
             response.stream = MemoryStream(responseBody)
 
-            cacheEntry = cPickle.dumps(
-                (self._tokenForURI(principalURI),
-                 self._tokenForURI(request.uri),
-                 (response.code,
-                  dict(list(response.headers.getAllRawHeaders())),
-                  responseBody)))
-
-            d1 = self._getMemcacheProtocol()
-            d1.addCallback(_setCacheEntry, key, cacheEntry)
-
+            d1 = self._getTokens(principalURI, request.uri)
+            d1.addCallback(_makeCacheEntry, (key, responseBody))
             return d1
 
         if hasattr(request, 'cacheKey'):

Modified: CalendarServer/branches/unified-cache/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/unified-cache/twistedcaldav/test/test_cache.py	2008-05-23 23:45:33 UTC (rev 2467)
+++ CalendarServer/branches/unified-cache/twistedcaldav/test/test_cache.py	2008-05-23 23:46:11 UTC (rev 2468)
@@ -33,6 +33,7 @@
 from twistedcaldav.cache import CacheTokensProperty
 from twistedcaldav.cache import ResponseCache
 from twistedcaldav.cache import MemcacheResponseCache
+from twistedcaldav.cache import MemcacheChangeNotifier
 
 from twistedcaldav.test.util import InMemoryPropertyStore
 
@@ -120,6 +121,35 @@
         return d
 
 
+class MemCacheChangeNotifierTests(TestCase):
+    def setUp(self):
+        self.memcache = InMemoryMemcacheProtocol()
+        self.ccn = MemcacheChangeNotifier(InMemoryPropertyStore())
+        self.ccn._memcacheProtocol = self.memcache
+        self.ccn._newCacheToken = instancemethod(_newCacheToken,
+                                                 self.ccn,
+                                                 MemcacheChangeNotifier)
+
+
+    def assertToken(self, expectedToken):
+        token = self.memcache._cache['cacheToken::memory:'][1]
+        self.assertEquals(token, expectedToken)
+
+
+    def test_cacheTokenPropertyIsProvisioned(self):
+        d = self.ccn.changed()
+        d.addCallback(lambda _: self.assertToken('token0'))
+        return d
+
+
+    def test_changedChangesToken(self):
+        d = self.ccn.changed()
+        d.addCallback(lambda _: self.ccn.changed())
+        d.addCallback(lambda _: self.assertToken('token1'))
+        return d
+
+
+
 class BaseCacheTestMixin(object):
     def assertResponse(self, response, expected):
         self.assertEquals(response.code, expected[0])
@@ -335,14 +365,18 @@
     def setUp(self):
         memcacheStub = InMemoryMemcacheProtocol()
         self.rc = MemcacheResponseCache(None, None, None, None)
+        self.rc.logger.setLevel('debug')
         self.tokens = {}
 
         self.tokens['/calendars/users/cdaboo/'] = 'uriToken0'
         self.tokens['/principals/users/cdaboo/'] = 'principalToken0'
         self.tokens['/principals/users/dreid/'] = 'principalTokenX'
 
-        self.rc._tokenForURI = self.tokens.get
+        def _getToken(uri):
+            return succeed(self.tokens.get(uri))
 
+        self.rc._tokenForURI = _getToken
+
         self.expected_response = (200, Headers({}), "Foo")
 
         expected_key = hashlib.md5(':'.join([str(t) for t in (

Modified: CalendarServer/branches/unified-cache/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/unified-cache/twistedcaldav/test/util.py	2008-05-23 23:45:33 UTC (rev 2467)
+++ CalendarServer/branches/unified-cache/twistedcaldav/test/util.py	2008-05-23 23:46:11 UTC (rev 2468)
@@ -18,6 +18,7 @@
 from twisted.web2.http import HTTPError, StatusResponse
 
 from twisted.internet.defer import succeed
+from twisted.python.filepath import FilePath
 
 from twistedcaldav.static import CalDAVFile
 
@@ -28,11 +29,14 @@
 
 class InMemoryPropertyStore(object):
     def __init__(self):
-        class __FauxResource(object):
-            fp = ':memory:'
+        class _FauxPath(object):
+            path = ':memory:'
 
+        class _FauxResource(object):
+            fp = _FauxPath()
+
         self._properties = {}
-        self.resource = __FauxResource()
+        self.resource = _FauxResource()
 
     def get(self, qname):
         data = self._properties.get(qname)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080523/6a6b763b/attachment-0001.htm 


More information about the calendarserver-changes mailing list