[CalendarServer-changes] [8972] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Apr 3 14:07:40 PDT 2012
Revision: 8972
http://trac.macosforge.org/projects/calendarserver/changeset/8972
Author: cdaboo at apple.com
Date: 2012-04-03 14:07:40 -0700 (Tue, 03 Apr 2012)
Log Message:
-----------
Do on-demand time range expansion in a separate transaction if possible.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/dateops.py
CalendarServer/trunk/txdav/caldav/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql.py
CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
Modified: CalendarServer/trunk/twistedcaldav/dateops.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/dateops.py 2012-04-03 18:15:08 UTC (rev 8971)
+++ CalendarServer/trunk/twistedcaldav/dateops.py 2012-04-03 21:07:40 UTC (rev 8972)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2012 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -262,6 +262,18 @@
dt = datetime.datetime.strptime(ts[:19], "%Y-%m-%d %H:%M:%S")
return PyCalendarDateTime(year=dt.year, month=dt.month, day=dt.day, hours=dt.hour, minutes=dt.minute, seconds=dt.second)
+def parseSQLDateToPyCalendar(ts):
+ """
+ Parse an SQL formated date into a PyCalendarDateTime
+ @param ts: the SQL date
+ @type ts: C{str}
+
+ @return: L{PyCalendarDateTime} result
+ """
+
+ dt = datetime.datetime.strptime(ts[:10], "%Y-%m-%d")
+ return PyCalendarDateTime(year=dt.year, month=dt.month, day=dt.day)
+
def datetimeMktime(dt):
assert isinstance(dt, datetime.date)
Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-04-03 18:15:08 UTC (rev 8971)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py 2012-04-03 21:07:40 UTC (rev 8972)
@@ -39,7 +39,7 @@
from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque
from twistedcaldav.config import config
from twistedcaldav.dateops import normalizeForIndex, datetimeMktime,\
- parseSQLTimestamp, pyCalendarTodatetime
+ parseSQLTimestamp, pyCalendarTodatetime, parseSQLDateToPyCalendar
from twistedcaldav.ical import Component, InvalidICalendarDataError
from twistedcaldav.instance import InvalidOverriddenInstanceError
from twistedcaldav.memcacher import Memcacher
@@ -1007,7 +1007,31 @@
returnValue(component)
+ @classproperty
+ def _recurrenceMaxByIDQuery(cls): #@NoSelf
+ """
+ DAL query to load RECURRANCE_MAX via an object's resource ID.
+ """
+ co = schema.CALENDAR_OBJECT
+ return Select([co.RECURRANCE_MAX], From=co,
+ Where=co.RESOURCE_ID == Parameter("resourceID"))
+
+
@inlineCallbacks
+ def recurrenceMax(self):
+ """
+ Get the RECURRANCE_MAX value.
+
+ @return: L{PyCalendarDateTime} result
+ """
+ rMax = (
+ yield self._recurrenceMaxByIDQuery.on(self._txn,
+ resourceID=self._resourceID)
+ )[0][0]
+ returnValue(parseSQLDateToPyCalendar(rMax))
+
+
+ @inlineCallbacks
def organizer(self):
returnValue((yield self.component()).getOrganizer())
Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py 2012-04-03 18:15:08 UTC (rev 8971)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py 2012-04-03 21:07:40 UTC (rev 8972)
@@ -2694,9 +2694,10 @@
self._created = None
self._modified = None
self._objectText = None
+
+ self._overrideTxn = None
-
@classproperty
def _allColumnsWithParent(cls): #@NoSelf
obj = cls._objectSchema
@@ -2902,11 +2903,25 @@
@property
def _txn(self):
- return self._parentCollection._txn
+ return self._overrideTxn if self._overrideTxn else self._parentCollection._txn
def transaction(self):
- return self._parentCollection._txn
+ return self._overrideTxn if self._overrideTxn else self._parentCollection._txn
+ def useTxn(self, newTxn):
+ self._overrideTxn = newTxn
+
+ @classmethod
+ def _selectForUpdateQuery(cls, nowait): #@NoSelf
+ """
+ DAL statement to lock a L{CommonObjectResource} by its resource ID.
+ """
+ return Select(From=cls._objectSchema, ForUpdate=True, NoWait=nowait, Where=cls._objectSchema.RESOURCE_ID == Parameter("resourceID"))
+
+ @inlineCallbacks
+ def lock(self, nowait=False):
+ yield self._selectForUpdateQuery(nowait).on(self._txn, NoSuchObjectResourceError, resourceID=self._resourceID)
+
def setComponent(self, component, inserting=False):
raise NotImplementedError
Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2012-04-03 18:15:08 UTC (rev 8971)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py 2012-04-03 21:07:40 UTC (rev 8972)
@@ -41,7 +41,7 @@
from twistedcaldav.sharing import Invite
from txdav.common.icommondatastore import (
- IndexedSearchException, ReservationError)
+ IndexedSearchException, ReservationError, NoSuchObjectResourceError)
from twext.enterprise.dal.syntax import Update, SavepointAction
from twext.enterprise.dal.syntax import Insert
@@ -1156,11 +1156,40 @@
with a longer expansion.
"""
obj = yield self.calendar.calendarObjectWithName(name)
- yield obj.updateDatabase(
- (yield obj.component()), expand_until=expand_until, reCreate=True
- )
+
+ # Use a new transaction to do this update quickly without locking the row for too long. However, the original
+ # transaction may have the row locked, so use NOWAIT and if that fails, fakll back to using the original txn.
+
+ newTxn = obj.transaction().store().newTransaction()
+ obj.useTxn(newTxn)
+ try:
+ yield obj.lock(nowait=True)
+ except NoSuchObjectResourceError:
+ yield newTxn.commit()
+ obj.useTxn(None)
+ returnValue(None)
+ except:
+ yield newTxn.abort()
+ obj.useTxn(None)
+ newTxn = None
+ # Now do the re-expand using the appropriate transaction
+ try:
+ if newTxn is None:
+ rmax = None
+ else:
+ rmax = (yield obj.recurrenceMax())
+ if rmax is None or rmax < expand_until:
+ yield obj.updateDatabase(
+ (yield obj.component()), expand_until=expand_until, reCreate=True
+ )
+ finally:
+ if newTxn is not None:
+ yield newTxn.commit()
+ obj.useTxn(None)
+
+
@inlineCallbacks
def testAndUpdateIndex(self, minDate):
# Find out if the index is expanded far enough
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120403/8a85c936/attachment.html>
More information about the calendarserver-changes
mailing list