[CalendarServer-changes] [6931] CalendarServer/trunk/contrib/performance

source_changes at macosforge.org source_changes at macosforge.org
Tue Feb 15 12:54:05 PST 2011


Revision: 6931
          http://trac.macosforge.org/projects/calendarserver/changeset/6931
Author:   exarkun at twistedmatrix.com
Date:     2011-02-15 12:54:05 -0800 (Tue, 15 Feb 2011)
Log Message:
-----------
Put benchmark implementations all beneath a single package

Modified Paths:
--------------
    CalendarServer/trunk/contrib/performance/benchmark.py

Added Paths:
-----------
    CalendarServer/trunk/contrib/performance/benchmarks/
    CalendarServer/trunk/contrib/performance/benchmarks/__init__.py
    CalendarServer/trunk/contrib/performance/benchmarks/event.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_add_attendee.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_change_date.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_change_summary.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_delete.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_delete_attendee.py
    CalendarServer/trunk/contrib/performance/benchmarks/event_move.py
    CalendarServer/trunk/contrib/performance/benchmarks/find_calendars.py
    CalendarServer/trunk/contrib/performance/benchmarks/find_events.py
    CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py

Removed Paths:
-------------
    CalendarServer/trunk/contrib/performance/event.py
    CalendarServer/trunk/contrib/performance/event_add_attendee.py
    CalendarServer/trunk/contrib/performance/event_change_date.py
    CalendarServer/trunk/contrib/performance/event_change_summary.py
    CalendarServer/trunk/contrib/performance/event_delete.py
    CalendarServer/trunk/contrib/performance/event_delete_attendee.py
    CalendarServer/trunk/contrib/performance/event_move.py
    CalendarServer/trunk/contrib/performance/find_calendars.py
    CalendarServer/trunk/contrib/performance/find_events.py
    CalendarServer/trunk/contrib/performance/vfreebusy.py

Modified: CalendarServer/trunk/contrib/performance/benchmark.py
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmark.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/benchmark.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -31,6 +31,7 @@
     Deferred, inlineCallbacks, gatherResults)
 from twisted.internet import reactor
 from twisted.python.log import msg
+from twisted.python.modules import getModule
 
 from stats import SQLDuration, Bytes
 
@@ -431,6 +432,14 @@
         pid.getContent() for pid in run.globChildren('*instance*')]
 
 
+_benchmarks = getModule("benchmarks")
+def resolveBenchmark(name):
+    for module in _benchmarks.iterModules():
+        if module.name == ".".join((_benchmarks.name, name)):
+            return module.load()
+    raise ValueError("Unknown benchmark: %r" % (name,))
+
+
 def main():
     from twisted.python.log import startLogging, err
 
@@ -458,7 +467,7 @@
     d = benchmark(
         options['host'], options['port'], pids, options['label'],
         options['parameters'],
-        [(arg, namedAny(arg).measure) for arg in options['benchmarks']])
+        [(arg, resolveBenchmark(arg).measure) for arg in options['benchmarks']])
     d.addErrback(err, "Failure at benchmark runner top-level")
     reactor.callWhenRunning(d.addCallback, lambda ign: reactor.stop())
     reactor.run()

