[CalendarServer-changes] [274] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Oct 17 14:10:07 PDT 2006


Revision: 274
          http://trac.macosforge.org/projects/calendarserver/changeset/274
Author:   cdaboo at apple.com
Date:     2006-10-17 14:10:06 -0700 (Tue, 17 Oct 2006)

Log Message:
-----------
Performance tweaks. Includes pre-calculation of inherited aces, faster child resource lookup, more efficient resource lookup.

Modified Paths:
--------------
    CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.resource.patch
    CalendarServer/trunk/lib-patches/Twisted/twisted.web2.server.patch
    CalendarServer/trunk/twistedcaldav/method/report_calquery.py
    CalendarServer/trunk/twistedcaldav/method/report_common.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/static.py

Added Paths:
-----------
    CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.propfind.patch
    CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
    CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch

Added: CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.propfind.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.propfind.patch	                        (rev 0)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.propfind.patch	2006-10-17 21:10:06 UTC (rev 274)
@@ -0,0 +1,22 @@
+Index: twisted/web2/dav/method/propfind.py
+===================================================================
+--- twisted/web2/dav/method/propfind.py	(revision 18375)
++++ twisted/web2/dav/method/propfind.py	(working copy)
+@@ -102,11 +102,15 @@
+ 
+     xml_responses = []
+ 
+-    # FIXME: take advantage of the new generative properties of findChildren
++    # Do some optimisation of access control calculation by determining any inherited ACLs outside of
++    # the child resource loop and supply those to the checkPrivileges on each child.
++    filteredaces = waitForDeferred(self.inheritedACEsforChildren(request))
++    yield filteredaces
++    filteredaces = filteredaces.getResult()
+ 
+     resources = [(self, None)]
+ 
+-    d = self.findChildren(depth, request, lambda x, y: resources.append((x, y)), (davxml.Read(),))
++    d = self.findChildren(depth, request, lambda x, y: resources.append((x, y)), (davxml.Read(),), inherited_aces=filteredaces)
+     x = waitForDeferred(d)
+     yield x
+     x.getResult()

Added: CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	                        (rev 0)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_match.patch	2006-10-17 21:10:06 UTC (rev 274)
@@ -0,0 +1,46 @@
+Index: twisted/web2/dav/method/report_principal_match.py
+===================================================================
+--- twisted/web2/dav/method/report_principal_match.py	(revision 18375)
++++ twisted/web2/dav/method/report_principal_match.py	(working copy)
+@@ -89,13 +89,21 @@
+         responses = []
+         matchcount = 0
+ 
++        selfPrincipal = self.currentPrincipal(request).children[0]
++
++        # Do some optimisation of access control calculation by determining any inherited ACLs outside of
++        # the child resource loop and supply those to the checkPrivileges on each child.
++        filteredaces = waitForDeferred(self.inheritedACEsforChildren(request))
++        yield filteredaces
++        filteredaces = filteredaces.getResult()
++    
++        children = []
++        d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)),
++                                              privileges=(davxml.Read(),), inherited_aces=filteredaces))
++        yield d
++        d.getResult()
++
+         if lookForPrincipals:
+-            selfPrincipal = self.currentPrincipal(request).children[0]
+-
+-            children = []
+-            d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
+-            yield d
+-            d.getResult()
+ 
+             for child, uri in children:
+                 if isPrincipalResource(child) and child.principalMatch(selfPrincipal):
+@@ -115,13 +123,6 @@
+                     yield d
+                     d.getResult()
+         else:
+-            selfPrincipal = self.currentPrincipal(request).children[0]
+-
+-            children = []
+-            d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
+-            yield d
+-            d.getResult()
+-
+             for child, uri in children:
+                 # Try to read the requested property from this resource
+                 try:

Added: CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	                        (rev 0)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.method.report_principal_property_search.patch	2006-10-17 21:10:06 UTC (rev 274)
@@ -0,0 +1,21 @@
+Index: twisted/web2/dav/method/report_principal_property_search.py
+===================================================================
+--- twisted/web2/dav/method/report_principal_property_search.py	(revision 18375)
++++ twisted/web2/dav/method/report_principal_property_search.py	(working copy)
+@@ -145,8 +145,15 @@
+         # Loop over all collections and principal resources within
+         for resource, ruri in resources:
+ 
++            # Do some optimisation of access control calculation by determining any inherited ACLs outside of
++            # the child resource loop and supply those to the checkPrivileges on each child.
++            filteredaces = waitForDeferred(resource.inheritedACEsforChildren(request))
++            yield filteredaces
++            filteredaces = filteredaces.getResult()
++
+             children = []
+-            d = waitForDeferred(resource.findChildren("infinity", request, lambda x, y: children.append((x,y)), privileges=(davxml.Read(),)))
++            d = waitForDeferred(resource.findChildren("infinity", request, lambda x, y: children.append((x,y)),
++                                                      privileges=(davxml.Read(),), inherited_aces=filteredaces))
+             yield d
+             d.getResult()
+ 

