[CalendarServer-changes] [179] CalendarServer/branches/users/cdaboo/quota

source_changes at macosforge.org source_changes at macosforge.org
Fri Sep 22 07:25:41 PDT 2006


Revision: 179
          http://trac.macosforge.org/projects/calendarserver/changeset/179
Author:   cdaboo at apple.com
Date:     2006-09-22 07:25:41 -0700 (Fri, 22 Sep 2006)

Log Message:
-----------
Cleaning-up quota code after review.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.idav.patch
    CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.resource.patch
    CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.static
    CalendarServer/branches/users/cdaboo/quota/twistedcaldav/method/put_common.py
    CalendarServer/branches/users/cdaboo/quota/twistedcaldav/static.py

Modified: CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.idav.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.idav.patch	2006-09-22 02:49:46 UTC (rev 178)
+++ CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.idav.patch	2006-09-22 14:25:41 UTC (rev 179)
@@ -2,7 +2,7 @@
 ===================================================================
 --- twisted/web2/dav/idav.py	(revision 18209)
 +++ twisted/web2/dav/idav.py	(working copy)
-@@ -180,6 +180,72 @@
+@@ -180,6 +180,80 @@
              the specified principal.
          """
  
@@ -20,6 +20,14 @@
 +            C{None} if quota is not defined on the resource.
 +        """
 +    
++    def hasQuota(request):
++        """
++        Check whether this resource is undre quota control by checking each parent to see if
++        it has a quota root.
++        
++        @return: C{True} if under quota control, C{False} if not.
++        """
++        
 +    def hasQuotaRoot(request):
 +        """
 +        Determine whether the resource has a quota root.
@@ -49,7 +57,7 @@
 +        Get the size of this resource (if its a collection get total for all children as well).
 +        TODO: Take into account size of dead-properties.
 +
-+        @return: a C{int} containing the size of the resource.
++        @return: a L{Deferred} with a C{int} result containing the size of the resource.
 +        """
 +        
 +    def currentQuotaUse(request):
@@ -57,8 +65,8 @@
 +        Get the cached quota use value, or if not present (or invalid) determine
 +        quota use by brute force.
 +
-+        @return: a C{int} containing the current used byte if this collection
-+            is quota-controlled, or C{None} if not quota controlled.
++        @return: an L{Deferred} with a C{int} result containing the current used byte count if
++            this collection is quota-controlled, or C{None} if not quota controlled.
 +        """
 +        
 +    def updateQuotaUse(request, adjust):
@@ -68,7 +76,7 @@
 +
 +        @param adjust: a C{int} containing the number of bytes added (positive) or
 +        removed (negative) that should be used to adjust the cached total.
-+        @return: a C{int} containing the current used byte if this collection
++        @return: an L{Deferred} with a C{int} result containing the current used byte if this collection
 +            is quota-controlled, or C{None} if not quota controlled.
 +        """
 +

Modified: CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.resource.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.resource.patch	2006-09-22 02:49:46 UTC (rev 178)
+++ CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.resource.patch	2006-09-22 14:25:41 UTC (rev 179)
@@ -13,20 +13,29 @@
  
      3. Live properties may be acted on specially and are stored in the X{dead
         property store}.  These are not listed in the L{liveProperties} attribute,
-@@ -129,6 +131,12 @@
+@@ -125,6 +127,8 @@
+         (dav_namespace, "acl-restrictions"          ), # RFC 3744, section 5.6
+         (dav_namespace, "inherited-acl-set"         ), # RFC 3744, section 5.7
+         (dav_namespace, "principal-collection-set"  ), # RFC 3744, section 5.8
++        (dav_namespace, "quota-available-bytes"     ), # RFC 4331, section 3
++        (dav_namespace, "quota-used-bytes"          ), # RFC 4331, section 4
+ 
          (twisted_dav_namespace, "resource-class"),
      )
