[CalendarServer-changes] [7728] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Jul 7 02:45:17 PDT 2011


Revision: 7728
          http://trac.macosforge.org/projects/calendarserver/changeset/7728
Author:   glyph at apple.com
Date:     2011-07-07 02:45:15 -0700 (Thu, 07 Jul 2011)
Log Message:
-----------
Allow attachment quota enforcement to be disabled with a UserQuota of 0 again.

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tap/util.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
    CalendarServer/trunk/twistedcaldav/test/util.py
    CalendarServer/trunk/txdav/caldav/datastore/file.py
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
    CalendarServer/trunk/txdav/caldav/icalendarstore.py
    CalendarServer/trunk/txdav/common/datastore/file.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/test/util.py

Property Changed:
----------------
    CalendarServer/trunk/


Property changes on: CalendarServer/trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/wsanchez/transations:5515-5593
   + /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/generic-sqlstore:6167-6191
/CalendarServer/branches/new-store:5594-5934
/CalendarServer/branches/new-store-no-caldavfile:5911-5935
/CalendarServer/branches/new-store-no-caldavfile-2:5936-5981
/CalendarServer/branches/users/cdaboo/batchupload-6699:6700-7198
/CalendarServer/branches/users/cdaboo/cached-subscription-calendars-5692:5693-5702
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/more-sharing-5591:5592-5601
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/cdaboo/pods:7297-7377
/CalendarServer/branches/users/cdaboo/pycalendar:7085-7206
/CalendarServer/branches/users/cdaboo/pycard:7227-7237
/CalendarServer/branches/users/cdaboo/relative-config-paths-5070:5071-5105
/CalendarServer/branches/users/cdaboo/shared-calendars-5187:5188-5440
/CalendarServer/branches/users/cdaboo/timezones:7443-7699
/CalendarServer/branches/users/glyph/conn-limit:6574-6577
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/glyph/dalify:6932-7023
/CalendarServer/branches/users/glyph/db-reconnect:6824-6876
/CalendarServer/branches/users/glyph/deploybuild:7563-7572
/CalendarServer/branches/users/glyph/disable-quota:7718-7727
/CalendarServer/branches/users/glyph/dont-start-postgres:6592-6614
/CalendarServer/branches/users/glyph/linux-tests:6893-6900
/CalendarServer/branches/users/glyph/misc-portability-fixes:7365-7374
/CalendarServer/branches/users/glyph/more-deferreds-6:6322-6368
/CalendarServer/branches/users/glyph/more-deferreds-7:6369-6445
/CalendarServer/branches/users/glyph/new-export:7444-7485
/CalendarServer/branches/users/glyph/oracle:7106-7155
/CalendarServer/branches/users/glyph/oracle-nulls:7340-7351
/CalendarServer/branches/users/glyph/quota:7604-7637
/CalendarServer/branches/users/glyph/sendfdport:5388-5424
/CalendarServer/branches/users/glyph/sharedpool:6490-6550
/CalendarServer/branches/users/glyph/sql-store:5929-6073
/CalendarServer/branches/users/glyph/subtransactions:7248-7258
/CalendarServer/branches/users/glyph/uidexport:7673-7676
/CalendarServer/branches/users/glyph/use-system-twisted:5084-5149
/CalendarServer/branches/users/sagen/inboxitems:7380-7381
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/purge_old_events:6735-6746
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/branches/users/wsanchez/transations:5515-5593

Modified: CalendarServer/trunk/calendarserver/tap/util.py
===================================================================
--- CalendarServer/trunk/calendarserver/tap/util.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/calendarserver/tap/util.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -188,18 +188,21 @@
         )
     else:
         notifierFactory = None
+    quota = config.UserQuota
+    if quota == 0:
+        quota = None
     if txnFactory is not None:
         return CommonSQLDataStore(
             txnFactory, notifierFactory, FilePath(config.AttachmentsRoot),
             config.EnableCalDAV, config.EnableCardDAV,
-            quota=config.UserQuota
+            quota=quota
         )
     else:
         return CommonFileDataStore(
             FilePath(config.DocumentRoot),
             notifierFactory, config.EnableCalDAV, config.EnableCardDAV,
-            quota=config.UserQuota
-        ) 
+            quota=quota
+        )
 
 
 

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -2062,27 +2062,32 @@
     def isCollection(self):
         return True
 
+
     def quotaSize(self, request):
         # FIXME: tests, workingness
         return succeed(0)
 
+
     def hasQuotaRoot(self, request):
         """
-        Always get quota root value from config.
+        Is this resource a quota root?  This returns True if the backend is
+        enforcing quota.
 
         @return: a C{True} if this resource has quota root, C{False} otherwise.
         """
