[CalendarServer-changes] [2359] CalendarServer/branches/propfind-cache/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Apr 30 16:16:08 PDT 2008


Revision: 2359
          http://trac.macosforge.org/projects/calendarserver/changeset/2359
Author:   dreid at apple.com
Date:     2008-04-30 16:16:07 -0700 (Wed, 30 Apr 2008)

Log Message:
-----------
Start of a resource that caches responses

Modified Paths:
--------------
    CalendarServer/branches/propfind-cache/twistedcaldav/cache.py
    CalendarServer/branches/propfind-cache/twistedcaldav/root.py
    CalendarServer/branches/propfind-cache/twistedcaldav/test/test_cache.py
    CalendarServer/branches/propfind-cache/twistedcaldav/test/test_root.py

Modified: CalendarServer/branches/propfind-cache/twistedcaldav/cache.py
===================================================================
--- CalendarServer/branches/propfind-cache/twistedcaldav/cache.py	2008-04-28 17:35:23 UTC (rev 2358)
+++ CalendarServer/branches/propfind-cache/twistedcaldav/cache.py	2008-04-30 23:16:07 UTC (rev 2359)
@@ -15,12 +15,15 @@
 ##
 
 import uuid
+import time
+import os
 
+from twisted.python.filepath import FilePath
 
 from twisted.web2.dav import davxml
 from twisted.web2.http import HTTPError
+from twisted.web2.dav.xattrprops import xattrPropertyStore
 
-
 class CacheTokensProperty(davxml.WebDAVTextElement):
     namespace = davxml.twisted_private_namespace
     name = "cacheTokens"
@@ -102,3 +105,75 @@
             return True
 
         return False
+
+
+
+class PropfindCachingResource(object):
+    CACHE_TIMEOUT = 60*60 # 1 hour
+
+    propertyStoreFactory = xattrPropertyStore
+    observerFactory = CacheChangeObserver
+
+    def __init__(self, docroot, timeFunc=time.time):
+        self._docroot = docroot
+        self._responses = {}
+        self._observers = {}
+        self._timeFunc = timeFunc
+
+
+    def _tokenPathForURI(self, uri):
+        tokenPath = self._docroot
+
+        for childName in uri.split('/')[:4]:
+            tokenPath = tokenPath.child(childName)
+
+        return tokenPath
+
+
+    def _observerForURI(self, uri):
+        class FauxStaticResource(object):
+            def __init__(self, fp):
+                self.fp = fp
+
+        propertyStore = self.propertyStoreFactory(
+                FauxStaticResource(self._tokenPathForURI(uri)))
+
+        return self.observerFactory(propertyStore)
+
+
+    def _cacheResponse(self, response, request):
+        if getattr(request, 'cacheRequest', False):
+            if request.uri not in self._observers:
+                self._observers[request.uri] = self._observerForURI(request.uri)
+
+            self._responses[(request.method,
+                             request.uri,
+                             request.authnUser)] = (self._timeFunc(),
+                                                    response)
+
+        return response
+
+
+    def renderHTTP(self, request):
+        key = (request.method, request.uri, request.authnUser)
+
+        if key in self._responses:
+            cacheTime, cachedResponse = self._responses[key]
+            if cacheTime + CACHE_TIMEOUT <= self._timeFunc():
+                if (request.uri in self._observers and
+                    self._observers[request.uri]()):
+
+                    return cachedResponse
+
+        def _renderResource(resource, request):
+            request.addResponseFilter(self._cacheResponse)
+            return resource.renderHTTP(request)
+
+        request.notInCache = True
+        d = request.locateResource(request.uri)
+        d.addCallback(_renderResource, request)
+        return d
+
+
+    def locateChild(self, request, segments):
+        return self, []