+@@ -129,6 +133,12 @@
+         (twisted_dav_namespace, "resource-class"),
+     )
  
 +    # These are live (compued) properties that may exist on only certain resources
 +    dynamicLiveProperties = (
-+         (dav_namespace, "quota-available-bytes"     ), # RFC 4331, section 3
++        (dav_namespace, "quota-available-bytes"     ), # RFC 4331, section 3
 +        (dav_namespace, "quota-used-bytes"          ), # RFC 4331, section 4
 +    )
 +
      def deadProperties(self):
          """
          Provides internal access to the WebDAV dead property store.  You
-@@ -161,6 +169,20 @@
+@@ -161,6 +171,15 @@
          if qname[0] == twisted_private_namespace:
              return succeed(False)
  
@@ -34,20 +43,15 @@
 +        if (qname in self.dynamicLiveProperties):
 +            namespace, name = qname
 +            if namespace == dav_namespace:
-+                if name == "quota-available-bytes":
++                if name in ["quota-available-bytes", "quota-used-bytes"]:
 +                    d = self.quota(request)
 +                    d.addCallback(lambda qvalue: qvalue is not None)
 +                    return d
-+    
-+                if name == "quota-used-bytes":
-+                    d = self.quota(request)
-+                    d.addCallback(lambda qvalue: qvalue is not None)
-+                    return d
 +        
          return succeed(qname in self.liveProperties or self.deadProperties().contains(qname))
  
      def readProperty(self, property, request):
-@@ -263,6 +285,32 @@
+@@ -263,6 +282,32 @@
                          # TODO: Merge change from original patch
                          lambda: self.safeAccessControlList(request)
                      )
@@ -80,7 +84,7 @@
  
              if namespace == twisted_dav_namespace:
                  if name == "resource-class":
-@@ -320,7 +368,8 @@
+@@ -320,7 +365,8 @@
                  qname = property.qname()
                  sname = property.sname()
  
@@ -90,7 +94,7 @@
                  raise HTTPError(StatusResponse(
                      responsecode.FORBIDDEN,
                      "Live property %s cannot be deleted." % (sname,)
-@@ -343,6 +392,14 @@
+@@ -343,6 +389,14 @@
          # FIXME: A set would be better here, that that's a python 2.4+ feature.
          qnames = list(self.liveProperties)
  
@@ -105,7 +109,7 @@
          for qname in self.deadProperties().list():
              if (qname not in qnames) and (qname[0] != twisted_private_namespace):
                  qnames.append(qname)
-@@ -347,7 +404,9 @@
+@@ -347,7 +401,9 @@
              if (qname not in qnames) and (qname[0] != twisted_private_namespace):
                  qnames.append(qname)
  
@@ -116,7 +120,7 @@
  
      def listAllprop(self, request):
          """
-@@ -1507,6 +1566,230 @@
+@@ -1507,6 +1563,264 @@
          return None
  
      ##
@@ -161,7 +165,9 @@
 +        if self.isCollection():
 +            qroot = self.quotaRoot(request)
 +            if qroot is not None:
-+                used = self.currentQuotaUse(request)
++                used = waitForDeferred(self.currentQuotaUse(request))
++                yield used
++                used = used.getResult()
 +                available = qroot - used
 +                if available < 0:
 +                    available = 0
@@ -186,6 +192,32 @@
 +    
 +    quota = deferredGenerator(quota)
 +
++    def hasQuota(self, request):
++        """
++        Check whether this resource is undre quota control by checking each parent to see if
++        it has a quota root.
++        
++        @return: C{True} if under quota control, C{False} if not.
++        """
++        
++        # Check this one first
++        if self.hasQuotaRoot(request):
++            yield True
++        
++        # Look at each parent
++        url = request.urlForResource(self)
++        if url != "/":
++            parent = waitForDeferred(request.locateResource(parentForURL(url)))
++            yield parent
++            parent = parent.getResult()
++            d = waitForDeferred(parent.hasQuota(request))
++            yield d
++            yield d.getResult()
++        else:
++            yield False
++    
++    hasQuota = deferredGenerator(hasQuota)
++        
 +    def hasQuotaRoot(self, request):
 +        """
 +        @return: a C{True} if this resource has quota root, C{False} otherwise.
@@ -282,13 +314,15 @@
 +        Update the quota used value on all quota root parents of this resource.
 +
 +        @param adjust: a C{int} containing the number of bytes added (positive) or
-+        removed (negative) that should be used to adjust the cached total.
++            removed (negative) that should be used to adjust the cached total.
 +        """
 +        
 +        # Check this resource first
 +        if self.isCollection():
 +            if self.hasQuotaRoot(request):
-+                self.updateQuotaUse(request, adjust)
++                d = waitForDeferred(self.updateQuotaUse(request, adjust))
++                yield d
++                d.getResult()
 +        
 +        # Check the next parent
 +        url = request.urlForResource(self)
@@ -309,7 +343,7 @@
 +        Get the cached quota use value, or if not present (or invalid) determine
 +        quota use by brute force.
 +