-        return config.UserQuota != 0
-    
+        return self._newStoreHome.quotaAllowedBytes() is None
+
+
     def quotaRoot(self, request):
         """
-        Always get quota root value from config.
+        Retrieve the number of total allowed bytes from the backend.
 
         @return: a C{int} containing the maximum allowed bytes if this
             collection is quota-controlled, or C{None} if not quota controlled.
         """
         return self._newStoreHome.quotaAllowedBytes()
 
+
     def currentQuotaUse(self, request):
         """
         Get the quota use value

Modified: CalendarServer/trunk/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_wrapping.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/twistedcaldav/test/test_wrapping.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -406,7 +406,7 @@
             "PUT", "wsanchez"
         )
         self.requestUnderTest.stream = MemoryStream(
-            "x" * deriveQuota(self.id()) * 2)
+            "x" * deriveQuota(self) * 2)
         try:
             result = yield calendarObject.http_PUT(self.requestUnderTest)
         except HTTPError, he:

Modified: CalendarServer/trunk/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/util.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/twistedcaldav/test/util.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -105,7 +105,7 @@
         hook for subclasses to override to provide different data stores.
         """
         return CommonDataStore(FilePath(config.DocumentRoot), None, True, False,
-                               quota=deriveQuota(self.id()))
+                               quota=deriveQuota(self))
 
 
     def setupCalendars(self):

Modified: CalendarServer/trunk/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/caldav/datastore/file.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -621,9 +621,9 @@
         newSize = self._file.tell()
         # FIXME: do anything
         self._file.close()
-
-        if home.quotaAllowedBytes() < (home.quotaUsedBytes()
-                                       + (newSize - oldSize)):
+        allowed = home.quotaAllowedBytes()
+        if allowed is not None and allowed < (home.quotaUsedBytes()
+                                              + (newSize - oldSize)):
             self._path.remove()
             return fail(QuotaExceeded())
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -800,8 +800,9 @@
 
         oldSize = self._attachment.size()
 
-        if home.quotaAllowedBytes() < ((yield home.quotaUsedBytes())
-                                       + (len(self._buf) - oldSize)):
+        allowed = home.quotaAllowedBytes()
+        if allowed is not None and allowed < ((yield home.quotaUsedBytes())
+                                              + (len(self._buf) - oldSize)):
             if self._creating:
                 yield self._attachment._internalRemove()
             raise QuotaExceeded()

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -54,6 +54,7 @@
 from txdav.caldav.icalendarstore import IAttachmentStorageTransport
 from txdav.caldav.icalendarstore import QuotaExceeded
 from txdav.common.datastore.test.util import deriveQuota
+from txdav.common.datastore.test.util import withSpecialQuota
 from twistedcaldav.ical import Component
 
 storePath = FilePath(__file__).parent().child("calendar_store")
@@ -1611,13 +1612,26 @@
         L{ICalendarHome.quotaAllowedBytes} should return the configuration value
         passed to the calendar store's constructor.
         """
-        expected = deriveQuota(self.id())
+        expected = deriveQuota(self)
         home = yield self.homeUnderTest()
         actual = home.quotaAllowedBytes()
         self.assertEquals(expected, actual)
 
 
+    @withSpecialQuota(None)
     @inlineCallbacks
+    def test_quotaUnlimited(self):
+        """
+        When L{ICalendarHome.quotaAllowedBytes} returns C{None}, quota is
+        unlimited; any sized attachment can be stored.
+        """
+        home = yield self.homeUnderTest()
+        allowed = home.quotaAllowedBytes()
+        self.assertIdentical(allowed, None)
+        yield self.test_createAttachment()
+
+
+    @inlineCallbacks
     def test_quotaTransportAddress(self):
         """
         Since L{IAttachmentStorageTransport} is a subinterface of L{ITransport},

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/test_file.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -67,7 +67,7 @@
 
     testID = test.id()
     test.calendarStore = CalendarStore(storeRootPath, test.notifierFactory,
-                                       quota=deriveQuota(testID))
+                                       quota=deriveQuota(test))
     test.txn = test.calendarStore.newTransaction(testID + "(old)")
     assert test.calendarStore is not None, "No calendar store?"
 

Modified: CalendarServer/trunk/txdav/caldav/icalendarstore.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/icalendarstore.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/caldav/icalendarstore.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -177,11 +177,13 @@
 
     def quotaAllowedBytes():
         """
-        The number of bytes of quota that the user is allowed to access.
+        The number of bytes of data that the user is allowed to store in this
+        calendar home.  If quota is not enforced for this calendar home, this
+        will return C{None}.
 
-        Currently this is only enforced / tracked against attachment data.
+        Currently this is only enforced against attachment data.
 
-        @rtype: C{int}
+        @rtype: C{int} or C{NoneType}
         """
 
 
