Revision: 9338 http://trac.macosforge.org/projects/calendarserver/changeset/9338 Author: cdaboo@apple.com Date: 2012-06-07 15:51:15 -0700 (Thu, 07 Jun 2012) Log Message: ----------- Minimise the numbers of times we serialize a calendar object to improve performance. Modified Paths: -------------- CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py CalendarServer/trunk/twistedcaldav/method/put_common.py CalendarServer/trunk/twistedcaldav/scheduling/caldav.py CalendarServer/trunk/twistedcaldav/scheduling/implicit.py CalendarServer/trunk/twistedcaldav/scheduling/processing.py CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py CalendarServer/trunk/twistedcaldav/storebridge.py Modified: CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py =================================================================== --- CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/method/put_addressbook_common.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -91,6 +91,7 @@ destination=None, destination_uri=None, destinationparent=None, destinationadbk=True, vcard=None, vcarddata=None, indexdestination = True, + returnData=False, ): """ Function that does common PUT/COPY/MOVE behavior. @@ -108,6 +109,7 @@ @param sourceparent: the L{CalDAVResource} for the source resource's parent collection, or None if source is None. @param destinationparent: the L{CalDAVResource} for the destination resource's parent collection. @param deletesource: True if the source resource is to be deleted on successful completion, False otherwise. + @param returnData: True if the caller wants the actual data written to the store returned """ # Check that all arguments are valid @@ -144,6 +146,7 @@ self.vcarddata = vcarddata self.deletesource = deletesource self.indexdestination = indexdestination + self.returnData = returnData self.access = None Modified: CalendarServer/trunk/twistedcaldav/method/put_common.py =================================================================== --- CalendarServer/trunk/twistedcaldav/method/put_common.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/method/put_common.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -132,6 +132,7 @@ allowImplicitSchedule=True, internal_request=False, processing_organizer=None, + returnData=False, ): """ Function that does common PUT/COPY/MOVE behavior. @@ -153,6 +154,7 @@ @param allowImplicitSchedule: True if implicit scheduling should be attempted, False otherwise. @param internal_request: True if this request originates internally and needs to bypass scheduling authorization checks. @param processing_organizer: True if implicit processing for an organizer, False if for an attendee, None if not implicit processing. + @param returnData: True if the caller wants the actual data written to the store returned """ # Check that all arguments are valid @@ -193,6 +195,7 @@ self.allowImplicitSchedule = allowImplicitSchedule self.internal_request = internal_request self.processing_organizer = processing_organizer + self.returnData = returnData self.access = None self.hasPrivateComments = False @@ -1024,7 +1027,8 @@ def doStore(self, implicit): # Stash the current calendar data as we may need to return it - self.returndata = str(self.calendar) if self.calendardata is None else self.calendardata + if self.returnData: + self.storeddata = str(self.calendar) if self.calendardata is None else self.calendardata # Always do the per-user data merge right before we store yield self.mergePerUserData() Modified: CalendarServer/trunk/twistedcaldav/scheduling/caldav.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/caldav.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/scheduling/caldav.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -14,13 +14,8 @@ # limitations under the License. ## -import time +import uuid -try: - from hashlib import md5 -except ImportError: - from md5 import new as md5 - from twext.python.log import Logger from twext.web2.dav.http import ErrorResponse @@ -143,7 +138,7 @@ @inlineCallbacks def generateResponse(self, recipient, responses): # Hash the iCalendar data for use as the last path element of the URI path - name = md5(self.scheduler.calendardata + str(time.time()) + recipient.inboxURL).hexdigest() + ".ics" + name = str(uuid.uuid4()) + ".ics" # Get a resource for the new item childURL = joinURL(recipient.inboxURL, name) Modified: CalendarServer/trunk/twistedcaldav/scheduling/implicit.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -877,7 +877,7 @@ # Do the PUT processing log.info("Implicit CANCEL - organizer: '%s' to attendee: '%s', UID: '%s', RIDs: '%s'" % (self.organizer, attendee, self.uid, rids)) - response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, self.internal_request)) + response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True)) self.handleSchedulingResponse(response, True) count += 1 @@ -919,7 +919,7 @@ # Do the PUT processing log.info("Implicit REQUEST - organizer: '%s' to attendee: '%s', UID: '%s'" % (self.organizer, attendee, self.uid,)) - response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, self.internal_request)) + response = (yield scheduler.doSchedulingViaPUT(self.originator, (attendee,), itipmsg, internal_request=True)) self.handleSchedulingResponse(response, True) count += 1 @@ -1186,6 +1186,6 @@ self.handleSchedulingResponse(response, False) log.info("Implicit %s - attendee: '%s' to organizer: '%s', UID: '%s'" % (action, self.attendee, self.organizer, self.uid,)) - d = scheduler.doSchedulingViaPUT(self.originator, (self.organizer,), itipmsg, self.internal_request) + d = scheduler.doSchedulingViaPUT(self.originator, (self.organizer,), itipmsg, internal_request=True) d.addCallback(_gotResponse) return d Modified: CalendarServer/trunk/twistedcaldav/scheduling/processing.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/scheduling/processing.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -14,9 +14,6 @@ # limitations under the License. ## -import time -from hashlib import md5 - from twisted.python.log import err as log_traceback from twext.python.log import Logger @@ -39,6 +36,7 @@ from pycalendar.duration import PyCalendarDuration from pycalendar.datetime import PyCalendarDateTime from pycalendar.timezone import PyCalendarTimezone +import uuid """ CalDAV implicit processing. @@ -470,7 +468,7 @@ log.debug("ImplicitProcessing - originator '%s' to recipient '%s' processing METHOD:REQUEST, UID: '%s' - new processed" % (self.originator.cuaddr, self.recipient.cuaddr, self.uid)) new_calendar = iTipProcessing.processNewRequest(self.message, self.recipient.cuaddr) - name = md5(str(new_calendar) + str(time.time()) + default.url()).hexdigest() + ".ics" + name = str(uuid.uuid4()) + ".ics" # Handle auto-reply behavior if self.recipient.principal.canAutoSchedule(): @@ -895,7 +893,7 @@ # Create a new name if one was not provided if name is None: - name = md5(str(calendar) + str(time.time()) + collURL).hexdigest() + ".ics" + name = str(uuid.uuid4()) + ".ics" # Get a resource for the new item newchildURL = joinURL(collURL, name) Modified: CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py =================================================================== --- CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -160,7 +160,7 @@ if not hasattr(self.request, "extendedLogItems"): self.request.extendedLogItems = {} self.request.extendedLogItems["recipients"] = len(self.recipients) - self.request.extendedLogItems["cl"] = str(len(self.calendardata)) + self.request.extendedLogItems["cl"] = str(self.calendar) # Do some extra authorization checks self.checkAuthorization() @@ -199,7 +199,6 @@ self.originator = originator self.recipients = recipients self.calendar = calendar - self.calendardata = str(self.calendar) self.internal_request = internal_request # Do some extra authorization checks @@ -340,7 +339,6 @@ self.calendar = (yield Component.fromIStream(self.request.stream)) self.preProcessCalendarData() - self.calendardata = str(self.calendar) except: # FIXME: Bare except log.err("Error while handling %s: %s" % (self.method, Failure(),)) @@ -376,44 +374,49 @@ raise NotImplementedError def checkCalendarData(self): - # Must be a valid calendar - try: - self.calendar.validCalendarData() - except ValueError, e: - log.err("%s request calendar component is not valid:%s %s" % (self.method, e, self.calendar,)) - raise HTTPError(ErrorResponse( - responsecode.FORBIDDEN, - (caldav_namespace, "valid-calendar-data"), - description="Calendar component is not valid" - )) + + # Skip all the valid data checks for an internal request as we are going to assume all the internal + # request data has been generated properly. - # Must have a METHOD - if not self.calendar.isValidMethod(): - log.err("%s request must have valid METHOD property in calendar component: %s" % (self.method, self.calendar,)) - raise HTTPError(ErrorResponse( - responsecode.FORBIDDEN, - (caldav_namespace, "valid-calendar-data"), - description="Must have valid METHOD property" - )) + if not self.internal_request: + # Must be a valid calendar + try: + self.calendar.validCalendarData() + except ValueError, e: + log.err("%s request calendar component is not valid:%s %s" % (self.method, e, self.calendar,)) + raise HTTPError(ErrorResponse( + responsecode.FORBIDDEN, + (caldav_namespace, "valid-calendar-data"), + description="Calendar component is not valid" + )) - # Verify iTIP behavior - if not self.calendar.isValidITIP(): - log.err("%s request must have a calendar component that satisfies iTIP requirements: %s" % (self.method, self.calendar,)) - raise HTTPError(ErrorResponse( - responsecode.FORBIDDEN, - (caldav_namespace, "valid-calendar-data"), - description="Must have a calendar component that satisfies iTIP requirements" - )) - - # X-CALENDARSERVER-ACCESS is not allowed in Outbox POSTs - if self.calendar.hasProperty(Component.ACCESS_PROPERTY): - log.err("X-CALENDARSERVER-ACCESS not allowed in a calendar component %s request: %s" % (self.method, self.calendar,)) - raise HTTPError(ErrorResponse( - responsecode.FORBIDDEN, - (calendarserver_namespace, "no-access-restrictions"), - "Private events cannot be scheduled", - )) + # Must have a METHOD + if not self.calendar.isValidMethod(): + log.err("%s request must have valid METHOD property in calendar component: %s" % (self.method, self.calendar,)) + raise HTTPError(ErrorResponse( + responsecode.FORBIDDEN, + (caldav_namespace, "valid-calendar-data"), + description="Must have valid METHOD property" + )) + + # Verify iTIP behavior + if not self.calendar.isValidITIP(): + log.err("%s request must have a calendar component that satisfies iTIP requirements: %s" % (self.method, self.calendar,)) + raise HTTPError(ErrorResponse( + responsecode.FORBIDDEN, + (caldav_namespace, "valid-calendar-data"), + description="Must have a calendar component that satisfies iTIP requirements" + )) + # X-CALENDARSERVER-ACCESS is not allowed in Outbox POSTs + if self.calendar.hasProperty(Component.ACCESS_PROPERTY): + log.err("X-CALENDARSERVER-ACCESS not allowed in a calendar component %s request: %s" % (self.method, self.calendar,)) + raise HTTPError(ErrorResponse( + responsecode.FORBIDDEN, + (calendarserver_namespace, "no-access-restrictions"), + "Private events cannot be scheduled", + )) + # Determine iTIP method mode if self.calendar.propertyValue("METHOD") in ("PUBLISH", "REQUEST", "ADD", "CANCEL", "DECLINECOUNTER"): self.isiTIPRequest = True @@ -426,7 +429,7 @@ # Must have only one if len(attendees) != 1: - log.err("Wrong number of ATTENDEEs in calendar data: %s" % (self.calendardata,)) + log.err("Wrong number of ATTENDEEs in calendar data: %s" % (str(self.calendar),)) raise HTTPError(ErrorResponse( responsecode.FORBIDDEN, (caldav_namespace, "attendee-allowed"), @@ -512,7 +515,7 @@ str("".join([" %s\n" % (recipient,) for recipient in self.recipients])), str(self.request.serverInstance), str(self.method), - self.calendardata, + str(self.calendar), ) ) Modified: CalendarServer/trunk/twistedcaldav/storebridge.py =================================================================== --- CalendarServer/trunk/twistedcaldav/storebridge.py 2012-06-07 20:41:05 UTC (rev 9337) +++ CalendarServer/trunk/twistedcaldav/storebridge.py 2012-06-07 22:51:15 UTC (rev 9338) @@ -583,7 +583,7 @@ # Get a resource for the new item newchildURL = joinURL(request.path, name) newchild = (yield request.locateResource(newchildURL)) - dataChanged = (yield self.storeResourceData(request, newchild, newchildURL, component)) + dataChanged = (yield self.storeResourceData(request, newchild, newchildURL, component, returnData=return_changed)) except HTTPError, e: # Extract the pre-condition @@ -1124,7 +1124,7 @@ return caldavxml.CalendarData @inlineCallbacks - def storeResourceData(self, request, newchild, newchildURL, component, text=None): + def storeResourceData(self, request, newchild, newchildURL, component, text=None, returnData=False): storer = StoreCalendarObjectResource( request = request, destination = newchild, @@ -1133,10 +1133,11 @@ destinationparent = self, calendar = component, calendardata = text, + returnData = returnData, ) yield storer.run() - returnValue(storer.returndata if hasattr(storer, "returndata") else None) + returnValue(storer.storeddata if hasattr(storer, "storeddata") else None) @inlineCallbacks @@ -2057,7 +2058,7 @@ return carddavxml.AddressData @inlineCallbacks - def storeResourceData(self, request, newchild, newchildURL, component, text=None): + def storeResourceData(self, request, newchild, newchildURL, component, text=None, returnData=False): storer = StoreAddressObjectResource( request = request, sourceadbk = False, @@ -2067,6 +2068,7 @@ destinationparent = self, vcard = component, vcarddata = text, + returnData = returnData, ) yield storer.run()
participants (1)
-
source_changes@macosforge.org