-+        @return: a C{int} containing the current used byte if this collection
++        @return: an L{Deferred} with a C{int} result containing the current used byte if this collection
 +            is quota-controlled, or C{None} if not quota controlled.
 +        """
 +        assert self.isCollection(), "Only collections can have a quota root"
@@ -317,15 +351,15 @@
 +        
 +        # Try to get the cached value property
 +        if self.hasDeadProperty(TwistedQuotaUsedProperty):
-+            return int(str(self.readDeadProperty(TwistedQuotaUsedProperty)))
++            return succeed(int(str(self.readDeadProperty(TwistedQuotaUsedProperty))))
 +        else:
-+            # Do brute force size determination
-+            result = self.quotaSize(request)
-+            
-+            # Cache the brute force value in the private property
-+            self.writeDeadProperty(TwistedQuotaUsedProperty.fromString(str(result)))
-+            
-+            return result
++            # Do brute force size determination and cache the result in the private property
++            def _defer(result):
++                self.writeDeadProperty(TwistedQuotaUsedProperty.fromString(str(result)))
++                return result
++            d = self.quotaSize(request)
++            d.addCallback(_defer)
++            return d
 +
 +    def updateQuotaUse(self, request, adjust):
 +        """
@@ -333,21 +367,25 @@
 +
 +        @param adjust: a C{int} containing the number of bytes added (positive) or
 +        removed (negative) that should be used to adjust the cached total.
-+        @return: a C{int} containing the current used byte if this collection
++        @return: an L{Deferred} with a C{int} result containing the current used byte if this collection
 +            is quota-controlled, or C{None} if not quota controlled.
 +        """
 +        assert self.isCollection(), "Only collections can have a quota root"
 +        
 +        # Get current value
-+        size = self.currentQuotaUse(request)
-+        size += adjust
-+        self.writeDeadProperty(TwistedQuotaUsedProperty.fromString(str(size)))
++        def _defer(size):
++            size += adjust
++            self.writeDeadProperty(TwistedQuotaUsedProperty.fromString(str(size)))
++
++        d = self.currentQuotaUse(request)
++        d.addCallback(_defer)
++        return d
 +        
 +    ##
      # HTTP
      ##
  
-@@ -1741,6 +2024,28 @@
+@@ -1741,6 +2055,28 @@
  
  davxml.registerElement(TwistedAccessDisabledProperty)
  

Modified: CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.static
===================================================================
--- CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.static	2006-09-22 02:49:46 UTC (rev 178)
+++ CalendarServer/branches/users/cdaboo/quota/lib-patches/Twisted/twisted.web2.dav.static	2006-09-22 14:25:41 UTC (rev 179)
@@ -2,7 +2,7 @@
 ===================================================================
 --- twisted/web2/dav/static.py	(revision 18209)
 +++ twisted/web2/dav/static.py	(working copy)
-@@ -98,6 +98,57 @@
+@@ -98,6 +98,61 @@
          return succeed(davPrivilegeSet)
  
      ##
@@ -15,18 +15,18 @@
 +        TODO: Take into account size of dead-properties. Does stat
 +            include xattrs size?
 +
-+        @return: a C{int} containing the size of the resource.
++        @return: an L{Deferred} with a C{int} result containing the size of the resource.
 +        """
 +        if self.isCollection():
 +            return self.collectionQuotaUse(request)
 +        else:
-+            return self.fp.getsize()
++            return succeed(self.fp.getsize())
 +
 +    def collectionQuotaUse(self, request):
 +        """
 +        Brute force determination of quota used by this collection.
 +
-+        @return: a C{int} containing the current used byte if this collection
++        @return: an L{Deferred} with a C{int} result containing the current used byte if this collection
 +            is quota-controlled, or C{None} if not quota controlled.
 +        """
 +        assert self.isCollection(), "Only collections can have a quota root"
@@ -44,7 +44,9 @@
 +                child = top.child(f)
 +                if child.isdir():
 +                    # It's a directory, recurse into it
-+                    total += walktree(child)
++                    result = waitForDeferred(walktree(child))
++                    yield result
++                    total += result.getResult()
 +                elif child.isfile():
 +                    # It's a file, call the callback function
 +                    total += child.getsize()
@@ -52,8 +54,10 @@
 +                    # Unknown file type, print a message
 +                    pass
 +        
-+            return total
++            yield total
 +        
++        walktree = deferredGenerator(walktree)
++
 +        return walktree(self.fp)
 +
 +    ##

