[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