[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