Modified: CalendarServer/branches/users/cdaboo/quota/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/quota/twistedcaldav/method/put_common.py	2006-09-22 02:49:46 UTC (rev 178)
+++ CalendarServer/branches/users/cdaboo/quota/twistedcaldav/method/put_common.py	2006-09-22 14:25:41 UTC (rev 179)
@@ -384,7 +384,9 @@
         yield destquota
         destquota = destquota.getResult()
         if destquota is not None and destination.exists():
-            old_dest_size = destination.quotaSize(request)
+            old_dest_size = waitForDeferred(destination.quotaSize(request))
+            yield old_dest_size
+            old_dest_size = old_dest_size.getResult()
         else:
             old_dest_size = 0
             
@@ -393,7 +395,9 @@
             yield sourcequota
             sourcequota = sourcequota.getResult()
             if sourcequota is not None and source.exists():
-                old_source_size = source.quotaSize(request)
+                old_source_size = waitForDeferred(source.quotaSize(request))
+                yield old_source_size
+                old_source_size = old_source_size.getResult()
             else:
                 old_source_size = 0
         else:
@@ -531,7 +535,9 @@
         # Do quota check on destination
         if destquota is not None:
             # Get size of new/old resources
-            new_dest_size = destination.quotaSize(request)
+            new_dest_size = waitForDeferred(destination.quotaSize(request))
+            yield new_dest_size
+            new_dest_size = new_dest_size.getResult()
             diff_size = new_dest_size - old_dest_size
             if diff_size >= destquota[0]:
                 log.err("Over quota: available %d, need %d" % (destquota[0], diff_size))

Modified: CalendarServer/branches/users/cdaboo/quota/twistedcaldav/static.py
===================================================================
--- CalendarServer/branches/users/cdaboo/quota/twistedcaldav/static.py	2006-09-22 02:49:46 UTC (rev 178)
+++ CalendarServer/branches/users/cdaboo/quota/twistedcaldav/static.py	2006-09-22 14:25:41 UTC (rev 179)
@@ -309,47 +309,51 @@
     # Quota
     ##
 
-    def collectionQuotaUse(self, request):
+    def quotaSize(self, request):
         """
-        Brute force determination of quota used by this collection.
+        Get the size of this resource.
+        TODO: Take into account size of dead-properties. Does stat
+            include xattrs size?
 
-        @return: a C{int} containing the current used byte if this collection
-            is quota-controlled, or C{None} if not quota controlled.
+        @return: an L{Deferred} with a C{int} result containing the size of the resource.
         """
-        assert self.isCollection(), "Only collections can have a quota root"
-
-        # Do default if not a calendar collection
-        if not self.isPseudoCalendarCollection():
-            return super(CalDAVFile, self).collectionQuotaUse(request)
-
-        def walktree(top, top_level = False):
-            """
-            Recursively descend the directory tree rooted at top,
-            calling the callback function for each regular file
-            """
-        
-            total = 0
-            for f in top.listdir():
+        if self.isCollection():
+            def walktree(top, top_level = False):
+                """
+                Recursively descend the directory tree rooted at top,
+                calling the callback function for each regular file
                 
-                # Ignore the database
-                if top_level and f == db_basename:
-                    continue
+                @param top: L{FilePath} for the directory to walk.
+                """
+            
+                total = 0
+                for f in top.listdir():
+    
+                    # Ignore the database
+                    if top_level and f == db_basename:
+                        continue
+    
+                    child = top.child(f)
+                    if child.isdir():
+                        # It's a directory, recurse into it
+                        result = waitForDeferred(walktree(child))
+                        yield result
+                        total += result.getResult()
+                    elif child.isfile():
+                        # It's a file, call the callback function
+                        total += child.getsize()
+                    else:
+                        # Unknown file type, print a message
+                        pass
+            
+                yield total
+            
+            walktree = deferredGenerator(walktree)
+    
+            return walktree(self.fp, True)
+        else:
+            return succeed(self.fp.getsize())
 
-                child = top.child(f)
-                if child.isdir():
-                    # It's a directory, recurse into it
-                    total += walktree(child)
-                elif child.isfile():
-                    # It's a file, call the callback function
-                    total += child.getsize()
-                else:
-                    # Unknown file type, print a message
-                    pass
-        
-            return total
-        
-        return walktree(self.fp, True)
-
     ##
     # Utilities
     ##

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20060922/9cde76c8/attachment.html


More information about the calendarserver-changes mailing list