Added: CalendarServer/trunk/contrib/performance/benchmarks/__init__.py
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/__init__.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/__init__.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,3 @@
+"""
+Package containing implementations of all of the microbenchmarks.
+"""

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event.py (from rev 6927, CalendarServer/trunk/contrib/performance/event.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,153 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Benchmark a server's handling of event creation.
+"""
+
+from itertools import count
+from urllib2 import HTTPDigestAuthHandler
+from uuid import uuid4
+from datetime import datetime, timedelta
+
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet import reactor
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import CREATED
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+from benchlib import initialize, sample
+
+# XXX Represent these as vobjects?  Would make it easier to add more vevents.
+event = """\
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VTIMEZONE
+TZID:America/Los_Angeles
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:PST
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:PDT
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+END:VTIMEZONE
+%(VEVENTS)s\
+END:VCALENDAR
+"""
+
+attendee = """\
+ATTENDEE;CN=User %(SEQUENCE)02d;CUTYPE=INDIVIDUAL;EMAIL=user%(SEQUENCE)02d at example.com;PARTSTAT=NE
+ EDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:urn:uuid:user%(SEQUENCE)02d
+"""
+
+organizer = """\
+ORGANIZER;CN=User %(SEQUENCE)02d;EMAIL=user%(SEQUENCE)02d at example.com:urn:uuid:user%(SEQUENCE)02d
+ATTENDEE;CN=User %(SEQUENCE)02d;EMAIL=user%(SEQUENCE)02d at example.com;PARTSTAT=ACCEPTE
+ D:urn:uuid:user%(SEQUENCE)02d
+"""
+
+def makeOrganizer(sequence):
+    return organizer % {'SEQUENCE': sequence}
+
+def makeAttendees(count):
+    return ''.join([
+            attendee % {'SEQUENCE': n} for n in range(2, count + 2)])
+
+
+def formatDate(d):
+    return ''.join(filter(str.isalnum, d.isoformat()))
+
+
+SUMMARY = "STUFF IS THINGS"
+
+def makeEvent(i, organizerSequence, attendeeCount):
+    s = """\
+BEGIN:VEVENT
+UID:%(UID)s
+DTSTART;TZID=America/Los_Angeles:%(START)s
+DTEND;TZID=America/Los_Angeles:%(END)s
+CREATED:20100729T193912Z
+DTSTAMP:20100729T195557Z
+%(ORGANIZER)s\
+%(ATTENDEES)s\
+SEQUENCE:0
+SUMMARY:%(summary)s
+TRANSP:OPAQUE
+END:VEVENT
+"""
+    base = datetime(2010, 7, 30, 11, 15, 00)
+    interval = timedelta(0, 5)
+    duration = timedelta(0, 3)
+    return event % {
+        'VEVENTS': s % {
+            'UID': uuid4(),
+            'START': formatDate(base + i * interval),
+            'END': formatDate(base + i * interval + duration),
+            'ORGANIZER': makeOrganizer(organizerSequence),
+            'ATTENDEES': makeAttendees(attendeeCount),
+            'summary': SUMMARY,
+            },
+        }
+
+
+ at inlineCallbacks
+def measure(host, port, dtrace, attendeeCount, samples):
+    organizerSequence = 1
+    user = password = "user%02d" % (organizerSequence,)
+    root = "/"
+    principal = "/"
+    calendar = "event-creation-benchmark"
+
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # First set things up
+    yield initialize(agent, host, port, user, password, root, principal, calendar)
+
+    method = 'PUT'
+    uri = 'http://%s:%d/calendars/__uids__/%s/%s/foo-%%d.ics' % (
+        host, port, user, calendar)
+    headers = Headers({"content-type": ["text/calendar"]})
+
+    # An infinite stream of VEVENTs to PUT to the server.
+    events = ((i, makeEvent(i, organizerSequence, attendeeCount)) for i in count(2))
+
+    # Sample it a bunch of times
+    samples = yield sample(
+        dtrace, samples, 
+        agent, ((method, uri % (i,), headers, StringProducer(body))
+                for (i, body)
+                in events).next,
+        CREATED)
+    returnValue(samples)
+

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_add_attendee.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_add_attendee.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_add_attendee.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_add_attendee.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,36 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+import _event_change
+
+from event import makeAttendees
+
+
+def measure(host, port, dtrace, attendeeCount, samples):
+    attendees = makeAttendees(attendeeCount)
+
+    def addAttendees(event, i):
+        """
+        Add C{i} new attendees to the given event.
+        """
+        # Find the last CREATED line
+        created = event.rfind('CREATED')
+        # Insert the attendees before it.
+        return event[:created] + attendees + event[created:]
+
+    return _event_change.measure(
+        host, port, dtrace, 0, samples, "add-attendee",
+        addAttendees, eventPerSample=True)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_change_date.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_change_date.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_change_date.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_change_date.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,51 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Benchmark a change in the date boundaries of an event.
+"""
+
+
+import datetime
+
+import _event_change
+
+TIME_FORMAT = '%Y%m%dT%H%M%S'
+
+def _increment(event, marker, amount):
+    # Find the last occurrence of the marker
+    dtstart = event.rfind(marker)
+    # Find the end of that line
+    eol = event.find('\n', dtstart)
+    # Find the : preceding the date on that line
+    colon = event.find(':', dtstart)
+    # Replace the text between the colon and the eol with the new timestamp
+    old = datetime.datetime.strptime(event[colon + 1:eol], TIME_FORMAT)
+    new = old + amount
+    return event[:colon + 1] + new.strftime(TIME_FORMAT) + event[eol:]
+
+
+def replaceTimestamp(event, i):
+    offset = datetime.timedelta(hours=i)
+    return _increment(
+        _increment(event, 'DTSTART', offset),
+        'DTEND', offset)
+
+
+def measure(host, port, dtrace, attendeeCount, samples):
+    return _event_change.measure(
+        host, port, dtrace, attendeeCount, samples, "change-date",
+        replaceTimestamp)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_change_summary.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_change_summary.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_change_summary.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_change_summary.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,28 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from event import SUMMARY
+
+import _event_change
+
+def replaceSummary(event, i):
+    return event.replace(SUMMARY, 'Replacement summary %d' % (i,))
+
+
+def measure(host, port, dtrace, attendeeCount, samples):
+    return _event_change.measure(
+        host, port, dtrace, attendeeCount, samples, "change-summary",
+        replaceSummary)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_delete.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_delete.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_delete.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_delete.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,77 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Benchmark a server's handling of event deletion.
+"""
+
+from itertools import count
+from urllib2 import HTTPDigestAuthHandler
+
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import NO_CONTENT
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+
+from benchlib import initialize, sample
+from event import makeEvent
+
+ at inlineCallbacks
+def measure(host, port, dtrace, attendeeCount, samples):
+    organizerSequence = 1
+    user = password = "user%02d" % (organizerSequence,)
+    root = "/"
+    principal = "/"
+    calendar = "event-deletion-benchmark"
+
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # Set up the calendar first
+    yield initialize(agent, host, port, user, password, root, principal, calendar)
+
+    # An infinite stream of VEVENTs to PUT to the server.
+    events = ((i, makeEvent(i, organizerSequence, attendeeCount))
+              for i in count(2))
+
+    # Create enough events to delete
+    uri = 'http://%s:%d/calendars/__uids__/%s/%s/foo-%%d.ics' % (
+        host, port, user, calendar)
+    headers = Headers({"content-type": ["text/calendar"]})
+    urls = []
+    for i, body in events:
+        urls.append(uri % (i,))
+        yield agent.request(
+            'PUT', urls[-1], headers, StringProducer(body))
+        if len(urls) == samples:
+            break
+
+    # Now delete them all
+    samples = yield sample(
+        dtrace, samples,
+        agent, (('DELETE', url) for url in urls).next,
+        NO_CONTENT)
+    returnValue(samples)
+

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_delete_attendee.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_delete_attendee.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_delete_attendee.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_delete_attendee.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+import _event_change
+
+def measure(host, port, dtrace, attendeeCount, samples):
+    def deleteAttendees(event, i):
+        """
+        Add C{i} new attendees to the given event.
+        """
+        for n in range(attendeeCount):
+            # Find the beginning of an ATTENDEE line
+            attendee = event.find('ATTENDEE')
+            # And the end of it
+            eol = event.find('\n', attendee)
+            # And remove it
+            event = event[:attendee] + event[eol:]
+        return event
+
+    return _event_change.measure(
+        host, port, dtrace, attendeeCount, samples, "delete-attendee",
+        deleteAttendees, eventPerSample=True)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/event_move.py (from rev 6927, CalendarServer/trunk/contrib/performance/event_move.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/event_move.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/event_move.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,77 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from itertools import count, cycle
+from urllib2 import HTTPDigestAuthHandler
+
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import CREATED
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+
+from benchlib import initialize, sample
+from event import makeEvent
+
+ at inlineCallbacks
+def measure(host, port, dtrace, attendeeCount, samples):
+    organizerSequence = 1
+    user = password = "user%02d" % (organizerSequence,)
+    root = "/"
+    principal = "/"
+
+    # Two calendars between which to move the event.
+    fooCalendar = "event-move-foo-benchmark"
+    barCalendar = "event-move-bar-benchmark"
+
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # Set up the calendars first
+    for calendar in [fooCalendar, barCalendar]:
+        yield initialize(
+            agent, host, port, user, password, root, principal, calendar)
+
+    fooURI = 'http://%s:%d/calendars/__uids__/%s/%s/some-event.ics' % (
+        host, port, user, fooCalendar)
+    barURI = 'http://%s:%d/calendars/__uids__/%s/%s/some-event.ics' % (
+        host, port, user, barCalendar)
+
+    # Create the event that will move around
+    headers = Headers({"content-type": ["text/calendar"]})
+    yield agent.request(
+        'PUT', fooURI, headers,
+        StringProducer(makeEvent(1, organizerSequence, attendeeCount)))
+
+    # Move it around sooo much
+    source = cycle([fooURI, barURI])
+    dest = cycle([barURI, fooURI])
+
+    params = (
+        ('MOVE', source.next(),
+         Headers({"destination": [dest.next()], "overwrite": ["F"]}))
+        for i in count(1))
+
+    samples = yield sample(dtrace, samples, agent, params.next, CREATED)
+    returnValue(samples)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/find_calendars.py (from rev 6927, CalendarServer/trunk/contrib/performance/find_calendars.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/find_calendars.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/find_calendars.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,104 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from itertools import count
+from urllib2 import HTTPDigestAuthHandler
+
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import MULTI_STATUS
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+
+from benchlib import CalDAVAccount, sample
+
+PROPFIND = """\
+<?xml version="1.0" encoding="utf-8"?>
+<x0:propfind xmlns:x0="DAV:" xmlns:x3="http://apple.com/ns/ical/" xmlns:x1="http://calendarserver.org/ns/" xmlns:x2="urn:ietf:params:xml:ns:caldav">
+ <x0:prop>
+  <x1:xmpp-server/>
+  <x1:xmpp-uri/>
+  <x1:getctag/>
+  <x0:displayname/>
+  <x2:calendar-description/>
+  <x3:calendar-color/>
+  <x3:calendar-order/>
+  <x2:supported-calendar-component-set/>
+  <x0:resourcetype/>
+  <x0:owner/>
+  <x2:calendar-free-busy-set/>
+  <x2:schedule-calendar-transp/>
+  <x2:schedule-default-calendar-URL/>
+  <x0:quota-available-bytes/>
+  <x0:quota-used-bytes/>
+  <x2:calendar-timezone/>
+  <x0:current-user-privilege-set/>
+  <x1:source/>
+  <x1:subscribed-strip-alarms/>
+  <x1:subscribed-strip-attachments/>
+  <x1:subscribed-strip-todos/>
+  <x3:refreshrate/>
+  <x1:push-transports/>
+  <x1:pushkey/>
+  <x1:publish-url/>
+ </x0:prop>
+</x0:propfind>
+"""
+
+ at inlineCallbacks
+def measure(host, port, dtrace, numCalendars, samples):
+    # There's already the "calendar" calendar
+    numCalendars -= 1
+
+    user = password = "user10"
+    root = "/"
+    principal = "/"
+
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # Create the number of calendars necessary
+    account = CalDAVAccount(
+        agent,
+        "%s:%d" % (host, port),
+        user=user, password=password,
+        root=root, principal=principal)
+    cal = "/calendars/users/%s/propfind-%%d/" % (user,)
+    for i in range(numCalendars):
+        yield account.makeCalendar(cal % (i,))
+
+    body = StringProducer(PROPFIND)
+    params = (
+        ('PROPFIND', 'http://%s:%d/calendars/__uids__/%s/' % (host, port, user),
+         Headers({"depth": ["1"], "content-type": ["text/xml"]}), body)
+        for i in count(1))
+
+    samples = yield sample(dtrace, samples, agent, params.next, MULTI_STATUS)
+
+    # Delete the calendars we created to leave the server in roughly
+    # the same state as we found it.
+    for i in range(numCalendars):
+        yield account.deleteResource(cal % (i,))
+
+    returnValue(samples)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/find_events.py (from rev 6927, CalendarServer/trunk/contrib/performance/find_events.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/find_events.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/find_events.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,98 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from itertools import count
+from urllib2 import HTTPDigestAuthHandler
+
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks, returnValue, gatherResults
+from twisted.internet.task import cooperate
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import MULTI_STATUS
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+
+from benchlib import CalDAVAccount, sample
+from event import makeEvent
+
+PROPFIND = """\
+<?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>
+"""
+
+def uploadEvents(numEvents, agent, uri, cal):
+    def worker():
+        for i in range(numEvents):
+            event = makeEvent(i, 1, 0)
+            yield agent.request(
+                'PUT',
+                '%s%s%d.ics' % (uri, cal, i),
+                Headers({"content-type": ["text/calendar"]}),
+                StringProducer(event))
+    worker = worker()
+    return gatherResults([
+            cooperate(worker).whenDone() for i in range(3)])
+
+
+ at inlineCallbacks
+def measure(host, port, dtrace, numEvents, samples):
+    user = password = "user11"
+    root = "/"
+    principal = "/"
+
+    uri = "http://%s:%d/" % (host, port)
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri=uri,
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # Create the number of calendars necessary
+    account = CalDAVAccount(
+        agent,
+        "%s:%d" % (host, port),
+        user=user, password=password,
+        root=root, principal=principal)
+    cal = "calendars/users/%s/find-events/" % (user,)
+    yield account.makeCalendar("/" + cal)
+
+    # Create the indicated number of events on the calendar
+    yield uploadEvents(numEvents, agent, uri, cal)
+
+    body = StringProducer(PROPFIND)
+    params = (
+        ('PROPFIND',
+         '%scalendars/__uids__/%s/find-events/' % (uri, user),
+         Headers({"depth": ["1"], "content-type": ["text/xml"]}), body)
+        for i in count(1))
+
+    samples = yield sample(dtrace, samples, agent, params.next, MULTI_STATUS)
+
+    # Delete the calendar we created to leave the server in roughly
+    # the same state as we found it.
+    yield account.deleteResource("/" + cal)
+
+    returnValue(samples)

Copied: CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py (from rev 6927, CalendarServer/trunk/contrib/performance/vfreebusy.py)
===================================================================
--- CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py	                        (rev 0)
+++ CalendarServer/trunk/contrib/performance/benchmarks/vfreebusy.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -0,0 +1,147 @@
+##
+# Copyright (c) 2010 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.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Benchmark a server's handling of VFREEBUSY requests.
+"""
+
+from urllib2 import HTTPDigestAuthHandler
+from uuid import uuid4
+from datetime import datetime, timedelta
+
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.internet import reactor
+from twisted.web.client import Agent
+from twisted.web.http_headers import Headers
+from twisted.web.http import OK
+
+from httpauth import AuthHandlerAgent
+from httpclient import StringProducer
+from benchlib import initialize, sample
+
+# XXX Represent these as vobjects?  Would make it easier to add more vevents.
+event = """\
+BEGIN:VCALENDAR
+VERSION:2.0
+CALSCALE:GREGORIAN
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VTIMEZONE
+TZID:America/New_York
+BEGIN:STANDARD
+DTSTART:20071104T020000
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20070311T020000
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+END:VTIMEZONE
+%(VEVENTS)s\
+END:VCALENDAR
+"""
+
+vfreebusy = """\
+BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+VERSION:2.0
+METHOD:REQUEST
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+BEGIN:VFREEBUSY
+UID:81F582C8-4E7F-491C-85F4-E541864BE0FA
+DTEND:20100730T150000Z
+ATTENDEE:urn:uuid:user02
+DTSTART:20100730T140000Z
+X-CALENDARSERVER-MASK-UID:EC75A61B-08A3-44FD-BFBB-2457BBD0D490
+DTSTAMP:20100729T174751Z
+ORGANIZER:mailto:user01 at example.com
+SUMMARY:Availability for urn:uuid:user02
+END:VFREEBUSY
+END:VCALENDAR
+"""
+
+def formatDate(d):
+    return ''.join(filter(str.isalnum, d.isoformat()))
+
+def makeEvent(i):
+    s = """\
+BEGIN:VEVENT
+UID:%(UID)s
+DTSTART;TZID=America/New_York:%(START)s
+DTEND;TZID=America/New_York:%(END)s
+CREATED:20100729T193912Z
+DTSTAMP:20100729T195557Z
+SEQUENCE:%(SEQUENCE)s
+SUMMARY:STUFF IS THINGS
+TRANSP:OPAQUE
+END:VEVENT
+"""
+    base = datetime(2010, 7, 30, 11, 15, 00)
+    interval = timedelta(hours=2)
+    duration = timedelta(hours=1)
+    return event % {
+        'VEVENTS': s % {
+            'UID': uuid4(),
+            'START': formatDate(base + i * interval),
+            'END': formatDate(base + i * interval + duration),
+            'SEQUENCE': i,
+            },
+        }
+
+
+def makeEvents(n):
+    return [makeEvent(i) for i in range(n)]
+
+
+ at inlineCallbacks
+def measure(host, port, dtrace, events, samples):
+    user = password = "user01"
+    root = "/"
+    principal = "/"
+    calendar = "vfreebusy-benchmark"
+
+    authinfo = HTTPDigestAuthHandler()
+    authinfo.add_password(
+        realm="Test Realm",
+        uri="http://%s:%d/" % (host, port),
+        user=user,
+        passwd=password)
+    agent = AuthHandlerAgent(Agent(reactor), authinfo)
+
+    # First set things up
+    account = yield initialize(
+        agent, host, port, user, password, root, principal, calendar)
+
+    base = "/calendars/users/%s/%s/foo-%%d.ics" % (user, calendar)
+    for i, cal in enumerate(makeEvents(events)):
+        yield account.writeData(base % (i,), cal, "text/calendar")
+
+    method = 'POST'
+    uri = 'http://%s:%d/calendars/__uids__/%s/outbox/' % (host, port, user)
+    headers = Headers({"content-type": ["text/calendar"]})
+    body = StringProducer(vfreebusy)
+
+    samples = yield sample(
+        dtrace, samples,
+        agent, lambda: (method, uri, headers, body),
+        OK)
+    returnValue(samples)
+

Deleted: CalendarServer/trunk/contrib/performance/event.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,153 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-Benchmark a server's handling of event creation.
-"""
-
-from itertools import count
-from urllib2 import HTTPDigestAuthHandler
-from uuid import uuid4
-from datetime import datetime, timedelta
-
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.internet import reactor
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import CREATED
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-from benchlib import initialize, sample
-
-# XXX Represent these as vobjects?  Would make it easier to add more vevents.
-event = """\
-BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//Apple Inc.//iCal 4.0.3//EN
-BEGIN:VTIMEZONE
-TZID:America/Los_Angeles
-BEGIN:STANDARD
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:PST
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0800
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:PDT
-TZOFFSETFROM:-0800
-TZOFFSETTO:-0700
-END:DAYLIGHT
-END:VTIMEZONE
-%(VEVENTS)s\
-END:VCALENDAR
-"""
-
-attendee = """\
-ATTENDEE;CN=User %(SEQUENCE)02d;CUTYPE=INDIVIDUAL;EMAIL=user%(SEQUENCE)02d at example.com;PARTSTAT=NE
- EDS-ACTION;ROLE=REQ-PARTICIPANT;RSVP=TRUE:urn:uuid:user%(SEQUENCE)02d
-"""
-
-organizer = """\
-ORGANIZER;CN=User %(SEQUENCE)02d;EMAIL=user%(SEQUENCE)02d at example.com:urn:uuid:user%(SEQUENCE)02d
-ATTENDEE;CN=User %(SEQUENCE)02d;EMAIL=user%(SEQUENCE)02d at example.com;PARTSTAT=ACCEPTE
- D:urn:uuid:user%(SEQUENCE)02d
-"""
-
-def makeOrganizer(sequence):
-    return organizer % {'SEQUENCE': sequence}
-
-def makeAttendees(count):
-    return ''.join([
-            attendee % {'SEQUENCE': n} for n in range(2, count + 2)])
-
-
-def formatDate(d):
-    return ''.join(filter(str.isalnum, d.isoformat()))
-
-
-SUMMARY = "STUFF IS THINGS"
-
-def makeEvent(i, organizerSequence, attendeeCount):
-    s = """\
-BEGIN:VEVENT
-UID:%(UID)s
-DTSTART;TZID=America/Los_Angeles:%(START)s
-DTEND;TZID=America/Los_Angeles:%(END)s
-CREATED:20100729T193912Z
-DTSTAMP:20100729T195557Z
-%(ORGANIZER)s\
-%(ATTENDEES)s\
-SEQUENCE:0
-SUMMARY:%(summary)s
-TRANSP:OPAQUE
-END:VEVENT
-"""
-    base = datetime(2010, 7, 30, 11, 15, 00)
-    interval = timedelta(0, 5)
-    duration = timedelta(0, 3)
-    return event % {
-        'VEVENTS': s % {
-            'UID': uuid4(),
-            'START': formatDate(base + i * interval),
-            'END': formatDate(base + i * interval + duration),
-            'ORGANIZER': makeOrganizer(organizerSequence),
-            'ATTENDEES': makeAttendees(attendeeCount),
-            'summary': SUMMARY,
-            },
-        }
-
-
- at inlineCallbacks
-def measure(host, port, dtrace, attendeeCount, samples):
-    organizerSequence = 1
-    user = password = "user%02d" % (organizerSequence,)
-    root = "/"
-    principal = "/"
-    calendar = "event-creation-benchmark"
-
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri="http://%s:%d/" % (host, port),
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # First set things up
-    yield initialize(agent, host, port, user, password, root, principal, calendar)
-
-    method = 'PUT'
-    uri = 'http://%s:%d/calendars/__uids__/%s/%s/foo-%%d.ics' % (
-        host, port, user, calendar)
-    headers = Headers({"content-type": ["text/calendar"]})
-
-    # An infinite stream of VEVENTs to PUT to the server.
-    events = ((i, makeEvent(i, organizerSequence, attendeeCount)) for i in count(2))
-
-    # Sample it a bunch of times
-    samples = yield sample(
-        dtrace, samples, 
-        agent, ((method, uri % (i,), headers, StringProducer(body))
-                for (i, body)
-                in events).next,
-        CREATED)
-    returnValue(samples)
-

Deleted: CalendarServer/trunk/contrib/performance/event_add_attendee.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_add_attendee.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_add_attendee.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,36 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import _event_change
-
-from event import makeAttendees
-
-
-def measure(host, port, dtrace, attendeeCount, samples):
-    attendees = makeAttendees(attendeeCount)
-
-    def addAttendees(event, i):
-        """
-        Add C{i} new attendees to the given event.
-        """
-        # Find the last CREATED line
-        created = event.rfind('CREATED')
-        # Insert the attendees before it.
-        return event[:created] + attendees + event[created:]
-
-    return _event_change.measure(
-        host, port, dtrace, 0, samples, "add-attendee",
-        addAttendees, eventPerSample=True)

Deleted: CalendarServer/trunk/contrib/performance/event_change_date.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_change_date.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_change_date.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,51 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-Benchmark a change in the date boundaries of an event.
-"""
-
-
-import datetime
-
-import _event_change
-
-TIME_FORMAT = '%Y%m%dT%H%M%S'
-
-def _increment(event, marker, amount):
-    # Find the last occurrence of the marker
-    dtstart = event.rfind(marker)
-    # Find the end of that line
-    eol = event.find('\n', dtstart)
-    # Find the : preceding the date on that line
-    colon = event.find(':', dtstart)
-    # Replace the text between the colon and the eol with the new timestamp
-    old = datetime.datetime.strptime(event[colon + 1:eol], TIME_FORMAT)
-    new = old + amount
-    return event[:colon + 1] + new.strftime(TIME_FORMAT) + event[eol:]
-
-
-def replaceTimestamp(event, i):
-    offset = datetime.timedelta(hours=i)
-    return _increment(
-        _increment(event, 'DTSTART', offset),
-        'DTEND', offset)
-
-
-def measure(host, port, dtrace, attendeeCount, samples):
-    return _event_change.measure(
-        host, port, dtrace, attendeeCount, samples, "change-date",
-        replaceTimestamp)

Deleted: CalendarServer/trunk/contrib/performance/event_change_summary.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_change_summary.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_change_summary.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,28 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from event import SUMMARY
-
-import _event_change
-
-def replaceSummary(event, i):
-    return event.replace(SUMMARY, 'Replacement summary %d' % (i,))
-
-
-def measure(host, port, dtrace, attendeeCount, samples):
-    return _event_change.measure(
-        host, port, dtrace, attendeeCount, samples, "change-summary",
-        replaceSummary)

Deleted: CalendarServer/trunk/contrib/performance/event_delete.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_delete.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_delete.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,77 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-Benchmark a server's handling of event deletion.
-"""
-
-from itertools import count
-from urllib2 import HTTPDigestAuthHandler
-
-from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import NO_CONTENT
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-
-from benchlib import initialize, sample
-from event import makeEvent
-
- at inlineCallbacks
-def measure(host, port, dtrace, attendeeCount, samples):
-    organizerSequence = 1
-    user = password = "user%02d" % (organizerSequence,)
-    root = "/"
-    principal = "/"
-    calendar = "event-deletion-benchmark"
-
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri="http://%s:%d/" % (host, port),
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # Set up the calendar first
-    yield initialize(agent, host, port, user, password, root, principal, calendar)
-
-    # An infinite stream of VEVENTs to PUT to the server.
-    events = ((i, makeEvent(i, organizerSequence, attendeeCount))
-              for i in count(2))
-
-    # Create enough events to delete
-    uri = 'http://%s:%d/calendars/__uids__/%s/%s/foo-%%d.ics' % (
-        host, port, user, calendar)
-    headers = Headers({"content-type": ["text/calendar"]})
-    urls = []
-    for i, body in events:
-        urls.append(uri % (i,))
-        yield agent.request(
-            'PUT', urls[-1], headers, StringProducer(body))
-        if len(urls) == samples:
-            break
-
-    # Now delete them all
-    samples = yield sample(
-        dtrace, samples,
-        agent, (('DELETE', url) for url in urls).next,
-        NO_CONTENT)
-    returnValue(samples)
-

Deleted: CalendarServer/trunk/contrib/performance/event_delete_attendee.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_delete_attendee.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_delete_attendee.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,35 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import _event_change
-
-def measure(host, port, dtrace, attendeeCount, samples):
-    def deleteAttendees(event, i):
-        """
-        Add C{i} new attendees to the given event.
-        """
-        for n in range(attendeeCount):
-            # Find the beginning of an ATTENDEE line
-            attendee = event.find('ATTENDEE')
-            # And the end of it
-            eol = event.find('\n', attendee)
-            # And remove it
-            event = event[:attendee] + event[eol:]
-        return event
-
-    return _event_change.measure(
-        host, port, dtrace, attendeeCount, samples, "delete-attendee",
-        deleteAttendees, eventPerSample=True)

Deleted: CalendarServer/trunk/contrib/performance/event_move.py
===================================================================
--- CalendarServer/trunk/contrib/performance/event_move.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/event_move.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,77 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from itertools import count, cycle
-from urllib2 import HTTPDigestAuthHandler
-
-from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import CREATED
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-
-from benchlib import initialize, sample
-from event import makeEvent
-
- at inlineCallbacks
-def measure(host, port, dtrace, attendeeCount, samples):
-    organizerSequence = 1
-    user = password = "user%02d" % (organizerSequence,)
-    root = "/"
-    principal = "/"
-
-    # Two calendars between which to move the event.
-    fooCalendar = "event-move-foo-benchmark"
-    barCalendar = "event-move-bar-benchmark"
-
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri="http://%s:%d/" % (host, port),
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # Set up the calendars first
-    for calendar in [fooCalendar, barCalendar]:
-        yield initialize(
-            agent, host, port, user, password, root, principal, calendar)
-
-    fooURI = 'http://%s:%d/calendars/__uids__/%s/%s/some-event.ics' % (
-        host, port, user, fooCalendar)
-    barURI = 'http://%s:%d/calendars/__uids__/%s/%s/some-event.ics' % (
-        host, port, user, barCalendar)
-
-    # Create the event that will move around
-    headers = Headers({"content-type": ["text/calendar"]})
-    yield agent.request(
-        'PUT', fooURI, headers,
-        StringProducer(makeEvent(1, organizerSequence, attendeeCount)))
-
-    # Move it around sooo much
-    source = cycle([fooURI, barURI])
-    dest = cycle([barURI, fooURI])
-
-    params = (
-        ('MOVE', source.next(),
-         Headers({"destination": [dest.next()], "overwrite": ["F"]}))
-        for i in count(1))
-
-    samples = yield sample(dtrace, samples, agent, params.next, CREATED)
-    returnValue(samples)

Deleted: CalendarServer/trunk/contrib/performance/find_calendars.py
===================================================================
--- CalendarServer/trunk/contrib/performance/find_calendars.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/find_calendars.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,104 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from itertools import count
-from urllib2 import HTTPDigestAuthHandler
-
-from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import MULTI_STATUS
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-
-from benchlib import CalDAVAccount, sample
-
-PROPFIND = """\
-<?xml version="1.0" encoding="utf-8"?>
-<x0:propfind xmlns:x0="DAV:" xmlns:x3="http://apple.com/ns/ical/" xmlns:x1="http://calendarserver.org/ns/" xmlns:x2="urn:ietf:params:xml:ns:caldav">
- <x0:prop>
-  <x1:xmpp-server/>
-  <x1:xmpp-uri/>
-  <x1:getctag/>
-  <x0:displayname/>
-  <x2:calendar-description/>
-  <x3:calendar-color/>
-  <x3:calendar-order/>
-  <x2:supported-calendar-component-set/>
-  <x0:resourcetype/>
-  <x0:owner/>
-  <x2:calendar-free-busy-set/>
-  <x2:schedule-calendar-transp/>
-  <x2:schedule-default-calendar-URL/>
-  <x0:quota-available-bytes/>
-  <x0:quota-used-bytes/>
-  <x2:calendar-timezone/>
-  <x0:current-user-privilege-set/>
-  <x1:source/>
-  <x1:subscribed-strip-alarms/>
-  <x1:subscribed-strip-attachments/>
-  <x1:subscribed-strip-todos/>
-  <x3:refreshrate/>
-  <x1:push-transports/>
-  <x1:pushkey/>
-  <x1:publish-url/>
- </x0:prop>
-</x0:propfind>
-"""
-
- at inlineCallbacks
-def measure(host, port, dtrace, numCalendars, samples):
-    # There's already the "calendar" calendar
-    numCalendars -= 1
-
-    user = password = "user10"
-    root = "/"
-    principal = "/"
-
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri="http://%s:%d/" % (host, port),
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # Create the number of calendars necessary
-    account = CalDAVAccount(
-        agent,
-        "%s:%d" % (host, port),
-        user=user, password=password,
-        root=root, principal=principal)
-    cal = "/calendars/users/%s/propfind-%%d/" % (user,)
-    for i in range(numCalendars):
-        yield account.makeCalendar(cal % (i,))
-
-    body = StringProducer(PROPFIND)
-    params = (
-        ('PROPFIND', 'http://%s:%d/calendars/__uids__/%s/' % (host, port, user),
-         Headers({"depth": ["1"], "content-type": ["text/xml"]}), body)
-        for i in count(1))
-
-    samples = yield sample(dtrace, samples, agent, params.next, MULTI_STATUS)
-
-    # Delete the calendars we created to leave the server in roughly
-    # the same state as we found it.
-    for i in range(numCalendars):
-        yield account.deleteResource(cal % (i,))
-
-    returnValue(samples)

Deleted: CalendarServer/trunk/contrib/performance/find_events.py
===================================================================
--- CalendarServer/trunk/contrib/performance/find_events.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/find_events.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,98 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from itertools import count
-from urllib2 import HTTPDigestAuthHandler
-
-from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue, gatherResults
-from twisted.internet.task import cooperate
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import MULTI_STATUS
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-
-from benchlib import CalDAVAccount, sample
-from event import makeEvent
-
-PROPFIND = """\
-<?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>
-"""
-
-def uploadEvents(numEvents, agent, uri, cal):
-    def worker():
-        for i in range(numEvents):
-            event = makeEvent(i, 1, 0)
-            yield agent.request(
-                'PUT',
-                '%s%s%d.ics' % (uri, cal, i),
-                Headers({"content-type": ["text/calendar"]}),
-                StringProducer(event))
-    worker = worker()
-    return gatherResults([
-            cooperate(worker).whenDone() for i in range(3)])
-
-
- at inlineCallbacks
-def measure(host, port, dtrace, numEvents, samples):
-    user = password = "user11"
-    root = "/"
-    principal = "/"
-
-    uri = "http://%s:%d/" % (host, port)
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri=uri,
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # Create the number of calendars necessary
-    account = CalDAVAccount(
-        agent,
-        "%s:%d" % (host, port),
-        user=user, password=password,
-        root=root, principal=principal)
-    cal = "calendars/users/%s/find-events/" % (user,)
-    yield account.makeCalendar("/" + cal)
-
-    # Create the indicated number of events on the calendar
-    yield uploadEvents(numEvents, agent, uri, cal)
-
-    body = StringProducer(PROPFIND)
-    params = (
-        ('PROPFIND',
-         '%scalendars/__uids__/%s/find-events/' % (uri, user),
-         Headers({"depth": ["1"], "content-type": ["text/xml"]}), body)
-        for i in count(1))
-
-    samples = yield sample(dtrace, samples, agent, params.next, MULTI_STATUS)
-
-    # Delete the calendar we created to leave the server in roughly
-    # the same state as we found it.
-    yield account.deleteResource("/" + cal)
-
-    returnValue(samples)

Deleted: CalendarServer/trunk/contrib/performance/vfreebusy.py
===================================================================
--- CalendarServer/trunk/contrib/performance/vfreebusy.py	2011-02-15 19:50:17 UTC (rev 6930)
+++ CalendarServer/trunk/contrib/performance/vfreebusy.py	2011-02-15 20:54:05 UTC (rev 6931)
@@ -1,147 +0,0 @@
-##
-# Copyright (c) 2010 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.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-"""
-Benchmark a server's handling of VFREEBUSY requests.
-"""
-
-from urllib2 import HTTPDigestAuthHandler
-from uuid import uuid4
-from datetime import datetime, timedelta
-
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twisted.internet import reactor
-from twisted.web.client import Agent
-from twisted.web.http_headers import Headers
-from twisted.web.http import OK
-
-from httpauth import AuthHandlerAgent
-from httpclient import StringProducer
-from benchlib import initialize, sample
-
-# XXX Represent these as vobjects?  Would make it easier to add more vevents.
-event = """\
-BEGIN:VCALENDAR
-VERSION:2.0
-CALSCALE:GREGORIAN
-PRODID:-//Apple Inc.//iCal 4.0.3//EN
-BEGIN:VTIMEZONE
-TZID:America/New_York
-BEGIN:STANDARD
-DTSTART:20071104T020000
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-TZNAME:EST
-TZOFFSETFROM:-0400
-TZOFFSETTO:-0500
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20070311T020000
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-TZNAME:EDT
-TZOFFSETFROM:-0500
-TZOFFSETTO:-0400
-END:DAYLIGHT
-END:VTIMEZONE
-%(VEVENTS)s\
-END:VCALENDAR
-"""
-
-vfreebusy = """\
-BEGIN:VCALENDAR
-CALSCALE:GREGORIAN
-VERSION:2.0
-METHOD:REQUEST
-PRODID:-//Apple Inc.//iCal 4.0.3//EN
-BEGIN:VFREEBUSY
-UID:81F582C8-4E7F-491C-85F4-E541864BE0FA
-DTEND:20100730T150000Z
-ATTENDEE:urn:uuid:user02
-DTSTART:20100730T140000Z
-X-CALENDARSERVER-MASK-UID:EC75A61B-08A3-44FD-BFBB-2457BBD0D490
-DTSTAMP:20100729T174751Z
-ORGANIZER:mailto:user01 at example.com
-SUMMARY:Availability for urn:uuid:user02
-END:VFREEBUSY
-END:VCALENDAR
-"""
-
-def formatDate(d):
-    return ''.join(filter(str.isalnum, d.isoformat()))
-
-def makeEvent(i):
-    s = """\
-BEGIN:VEVENT
-UID:%(UID)s
-DTSTART;TZID=America/New_York:%(START)s
-DTEND;TZID=America/New_York:%(END)s
-CREATED:20100729T193912Z
-DTSTAMP:20100729T195557Z
-SEQUENCE:%(SEQUENCE)s
-SUMMARY:STUFF IS THINGS
-TRANSP:OPAQUE
-END:VEVENT
-"""
-    base = datetime(2010, 7, 30, 11, 15, 00)
-    interval = timedelta(hours=2)
-    duration = timedelta(hours=1)
-    return event % {
-        'VEVENTS': s % {
-            'UID': uuid4(),
-            'START': formatDate(base + i * interval),
-            'END': formatDate(base + i * interval + duration),
-            'SEQUENCE': i,
-            },
-        }
-
-
-def makeEvents(n):
-    return [makeEvent(i) for i in range(n)]
-
-
- at inlineCallbacks
-def measure(host, port, dtrace, events, samples):
-    user = password = "user01"
-    root = "/"
-    principal = "/"
-    calendar = "vfreebusy-benchmark"
-
-    authinfo = HTTPDigestAuthHandler()
-    authinfo.add_password(
-        realm="Test Realm",
-        uri="http://%s:%d/" % (host, port),
-        user=user,
-        passwd=password)
-    agent = AuthHandlerAgent(Agent(reactor), authinfo)
-
-    # First set things up
-    account = yield initialize(
-        agent, host, port, user, password, root, principal, calendar)
-
-    base = "/calendars/users/%s/%s/foo-%%d.ics" % (user, calendar)
-    for i, cal in enumerate(makeEvents(events)):
-        yield account.writeData(base % (i,), cal, "text/calendar")
-
-    method = 'POST'
-    uri = 'http://%s:%d/calendars/__uids__/%s/outbox/' % (host, port, user)
-    headers = Headers({"content-type": ["text/calendar"]})
-    body = StringProducer(vfreebusy)
-
-    samples = yield sample(
-        dtrace, samples,
-        agent, lambda: (method, uri, headers, body),
-        OK)
-    returnValue(samples)
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110215/bd594349/attachment-0001.html>


More information about the calendarserver-changes mailing list