[CalendarServer-changes] [6699] CalendarServer/trunk/contrib/performance/loadtest

source_changes at macosforge.org source_changes at macosforge.org
Fri Dec 17 10:03:03 PST 2010


Revision: 6699
          http://trac.macosforge.org/projects/calendarserver/changeset/6699
Author:   exarkun at twistedmatrix.com
Date:     2010-12-17 10:02:58 -0800 (Fri, 17 Dec 2010)
Log Message:
-----------
Notice ctag changes and download new/changed events

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/loadtest/ical.py
    CalendarServer/trunk/contrib/performance/loadtest/population.py

Added Paths:
-----------
    CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_propfind.request
    CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_report.request

Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/ical.py	2010-12-17 17:23:04 UTC (rev 6698)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py	2010-12-17 18:02:58 UTC (rev 6699)
@@ -43,6 +43,12 @@
 SUPPORTED_REPORT_SET = '{DAV:}supported-report-set'
 
 
+class Event(object):
+    def __init__(self, url, etag):
+        self.url = url
+        self.etag = etag
+
+
 class Calendar(object):
     def __init__(self, resourceType, name, url, ctag):
         self.resourceType = resourceType
@@ -67,13 +73,27 @@
     _STARTUP_NOTIFICATION_PROPFIND = loadRequestBody('sl_startup_notification_propfind')
     _STARTUP_PRINCIPAL_REPORT = loadRequestBody('sl_startup_principal_report')
 
+    _CALENDAR_PROPFIND = loadRequestBody('sl_calendar_propfind')
+    _CALENDAR_REPORT = loadRequestBody('sl_calendar_report')
+
+
     def __init__(self, reactor, host, port, user, auth):
         self.reactor = reactor
         self.agent = AuthHandlerAgent(Agent(self.reactor), auth)
         self.root = 'http://%s:%d/' % (host, port)
         self.user = user
 
+        # Keep track of the calendars on this account, keys are
+        # Calendar URIs, values are Calendar instances.
+        self._calendars = {}
 
+        # Keep track of the events on this account, keys are event
+        # URIs (which are unambiguous across different calendars
+        # because they start with the uri of the calendar they are
+        # part of), values are Event instances.
+        self._events = {}
+
+
     def _request(self, method, url, headers, body):
         # XXX Do return code checking here.
         headers.setRawHeaders('User-Agent', [self.USER_AGENT])
@@ -90,9 +110,9 @@
         return d
 
 
-    def _parsePROPFINDResponse(self, response):
+    def _parseMultiStatus(self, response):
         """
-        Construct a principal from the body a response to a
+        Parse a <multistatus>
         I{PROPFIND} request for the principal URL.
 
         @type response: C{str}
@@ -115,7 +135,7 @@
         Parse 
         """
         calendars = []
-        principals = self._parsePROPFINDResponse(response)
+        principals = self._parseMultiStatus(response)
 
         # XXX Here, it would be really great to somehow use
         # CalDAVClientLibrary.client.principal.CalDAVPrincipal.listCalendars
@@ -149,7 +169,7 @@
                     'depth': ['0']}),
             StringProducer(self._STARTUP_PRINCIPAL_PROPFIND))
         d.addCallback(readBody)
-        d.addCallback(self._parsePROPFINDResponse)
+        d.addCallback(self._parseMultiStatus)
         d.addCallback(getitem, principalURL)
         return d
 
@@ -182,13 +202,65 @@
             StringProducer(self._STARTUP_CALENDARHOME_PROPFIND))
         d.addCallback(readBody)
         d.addCallback(self._extractCalendars)
-        def report(result):
-            # pprint(result)
-            pass
-        d.addCallback(report)
         return d
 
 