Modified: CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.resource.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.resource.patch	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.web2.dav.resource.patch	2006-10-17 21:10:06 UTC (rev 274)
@@ -89,7 +89,94 @@
  
      def listAllprop(self, request):
          """
-@@ -1501,6 +1551,265 @@
+@@ -474,7 +524,7 @@
+         """
+         unimplemented(self)
+ 
+-    def findChildren(self, depth, request, callback, privileges=None):
++    def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
+         """
+         See L{IDAVResource.findChildren}.
+ 
+@@ -491,7 +541,7 @@
+             if privileges is None:
+                 return child
+    
+-            ca = child.checkPrivileges(request, privileges)
++            ca = child.checkPrivileges(request, privileges, inherited_aces=inherited_aces)
+             ca.addCallback(lambda _: child)
+             return ca
+ 
+@@ -514,7 +564,7 @@
+                 completionDeferred.callback(None)
+             else:
+                 childpath = joinURL(basepath, childname)
+-                child = request.locateResource(childpath)
++                child = request.locateChildResource(self, childname)
+                 child.addCallback(_checkPrivileges)
+                 child.addCallbacks(_gotChild, _checkPrivilegesError, (childpath,))
+                 child.addErrback(completionDeferred.errback)
+@@ -530,6 +580,43 @@
+ 
+         return completionDeferred
+ 
++#    def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
++#        """
++#        See L{IDAVResource.findChildren}.
++#
++#        This implementation works for C{depth} values of C{"0"}, C{"1"}, 
++#        and C{"infinity"}.  As long as C{self.listChildren} is implemented
++#        """
++#        assert depth in ("0", "1", "infinity"), "Invalid depth: %s" % (depth,)
++#
++#        completionDeferred = Deferred()
++#
++#        if depth != "0" and self.isCollection():
++#            basepath = request.urlForResource(self)
++#            children = self.listChildren()
++#            for childname in children:
++#                childpath = joinURL(basepath, childname)
++#                child = waitForDeferred(request.locateResource(childpath))
++#                yield child
++#                child = child.getResult()
++#                if privileges is not None:
++#                    try:
++#                        d = waitForDeferred(child.checkPrivileges(request, privileges, inherited_aces=inherited_aces))
++#                        yield d
++#                        d.getResult()
++#                    except AccessDeniedError:
++#                        continue
++#                if child.isCollection():
++#                    callback(child, childpath + "/")
++#                    if depth == "infinity":
++#                        d = waitForDeferred(child.findChildren(depth, request, callback, privileges))
++#                        yield d
++#                        d.getResult()
++#                else:
++#                    callback(child, childpath)
++#
++#    findChildren = deferredGenerator(findChildren)
++
+     def supportedReports(self):
+         """
+         See L{IDAVResource.supportedReports}.
+@@ -904,10 +991,11 @@
+ 
+         resources = [(self, None)]
+ 
+-        x = self.findChildren(depth, request, lambda x, y: resources.append((x,y)))
+-        x = waitForDeferred(x)
+-        yield x
+-        x.getResult()
++        if recurse:
++            x = self.findChildren(depth, request, lambda x, y: resources.append((x,y)))
++            x = waitForDeferred(x)
++            yield x
++            x.getResult()
+ 
+         for resource, uri in resources:
+             acl = waitForDeferred(resource.accessControlList(request, inherited_aces=inherited_aces))
+@@ -1501,6 +1589,265 @@
          return None
  
      ##
@@ -355,7 +442,25 @@
      # HTTP
      ##
  
-@@ -1702,6 +2011,37 @@
+@@ -1548,7 +1895,7 @@
+     """
+     DAV resource with no children.
+     """
+-    def findChildren(self, depth, request, callback, privileges=None):
++    def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
+         return succeed(None)
+ 
+ class DAVPrincipalResource (DAVLeafResource):
+@@ -1574,7 +1921,7 @@
+     def isCollection(self):
+         return False
+ 
+-    def findChildren(self, depth, request, callback, privileges=None):
++    def findChildren(self, depth, request, callback, privileges=None, inherited_aces=None):
+         return succeed(None)
+ 
+     def readProperty(self, property, request):
+@@ -1702,6 +2049,37 @@
  davxml.registerElement(TwistedACLInheritable)
  davxml.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
  

Modified: CalendarServer/trunk/lib-patches/Twisted/twisted.web2.server.patch
===================================================================
--- CalendarServer/trunk/lib-patches/Twisted/twisted.web2.server.patch	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/lib-patches/Twisted/twisted.web2.server.patch	2006-10-17 21:10:06 UTC (rev 274)
@@ -1,8 +1,17 @@
 Index: twisted/web2/server.py
 ===================================================================
---- twisted/web2/server.py	(revision 18289)
+--- twisted/web2/server.py	(revision 18375)
 +++ twisted/web2/server.py	(working copy)
-@@ -156,7 +156,9 @@
+@@ -1,6 +1,8 @@
+ # -*- test-case-name: twisted.web2.test.test_server -*-
+ # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
+ # See LICENSE for details.
++from twisted.internet.defer import succeed
++from twisted.web2.dav.util import joinURL
+ 
+ 
+ """This is a web-sever which integrates with the twisted.internet
+@@ -156,7 +158,9 @@
          self.resources = []
          http.Request.__init__(self, *args, **kw)
  
