Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Trigger an event split, if allowed, when a txn timeout occurs during …

…setComponent().

git-svn-id: https://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk@12262 e27351fd-9f3e-4f54-a53b-843176b1656c
  • Loading branch information
cyrusdaboo committed Jan 7, 2014
1 parent abb35bf commit 67041864b3217857c216a99c2eaaad80076e5b2c
@@ -46,6 +46,7 @@

from twisted.internet.defer import inlineCallbacks, returnValue, succeed
from twisted.python import hashlib
from twisted.python.failure import Failure

from twistedcaldav import caldavxml, customxml, ical
from twistedcaldav.config import config
@@ -2331,6 +2332,12 @@ def doImplicitScheduling(self, component, inserting, internal_state, split_detai
internal_request=is_internal,
))

# Set an attribute on this object to indicate that it is valid to check for an event split. We need to do this here so that if a timeout
# occurs whilst doing implicit processing (most likely because the event is too big) we are able to subsequently detect that it is OK
# to split and then try that.
if internal_state not in (ComponentUpdateState.SPLIT_OWNER, ComponentUpdateState.SPLIT_ATTENDEE,) and scheduler.state == "organizer":
self.okToSplit = True

if do_implicit_action and not is_internal:

# Cannot do implicit in sharee's shared calendar
@@ -2445,6 +2452,7 @@ def _lockUID(self, component, inserting, internal_state):
raise UIDExistsElsewhereError("UID already exists in different calendar: %s." % (elsewhere.calendar().name(),))


@inlineCallbacks
def setComponent(self, component, inserting=False, smart_merge=False):
"""
Public api for storing a component. This will do full data validation checks on the specified component.
@@ -2457,7 +2465,17 @@ def setComponent(self, component, inserting=False, smart_merge=False):
component = self._componentClass.fromString(component)
except InvalidICalendarDataError as e:
raise InvalidComponentForStoreError(str(e))
return self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL, smart_merge)
try:
yield self._setComponentInternal(component, inserting, ComponentUpdateState.NORMAL, smart_merge)
except Exception as e:
ex = Failure()

# If the failure is due to a txn timeout and we have the special attribute indicating it is OK to
# attempt a split, then try splitting only when doing an update.
if self._txn.timedout and hasattr(self, "okToSplit") and not inserting:
yield self.timeoutSplit()

ex.raiseException()


@inlineCallbacks
@@ -3674,16 +3692,19 @@ def contentType(self):


@inlineCallbacks
def checkSplit(self):
def checkSplit(self, txn=None):
"""
Determine if the calendar data needs to be split, and enqueue a split work item if needed.
Determine if the calendar data needs to be split, and enqueue a split work item if needed. Note we may
need to do this in some other transaction.
"""

if config.Scheduling.Options.Splitting.Enabled:
will = (yield self.willSplit())
if will:
notBefore = datetime.datetime.utcnow() + datetime.timedelta(seconds=config.Scheduling.Options.Splitting.Delay)
work = (yield self._txn.enqueue(CalendarObject.CalendarObjectSplitterWork, resourceID=self._resourceID, notBefore=notBefore))
if txn is None:
txn = self._txn
work = (yield txn.enqueue(CalendarObject.CalendarObjectSplitterWork, resourceID=self._resourceID, notBefore=notBefore))

# _workItems is used during unit testing only, to track the created work
if not hasattr(self, "_workItems"):
@@ -3703,6 +3724,21 @@ def willSplit(self):
returnValue(will_split)


@inlineCallbacks
def timeoutSplit(self):
"""
A txn timeout occurred. Check to see if it is possible to split this event and if so schedule that to occur
as the timeout might be the result of the resource being too large and doing a split here will allow a
subsequent operation to succeed since the split can reduce the size.
"""

# Can only do if cached data exists
if self._cachedComponent:
txn = self.transaction().store().newTransaction("Timeout checkSplit")
yield self.checkSplit(txn=txn)
yield txn.commit()


@inlineCallbacks
def split(self, onlyThis=False, rid=None, olderUID=None):
"""

0 comments on commit 6704186

Please sign in to comment.
You can’t perform that action at this time.