[CalendarServer-changes] [9166] CalendarServer/trunk/txdav
source_changes at macosforge.org
source_changes at macosforge.org
Fri Apr 20 14:54:48 PDT 2012
Revision: 9166
http://trac.macosforge.org/projects/calendarserver/changeset/9166
Author: sagen at apple.com
Date: 2012-04-20 14:54:48 -0700 (Fri, 20 Apr 2012)
Log Message:
-----------
Cache home-child meta data query, and updates postCommit( ) to take an "immediately" keyword arg indicating we want the operation to happen prior to the response being returned to the client.
Modified Paths:
--------------
CalendarServer/trunk/txdav/base/datastore/file.py
CalendarServer/trunk/txdav/base/datastore/util.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/idav.py
Modified: CalendarServer/trunk/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/base/datastore/file.py 2012-04-20 20:47:07 UTC (rev 9165)
+++ CalendarServer/trunk/txdav/base/datastore/file.py 2012-04-20 21:54:48 UTC (rev 9166)
@@ -187,11 +187,11 @@
self.log_error("Cannot undo DataStoreTransaction")
raise
- for operation in self._postCommitOperations:
+ for (operation, ignored) in self._postCommitOperations:
operation()
- def postCommit(self, operation):
- self._postCommitOperations.append(operation)
+ def postCommit(self, operation, immediately=False):
+ self._postCommitOperations.append((operation, immediately))
def postAbort(self, operation):
self._postAbortOperations.append(operation)
Modified: CalendarServer/trunk/txdav/base/datastore/util.py
===================================================================
--- CalendarServer/trunk/txdav/base/datastore/util.py 2012-04-20 20:47:07 UTC (rev 9165)
+++ CalendarServer/trunk/txdav/base/datastore/util.py 2012-04-20 21:54:48 UTC (rev 9166)
@@ -59,43 +59,34 @@
self.cacheExpireSeconds = cacheExpireSeconds
def set(self, key, value):
- super(QueryCacher, self).set(key, value, expireTime=self.cacheExpireSeconds)
+ return super(QueryCacher, self).set(key, value, expireTime=self.cacheExpireSeconds)
- # Home child objects by name
+ def delete(self, key):
+ return super(QueryCacher, self).delete(key)
- def keyForObjectWithName(self, homeResourceID, name):
- return "objectWithName:%s:%s" % (homeResourceID, name)
- def getObjectWithName(self, homeResourceID, name):
- key = self.keyForObjectWithName(homeResourceID, name)
- return self.get(key)
+ def setAfterCommit(self, transaction, key, value):
+ transaction.postCommit(lambda: self.set(key, value), immediately=True)
- def setObjectWithName(self, transaction, homeResourceID, name, value):
- key = self.keyForObjectWithName(homeResourceID, name)
- transaction.postCommit(lambda:self.set(key, value))
+ def invalidateAfterCommit(self, transaction, key):
+ # Invalidate now (so that operations within this transaction see it)
+ # and *also* post-commit (because there could be a scheduled setAfterCommit
+ # for this key)
+ transaction.postCommit(lambda: self.delete(key), immediately=True)
+ return self.delete(key)
- def invalidateObjectWithName(self, transaction, homeResourceID, name):
- key = self.keyForObjectWithName(homeResourceID, name)
- # Invalidate immediately and post-commit in case a calendar was created and deleted
- # within the same transaction
- self.delete(key)
- transaction.postCommit(lambda:self.delete(key))
+ # Home child objects by name
+ def keyForObjectWithName(self, homeResourceID, name):
+ return "objectWithName:%s:%s" % (homeResourceID, name)
+
# Home metadata (Created/Modified)
def keyForHomeMetaData(self, homeResourceID):
return "homeMetaData:%s" % (homeResourceID)
- def getHomeMetaData(self, homeResourceID):
- key = self.keyForHomeMetaData(homeResourceID)
- return self.get(key)
+ # HomeChild metadata (Created/Modified (and SUPPORTED_COMPONENTS))
- def setHomeMetaData(self, transaction, homeResourceID, value):
- key = self.keyForHomeMetaData(homeResourceID)
- transaction.postCommit(lambda:self.set(key, value))
+ def keyForHomeChildMetaData(self, resourceID):
+ return "homeChildMetaData:%s" % (resourceID)
- def invalidateHomeMetaData(self, transaction, homeResourceID):
- key = self.keyForHomeMetaData(homeResourceID)
- # Invalidate immediately and post-commit
- self.delete(key)
- transaction.postCommit(lambda:self.delete(key))
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-04-20 20:47:07 UTC (rev 9165)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-04-20 21:54:48 UTC (rev 9166)
@@ -426,13 +426,14 @@
"""
return self._name == "inbox"
+
@inlineCallbacks
def setSupportedComponents(self, supported_components):
"""
Update the database column with the supported components. Technically this should only happen once
on collection creation, but for migration we may need to change after the fact - hence a separate api.
"""
-
+
cal = self._homeChildMetaDataSchema
yield Update(
{
@@ -442,6 +443,11 @@
).on(self._txn)
self._supportedComponents = supported_components
+ queryCacher = self._txn.store().queryCacher
+ if queryCacher is not None:
+ cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+
def getSupportedComponents(self):
return self._supportedComponents
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2012-04-20 20:47:07 UTC (rev 9165)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2012-04-20 21:54:48 UTC (rev 9166)
@@ -513,11 +513,11 @@
return self._apnSubscriptionsBySubscriberQuery.on(self, subscriberGUID=guid)
- def postCommit(self, operation):
+ def postCommit(self, operation, immediately=False):
"""
Run things after C{commit}.
"""
- self._postCommitOperations.append(operation)
+ self._postCommitOperations.append((operation, immediately))
def postAbort(self, operation):
@@ -659,10 +659,14 @@
"""
Commit the transaction and execute any post-commit hooks.
"""
+ @inlineCallbacks
def postCommit(ignored):
- for operation in self._postCommitOperations:
- operation()
- return ignored
+ for operation, immediately in self._postCommitOperations:
+ if immediately:
+ yield operation()
+ else:
+ operation()
+ returnValue(ignored)
if self._stats:
s = StringIO()
@@ -884,16 +888,24 @@
if result:
self._resourceID = result[0][0]
+
queryCacher = self._txn.store().queryCacher
if queryCacher:
- data = yield queryCacher.getHomeMetaData(self._resourceID)
- if data is not None:
- self._created, self._modified = data
- else:
- self._created, self._modified = (yield self._metaDataQuery.on(
- self._txn, resourceID=self._resourceID))[0]
- yield queryCacher.setHomeMetaData(self._txn, self._resourceID,
- (self._created, self._modified))
+ # Get cached copy
+ cacheKey = queryCacher.keyForHomeMetaData(self._resourceID)
+ data = yield queryCacher.get(cacheKey)
+ else:
+ data = None
+ if data is None:
+ # Don't have a cached copy
+ data = (yield self._metaDataQuery.on(
+ self._txn, resourceID=self._resourceID))[0]
+ if queryCacher:
+ # Cache the data
+ yield queryCacher.setAfterCommit(self._txn, cacheKey, data)
+
+ self._created, self._modified = data
+
yield self._loadPropertyStore()
returnValue(self)
else:
@@ -1452,7 +1464,8 @@
self._modified = (yield self._txn.subtransaction(_bumpModified, retries=0, failureOK=True))[0][0]
queryCacher = self._txn.store().queryCacher
if queryCacher is not None:
- yield queryCacher.invalidateHomeMetaData(self._txn, self._resourceID)
+ cacheKey = queryCacher.keyForHomeMetaData(self._resourceID)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
except AllRetriesFailed:
log.debug("CommonHome.bumpModified failed")
@@ -2045,9 +2058,12 @@
# Only caching non-shared objects so that we don't need to invalidate
# in sql_legacy
if owned and queryCacher:
- data = yield queryCacher.getObjectWithName(home._resourceID, name)
+ # Retrieve data from cache
+ cacheKey = queryCacher.keyForObjectWithName(home._resourceID, name)
+ data = yield queryCacher.get(cacheKey)
if data is None:
+ # No cached copy
if owned:
query = cls._resourceIDOwnedByHomeByName
else:
@@ -2055,11 +2071,12 @@
data = yield query.on(home._txn,
objectName=name, homeID=home._resourceID)
if owned and data and queryCacher:
- queryCacher.setObjectWithName(home._txn, home._resourceID,
- name, data)
+ # Cache the result
+ queryCacher.setAfterCommit(home._txn, cacheKey, data)
if not data:
returnValue(None)
+
resourceID = data[0][0]
child = cls(home, name, resourceID, owned)
yield child.initFromStore()
@@ -2193,9 +2210,22 @@
resource ID. We read in and cache all the extra metadata from the DB to
avoid having to do DB queries for those individually later.
"""
- dataRows = (
- yield self._metadataByIDQuery.on(self._txn,
- resourceID=self._resourceID))[0]
+ queryCacher = self._txn.store().queryCacher
+ if queryCacher:
+ # Retrieve from cache
+ cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
+ dataRows = yield queryCacher.get(cacheKey)
+ else:
+ dataRows = None
+ if dataRows is None:
+ # No cached copy
+ dataRows = (
+ yield self._metadataByIDQuery.on(self._txn,
+ resourceID=self._resourceID))[0]
+ if queryCacher:
+ # Cache the results
+ yield queryCacher.setAfterCommit(self._txn, cacheKey, dataRows)
+
for attr, value in zip(self.metadataAttributes(), dataRows):
setattr(self, attr, value)
yield self._loadPropertyStore()
@@ -2256,8 +2286,8 @@
queryCacher = self._home._txn.store().queryCacher
if queryCacher:
- queryCacher.invalidateObjectWithName(self._home._txn,
- self._home._resourceID, oldName)
+ cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, oldName)
+ yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
yield self._renameQuery.on(self._txn, name=name,
resourceID=self._resourceID,
@@ -2289,8 +2319,8 @@
queryCacher = self._home._txn.store().queryCacher
if queryCacher:
- queryCacher.invalidateObjectWithName(self._home._txn,
- self._home._resourceID, self._name)
+ cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, self._name)
+ yield queryCacher.invalidateAfterCommit(self._home._txn, cacheKey)
yield self._deletedSyncToken()
yield self._deleteQuery.on(self._txn, NoSuchHomeChildError,
@@ -2677,6 +2707,7 @@
Where=schema.RESOURCE_ID == Parameter("resourceID"),
Return=schema.MODIFIED)
+
@inlineCallbacks
def bumpModified(self):
"""
@@ -2695,6 +2726,11 @@
try:
self._modified = (yield self._txn.subtransaction(_bumpModified, retries=0, failureOK=True))[0][0]
+
+ queryCacher = self._txn.store().queryCacher
+ if queryCacher is not None:
+ cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
except AllRetriesFailed:
log.debug("CommonHomeChild.bumpModified failed")
Modified: CalendarServer/trunk/txdav/idav.py
===================================================================
--- CalendarServer/trunk/txdav/idav.py 2012-04-20 20:47:07 UTC (rev 9165)
+++ CalendarServer/trunk/txdav/idav.py 2012-04-20 21:54:48 UTC (rev 9166)
@@ -207,7 +207,7 @@
"""
- def postCommit(operation):
+ def postCommit(operation, immediately=False):
"""
Registers an operation to be executed after the transaction is
committed.
@@ -216,6 +216,8 @@
in the order which they were registered.
@param operation: a callable.
+ @param immediately: a boolean; True means finish this operation *before* the
+ commit( ) call completes, defaults to False.
"""
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120420/bc2f5213/attachment-0001.html>
More information about the calendarserver-changes
mailing list