Modified: CalendarServer/branches/propfind-cache/twistedcaldav/root.py
===================================================================
--- CalendarServer/branches/propfind-cache/twistedcaldav/root.py	2008-04-28 17:35:23 UTC (rev 2358)
+++ CalendarServer/branches/propfind-cache/twistedcaldav/root.py	2008-04-30 23:16:07 UTC (rev 2359)
@@ -86,19 +86,19 @@
             # Figure out the "username" from the davxml.Principal object
             request.checkingSACL = True
             d = request.locateResource(authzUser.children[0].children[0].data)
-            
+
             def _checkedSACLCb(principal):
                 delattr(request, "checkingSACL")
                 username = principal.record.shortName
-                
+
                 if RootResource.CheckSACL(username, self.saclService) != 0:
                     log.msg("User '%s' is not enabled with the '%s' SACL" % (username, self.saclService,))
                     return Failure(HTTPError(403))
-    
+
                 # Mark SACL's as having been checked so we can avoid doing it multiple times
                 request.checkedSACL = True
                 return True
-            
+
             d.addCallback(_checkedSACLCb)
             return d
 

Modified: CalendarServer/branches/propfind-cache/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/propfind-cache/twistedcaldav/test/test_cache.py	2008-04-28 17:35:23 UTC (rev 2358)
+++ CalendarServer/branches/propfind-cache/twistedcaldav/test/test_cache.py	2008-04-30 23:16:07 UTC (rev 2359)
@@ -18,9 +18,12 @@
 
 from twisted.trial.unittest import TestCase
 
+from twisted.python.filepath import FilePath
+
 from twistedcaldav.cache import CacheChangeNotifier
 from twistedcaldav.cache import CacheTokensProperty
 from twistedcaldav.cache import CacheChangeObserver
+from twistedcaldav.cache import PropfindCachingResource
 
 from twistedcaldav.test.util import InMemoryPropertyStore
 
@@ -147,3 +150,22 @@
 
         self.assertEquals(self.observer.dataHasChanged(), True)
         self.assertEquals(self.observer.propertiesHaveChanged(), False)
+
+
+
+class PropfindCachingResourceTests(TestCase):
+    # _tokenPathForURI tests
+    def test_tokenPathForURI(self):
+        pcr = PropfindCachingResource(FilePath('/root'))
+        paths = [
+            ('/principals/__uids__/557C330A-06E2-403B-BC24-CE3A253CDB5B/',
+             '/root/principals/__uids__/557C330A-06E2-403B-BC24-CE3A253CDB5B'),
+            ('/calendars/users/dreid/', '/root/calendars/users/dreid'),
+            ('/calendars/users/dreid/calendar', '/root/calendars/users/dreid')]
+
+        for inPath, outPath in paths:
+            self.assertEquals(pcr._tokenPathForURI(inPath).path, outPath)
+
+
+    def test_observerForURI(self):
+        pcr = PropfindCachingResource(FilePath('/root'))

Modified: CalendarServer/branches/propfind-cache/twistedcaldav/test/test_root.py
===================================================================
--- CalendarServer/branches/propfind-cache/twistedcaldav/test/test_root.py	2008-04-28 17:35:23 UTC (rev 2358)
+++ CalendarServer/branches/propfind-cache/twistedcaldav/test/test_root.py	2008-04-30 23:16:07 UTC (rev 2359)
@@ -64,11 +64,11 @@
             '/principals/',
             directory)
 
-        # Otherwise the tests that never touch the root resource will 
+        # Otherwise the tests that never touch the root resource will
         # fail on teardown.
         principals.provision()
 