+    @inlineCallbacks
+    def _updateCalendar(self, calendar):
+        url = calendar.url
+        if url.startswith('/'):
+            url = url[1:]
+
+        # First do a PROPFIND on the calendar to learn about events it
+        # might have.
+        response = yield self._request(
+            'PROPFIND',
+            self.root + url,
+            Headers({'content-type': ['text/xml'], 'depth': ['1']}),
+            StringProducer(self._CALENDAR_PROPFIND))
+
+        # XXX Check the response status code
+
+        body = yield readBody(response)
+
+        result = self._parseMultiStatus(body)
+        for responseHref in result:
+            if responseHref == calendar.url:
+                continue
+
+            etag = result[responseHref].getTextProperties()[davxml.getetag]
+            if responseHref not in self._events:
+                self._events[responseHref] = Event(responseHref, None)
+
+            if self._events[responseHref].etag != etag:
+                response = yield self._updateEvent(url, responseHref)
+                body = yield readBody(response)
+                result = self._parseMultiStatus(body)[responseHref]
+                etag = result.getTextProperties()[davxml.getetag]
+                self._events[responseHref].etag = etag
+
+                
+    def _updateEvent(self, calendar, event):
+        # Next do a REPORT on each event that might have information
+        # we don't know about.
+        return self._request(
+            'REPORT',
+            self.root + calendar,
+            Headers({'content-type': ['text/xml']}),
+            StringProducer(self._CALENDAR_REPORT % {'href': event}))
+
+
+    def _checkCalendarsForEvents(self, calendarHomeSet):
+        d = self._calendarHomePropfind(calendarHomeSet)
+        def cbCalendars(calendars):
+            for cal in calendars:
+                if self._calendars.setdefault(cal.url, cal).ctag != cal.ctag or True:
+                    self._updateCalendar(cal)
+                    break
+        d.addCallback(cbCalendars)
+        return d
+
+
     def _notificationPropfind(self, notificationURL):
         if notificationURL.startswith('/'):
             notificationURL = notificationURL[1:]
@@ -229,16 +301,14 @@
         (yield self._principalsReport(principalCollection))
 
         # Whatever
-        calendarHome = hrefs[caldavxml.calendar_home_set].toString()
-        (yield self._calendarHomePropfind(calendarHome))
 
         # Learn stuff I guess
-        notificationURL = hrefs[csxml.notification_URL].toString()
-        (yield self._notificationPropfind(notificationURL))
+        # notificationURL = hrefs[csxml.notification_URL].toString()
+        # (yield self._notificationPropfind(notificationURL))
 
         # More too
-        principalURL = hrefs[davxml.principal_URL].toString()
-        (yield self._principalReport(principalURL))
+        # principalURL = hrefs[davxml.principal_URL].toString()
+        # (yield self._principalReport(principalURL))
 
         returnValue(principal)
 
@@ -254,7 +324,7 @@
         # Poll Calendar Home (and notifications?) every 15 (or
         # whatever) minutes
         pollCalendarHome = LoopingCall(
-            self._calendarHomePropfind, 
+            self._checkCalendarsForEvents, 
             hrefs[caldavxml.calendar_home_set].toString())
         pollCalendarHome.start(self.CALENDAR_HOME_POLL_INTERVAL)
 

Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/population.py	2010-12-17 17:23:04 UTC (rev 6698)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py	2010-12-17 18:02:58 UTC (rev 6699)
@@ -136,12 +136,11 @@
     simulator = CalendarClientSimulator(
         populator, parameters, reactor, '127.0.0.1', 8008)
 
-    # Uh yea let's see
+    # Add some clients.
     call = LoopingCall(simulator.add, 1)
-    call.start(1)
-    reactor.callLater(60, call.stop)
+    call.start(3)
+    reactor.callLater(3 * 90, call.stop)
 
-
     reactor.run()
 
 if __name__ == '__main__':

Added: CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_propfind.request
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_propfind.request	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_propfind.request	2010-12-17 18:02:58 UTC (rev 6699)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<x0:propfind xmlns:x0="DAV:" xmlns:x1="http://calendarserver.org/ns/">
+ <x0:prop>
+  <x0:getetag/>
+  <x0:resourcetype/>
+  <x1:notificationtype/>
+ </x0:prop>
+</x0:propfind>

Added: CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_report.request
===================================================================
--- CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_report.request	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/loadtest/request-data/sl_calendar_report.request	2010-12-17 18:02:58 UTC (rev 6699)
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<x0:calendar-multiget xmlns:x0="urn:ietf:params:xml:ns:caldav" xmlns:x1="DAV:"><x1:prop><x1:getetag/><x0:calendar-data/><x0:schedule-tag/></x1:prop><x1:href>%(href)s</x1:href></x0:calendar-multiget>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101217/ff987134/attachment-0001.html>


More information about the calendarserver-changes mailing list