@@ -189,6 +191,8 @@
         """
         The number of bytes counted towards the user's quota.
 
+        Currently this is only tracked against attachment data.
+
         @rtype: C{int}
         """
 

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -82,14 +82,14 @@
         stores all calendar and addressbook data for a group of UIDs.
 
     @ivar quota: the amount of space granted to each calendar home (in bytes)
-        for storing attachments.
+        for storing attachments, or C{None} if quota should not be enforced.
 
-    @type quota: C{int}
+    @type quota: C{int} or C{NoneType}
     """
     implements(ICalendarStore)
 
     def __init__(self, path, notifierFactory, enableCalendars=True,
-        enableAddressBooks=True, quota=(2 ** 20)):
+                 enableAddressBooks=True, quota=(2 ** 20)):
         """
         Create a store.
 

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -116,9 +116,9 @@
         there is more than one store.  (Useful mostly for unit tests.)
 
     @ivar quota: the amount of space granted to each calendar home (in bytes)
-        for storing attachments.
+        for storing attachments, or C{None} if quota should not be enforced.
 
-    @type quota: C{int}
+    @type quota: C{int} or C{NoneType}
     """
 
     implements(ICalendarStore)

Modified: CalendarServer/trunk/txdav/common/datastore/test/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/test/util.py	2011-07-07 09:35:44 UTC (rev 7727)
+++ CalendarServer/trunk/txdav/common/datastore/test/util.py	2011-07-07 09:45:15 UTC (rev 7728)
@@ -49,6 +49,9 @@
 md5key = PropertyName.fromElement(TwistedGETContentMD5)
 
 def allInstancesOf(cls):
+    """
+    Use L{gc.get_referrers} to retrieve all instances of a given class.
+    """
     for o in gc.get_referrers(cls):
         if isinstance(o, cls):
             yield o
@@ -56,6 +59,12 @@
 
 
 def dumpConnectionStatus():
+    """
+    Dump all L{DiagnosticConnectionWrapper} objects to standard output.  This
+    function is useful for diagnosing connection leaks that corrupt state
+    between tests.  (It is currently not invoked anywhere, but may be useful if
+    these types of bugs crop up in the future.)
+    """
     print '+++ ALL CONNECTIONS +++'
     for connection in allInstancesOf(DiagnosticConnectionWrapper):
         print connection.label, connection.state
@@ -130,7 +139,7 @@
             pass
         currentTestID = testCase.id()
         cp = ConnectionPool(self.sharedService.produceConnection)
-        quota = deriveQuota(currentTestID)
+        quota = deriveQuota(testCase)
         store = CommonDataStore(
             cp.connection, notifierFactory, attachmentRoot, quota=quota
         )
@@ -186,7 +195,7 @@
 
 
 
-def deriveQuota(testID):
+def deriveQuota(testCase):
     """
     Derive a distinctive quota number for a specific test, based on its ID.
     This generates a quota which is small enough that tests may trivially exceed
@@ -198,19 +207,41 @@
     state; this allows us to have the test and the infrastructure agree on a
     number.
 
-    @param testID: The identifier for a test, as returned by L{TestCase.id}.
+    @param testCase: The identifier for a test, as returned by L{TestCase.id}.
 
     @type testID: C{str}
     """
-    h = md5(testID)
-    seed = int(h.hexdigest(), 16)
-    r = Random(seed)
-    baseline = 2000
-    fuzz = r.randint(1, 1000)
-    return baseline + fuzz
+    testID = testCase.id()
+    testMethodName = testID.split(".")[-1]
+    method = getattr(testCase, testMethodName)
+    notSet = object()
+    specialQuota = getattr(method, _SPECIAL_QUOTA, notSet)
+    if specialQuota is notSet:
+        h = md5(testID)
+        seed = int(h.hexdigest(), 16)
+        r = Random(seed)
+        baseline = 2000
+        fuzz = r.randint(1, 1000)
+        return baseline + fuzz
+    else:
+        return specialQuota
 
 
 
+_SPECIAL_QUOTA = "__special_quota__"
+
+def withSpecialQuota(quotaValue):
+    """
+    Test method decorator that will cause L{deriveQuota} to return a different
+    value for test cases that run that test method.
+    """
+    def thunk(function):
+        setattr(function, _SPECIAL_QUOTA, quotaValue)
+        return function
+    return thunk
+
+
+
 @inlineCallbacks
 def populateCalendarsFrom(requirements, store):
     """
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110707/a8b1f0be/attachment-0001.html>


More information about the calendarserver-changes mailing list