@@ -13,3 +22,75 @@
          if atEnd:
              self.responseFilters.append(f)
          else:
+@@ -347,6 +351,7 @@
+         return child
+ 
+     _resourcesByURL = weakref.WeakKeyDictionary()
++    _resourcesFromURL = weakref.WeakValueDictionary()
+ 
+     def _rememberURLForResource(self, url, resource):
+         """
+@@ -387,6 +392,11 @@
+         """
+         if url is None: return None
+ 
++        try:
++            return succeed(self._resourcesFromURL[url])
++        except KeyError:
++            pass
++
+         #
+         # Parse the URL
+         #
+@@ -417,7 +427,50 @@
+                 raise f
+             return None
+ 
+-        return defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False)
++        def _registerResource(child):
++            self._resourcesFromURL[url] = child
++            return child
++        
++        d = defer.maybeDeferred(self._getChild, None, self.site.resource, segments, updatepaths=False)
++        d.addCallback(_registerResource)
++        return d
++
++    def locateChildResource(self, res, childpath):
++        """
++        Looks up the child resource with the given name given the parent resource.
++        @param uri: The URL last path segment of the desired resource.
++        @return: a L{Deferred} resulting in the L{IResource} at the
++            given URL or C{None} if no such resource can be located.
++        @raise HTTPError: If C{url} is not a URL on the site that this
++            request is being applied to.  The contained response will
++            have a status code of L{responsecode.BAD_GATEWAY}.
++        @raise HTTPError: If C{url} contains a query or fragment.
++            The contained response will have a status code of
++            L{responsecode.BAD_REQUEST}.
++        """
++        if res is None or childpath is None: return None
++        
++        url = joinURL(self.urlForResource(res), childpath)
++        try:
++            return succeed(self._resourcesFromURL[url])
++        except KeyError:
++            pass
++
++        segment = unquote(childpath)
++
++        def notFound(f):
++            f.trap(http.HTTPError)
++            if f.response.code != responsecode.NOT_FOUND:
++                raise f
++            return None
++
++        def _registerResource(child):
++            self._resourcesFromURL[url] = child
++            return child
++        
++        d = defer.maybeDeferred(self._getChild, None, res, [segment], updatepaths=False)
++        d.addCallback(_registerResource)
++        return d
+ 
+     def _processingFailed(self, reason):
+         if reason.check(http.HTTPError) is not None:

Modified: CalendarServer/trunk/twistedcaldav/method/report_calquery.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_calquery.py	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/twistedcaldav/method/report_calquery.py	2006-10-17 21:10:06 UTC (rev 274)
@@ -148,8 +148,7 @@
             if filteredaces is not None:
                 for name, uid, type in calresource.index().search(filter): #@UnusedVariable
                     # Check privileges - must have at least DAV:read
-                    child_url = joinURL(uri, name)
-                    child = waitForDeferred(request.locateResource(child_url))
+                    child = waitForDeferred(request.locateChildResource(calresource, name))
                     yield child
                     child = child.getResult()
 

Modified: CalendarServer/trunk/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_common.py	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/twistedcaldav/method/report_common.py	2006-10-17 21:10:06 UTC (rev 274)
@@ -329,8 +329,7 @@
             continue
 
         # Check privileges - must have at least CalDAV:read-free-busy
-        child_url = joinURL(uri, name)
-        child = waitForDeferred(request.locateResource(child_url))
+        child = waitForDeferred(request.locateChildResource(calresource, name))
         yield child
         child = child.getResult()
 

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2006-10-17 21:10:06 UTC (rev 274)
@@ -479,8 +479,7 @@
         
         # Look at cuaddress property on each child and do attempt a match
         for childname in self.listChildren():
-            child_url = joinURL(self._url, childname)
-            child = waitForDeferred(request.locateResource(child_url))
+            child = waitForDeferred(request.locateChildResource(self, childname))
             yield child
             child = child.getResult()
             if not isinstance(child, CalendarPrincipalResource):

Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py	2006-10-13 19:54:40 UTC (rev 273)
+++ CalendarServer/trunk/twistedcaldav/static.py	2006-10-17 21:10:06 UTC (rev 274)
@@ -144,8 +144,7 @@
             # Must verify ACLs which means we need a request object at this point
             for name, uid, type in self.index().search(None): #@UnusedVariable
                 try:
-                    child_url = joinURL(request.uri, str(name))
-                    child = waitForDeferred(request.locateResource(child_url))
+                    child = waitForDeferred(request.locateChildResource(self, name))
                     yield child
                     child = child.getResult()
                     child = IDAVResource(child)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20061017/5df879e4/attachment.html


More information about the calendarserver-changes mailing list