-        root = RootResource(self.docroot, 
+        root = RootResource(self.docroot,
                             principalCollections=[principals])
 
         root.putChild('principals',
@@ -78,8 +78,8 @@
         portal.registerChecker(directory)
 
         self.root = auth.AuthenticationWrapper(
-            root, 
-            portal, 
+            root,
+            portal,
             credentialFactories=(basic.BasicCredentialFactory("Test realm"),),
             loginInterfaces=(auth.IPrincipal,))
 
@@ -88,7 +88,7 @@
     def test_noSacls(self):
         """
         Test the behaviour of locateChild when SACLs are not enabled.
-        
+
         should return a valid resource
         """
         self.root.resource.useSacls = False
@@ -111,7 +111,7 @@
 
     def test_inSacls(self):
         """
-        Test the behavior of locateChild when SACLs are enabled and the 
+        Test the behavior of locateChild when SACLs are enabled and the
         user is in the SACL group
 
         should return a valid resource
@@ -125,7 +125,7 @@
             headers=http_headers.Headers({
                     'Authorization': ['basic', '%s' % (
                             'dreid:dierd'.encode('base64'),)]}))
-        
+
         resrc, segments = self.root.locateChild(request,
                                          ['principals'])
 
@@ -137,10 +137,10 @@
 
             self.assertEquals(segments, [])
 
-            self.assertEquals(request.authzUser, 
+            self.assertEquals(request.authzUser,
                               davxml.Principal(
                     davxml.HRef('/principals/__uids__/5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1/')))
-            
+
         d = defer.maybeDeferred(resrc.locateChild, request, ['principals'])
         d.addCallback(_Cb)
 
@@ -150,7 +150,7 @@
         """
         Test the behavior of locateChild when SACLs are enabled and the
         user is not in the SACL group
-        
+
         should return a 403 forbidden response
         """
         self.root.resource.useSacls = True
@@ -162,14 +162,14 @@
             headers=http_headers.Headers({
                     'Authorization': ['basic', '%s' % (
                             'wsanchez:zehcnasw'.encode('base64'),)]}))
-        
+
         resrc, segments = self.root.locateChild(request,
                                          ['principals'])
 
         def _Eb(failure):
             failure.trap(HTTPError)
             self.assertEquals(failure.value.response.code, 403)
-            
+
         d = defer.maybeDeferred(resrc.locateChild, request, ['principals'])
         d.addErrback(_Eb)
 
@@ -179,7 +179,7 @@
         """
         Test the behavior of locateChild when SACLs are enabled and the request
         is unauthenticated
-        
+
         should return a 401 UnauthorizedResponse
         """
 
@@ -208,7 +208,7 @@
 
     def test_badCredentials(self):
         """
-        Test the behavior of locateChild when SACLS are enabled, and 
+        Test the behavior of locateChild when SACLS are enabled, and
         incorrect credentials are given.
 
         should return a 401 UnauthorizedResponse
@@ -222,14 +222,14 @@
             headers=http_headers.Headers({
                     'Authorization': ['basic', '%s' % (
                             'dreid:dreid'.encode('base64'),)]}))
-        
+
         resrc, segments = self.root.locateChild(request,
                                          ['principals'])
 
         def _Eb(failure):
             failure.trap(HTTPError)
             self.assertEquals(failure.value.response.code, 401)
-            
+
         d = defer.maybeDeferred(resrc.locateChild, request, ['principals'])
         d.addErrback(_Eb)
 
@@ -241,7 +241,7 @@
 
             if response.code != responsecode.FORBIDDEN:
                 self.fail("Incorrect response for DELETE /: %s" % (response.code,))
-            
+
         request = SimpleRequest(self.site, "DELETE", "/")
         return self.send(request, do_test)
 
@@ -251,7 +251,7 @@
 
             if response.code != responsecode.FORBIDDEN:
                 self.fail("Incorrect response for COPY /: %s" % (response.code,))
-            
+
         request = SimpleRequest(
             self.site,
             "COPY",
@@ -266,7 +266,7 @@
 
             if response.code != responsecode.FORBIDDEN:
                 self.fail("Incorrect response for MOVE /: %s" % (response.code,))
-            
+
         request = SimpleRequest(
             self.site,
             "MOVE",
@@ -274,4 +274,3 @@
             headers=http_headers.Headers({"Destination":"/copy/"})
         )
         return self.send(request, do_test)
-        

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080430/6da1d618/attachment-0001.html


More information about the calendarserver-changes mailing list