<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[15166] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/15166">15166</a></dd>
<dt>Author</dt> <dd>sagen@apple.com</dd>
<dt>Date</dt> <dd>2015-10-05 14:24:18 -0700 (Mon, 05 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Undo last commit</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkcalendarserverpushamppushpy">CalendarServer/trunk/calendarserver/push/amppush.py</a></li>
<li><a href="#CalendarServertrunkconfcaldavdappleplist">CalendarServer/trunk/conf/caldavd-apple.plist</a></li>
<li><a href="#CalendarServertrunkconfcaldavdtestplist">CalendarServer/trunk/conf/caldavd-test.plist</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestclientsplist">CalendarServer/trunk/contrib/performance/loadtest/clients.plist</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestconfigplist">CalendarServer/trunk/contrib/performance/loadtest/config.plist</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesticalpy">CalendarServer/trunk/contrib/performance/loadtest/ical.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestpopulationpy">CalendarServer/trunk/contrib/performance/loadtest/population.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestprofilespy">CalendarServer/trunk/contrib/performance/loadtest/profiles.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestsimpy">CalendarServer/trunk/contrib/performance/loadtest/sim.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesttest_profilespy">CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtesttest_simpy">CalendarServer/trunk/contrib/performance/loadtest/test_sim.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstdconfigpy">CalendarServer/trunk/twistedcaldav/stdconfig.py</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li>CalendarServer/trunk/contrib/performance/loadtest/request-data/OS_X_10_11/</li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkcalendarserverpushamppushpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/calendarserver/push/amppush.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/calendarserver/push/amppush.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/calendarserver/push/amppush.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> class UnsubscribeFromID(amp.Command):
</span><del>-    arguments = [('id', amp.String())]
</del><ins>+    arguments = [('token', amp.String()), ('id', amp.String())]
</ins><span class="cx">     response = [('status', amp.String())]
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -257,7 +257,7 @@
</span><span class="cx">         return {&quot;status&quot; : &quot;OK&quot;}
</span><span class="cx">     SubscribeToID.responder(subscribe)
</span><span class="cx"> 
</span><del>-    def unsubscribe(self, id):
</del><ins>+    def unsubscribe(self, token, id):
</ins><span class="cx">         try:
</span><span class="cx">             del self.subscriptions[id]
</span><span class="cx">         except KeyError:
</span></span></pre></div>
<a id="CalendarServertrunkconfcaldavdappleplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/conf/caldavd-apple.plist (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/conf/caldavd-apple.plist        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/conf/caldavd-apple.plist        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -371,10 +371,10 @@
</span><span class="cx">       --&gt;
</span><span class="cx"> 
</span><span class="cx">     &lt;key&gt;UserName&lt;/key&gt;
</span><del>-    &lt;string&gt;_calendar&lt;/string&gt;
</del><ins>+    &lt;string&gt;calendar&lt;/string&gt;
</ins><span class="cx"> 
</span><span class="cx">     &lt;key&gt;GroupName&lt;/key&gt;
</span><del>-    &lt;string&gt;_calendar&lt;/string&gt;
</del><ins>+    &lt;string&gt;calendar&lt;/string&gt;
</ins><span class="cx"> 
</span><span class="cx">     &lt;key&gt;ProcessType&lt;/key&gt;
</span><span class="cx">     &lt;string&gt;Combined&lt;/string&gt;
</span></span></pre></div>
<a id="CalendarServertrunkconfcaldavdtestplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/conf/caldavd-test.plist (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/conf/caldavd-test.plist        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/conf/caldavd-test.plist        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -537,7 +537,7 @@
</span><span class="cx">     &lt;key&gt;AccountingCategories&lt;/key&gt;
</span><span class="cx">     &lt;dict&gt;
</span><span class="cx">       &lt;key&gt;HTTP&lt;/key&gt;
</span><del>-      &lt;true/&gt;
</del><ins>+      &lt;false/&gt;
</ins><span class="cx">       &lt;key&gt;iTIP&lt;/key&gt;
</span><span class="cx">       &lt;false/&gt;
</span><span class="cx">       &lt;key&gt;iTIP-VFREEBUSY&lt;/key&gt;
</span><span class="lines">@@ -897,16 +897,12 @@
</span><span class="cx">     &lt;!-- Support for Postgres --&gt;
</span><span class="cx">     &lt;key&gt;Postgres&lt;/key&gt;
</span><span class="cx">     &lt;dict&gt;
</span><del>-      &lt;key&gt;ListenAddresses&lt;/key&gt;
-      &lt;array&gt;
-      &lt;string&gt;127.0.0.1&lt;/string&gt;
-      &lt;/array&gt;
</del><span class="cx">       &lt;key&gt;Options&lt;/key&gt;
</span><span class="cx">       &lt;array&gt;
</span><del>-        &lt;!-- Optional extra logging for posgres --&gt;
-        &lt;!-- &lt;string&gt;-c log_lock_waits=TRUE&lt;/string&gt; --&gt;
-        &lt;!-- &lt;string&gt;-c log_statement=all&lt;/string&gt; --&gt;
-        &lt;!-- &lt;string&gt;-c log_line_prefix='%t [%p]: [%l] '&lt;/string&gt; --&gt;
</del><ins>+              &lt;!-- Optional extra logging for posgres --&gt;
+              &lt;!-- &lt;string&gt;-c log_lock_waits=TRUE&lt;/string&gt; --&gt;
+              &lt;!-- &lt;string&gt;-c log_statement=all&lt;/string&gt; --&gt;
+              &lt;!-- &lt;string&gt;-c log_line_prefix='%t [%p]: [%l] '&lt;/string&gt; --&gt;
</ins><span class="cx">       &lt;/array&gt;
</span><span class="cx">     &lt;/dict&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestclientsplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/clients.plist (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/clients.plist        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/clients.plist        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -31,16 +31,16 @@
</span><span class="cx"> 
</span><span class="cx">                                 &lt;!-- Here is a OS X client simulator. --&gt;
</span><span class="cx">                                 &lt;key&gt;software&lt;/key&gt;
</span><del>-                                &lt;string&gt;contrib.performance.loadtest.ical.OS_X_10_11&lt;/string&gt;
</del><ins>+                                &lt;string&gt;contrib.performance.loadtest.ical.OS_X_10_7&lt;/string&gt;
</ins><span class="cx"> 
</span><del>-                                &lt;!-- Arguments to use to initialize the OS_X_10_11 instance. --&gt;
</del><ins>+                                &lt;!-- Arguments to use to initialize the OS_X_10_7 instance. --&gt;
</ins><span class="cx">                                 &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">                                 &lt;dict&gt;
</span><span class="cx">                                         &lt;!-- Name that appears in logs. --&gt;
</span><span class="cx">                                         &lt;key&gt;title&lt;/key&gt;
</span><del>-                                        &lt;string&gt;10.11&lt;/string&gt;
-
-                                        &lt;!-- OS_X_10_11 can poll the calendar home at some interval. This is
</del><ins>+                                        &lt;string&gt;10.7&lt;/string&gt;
+        
+                                        &lt;!-- OS_X_10_7 can poll the calendar home at some interval. This is
</ins><span class="cx">                                                 in seconds. --&gt;
</span><span class="cx">                                         &lt;key&gt;calendarHomePollInterval&lt;/key&gt;
</span><span class="cx">                                         &lt;integer&gt;30&lt;/integer&gt;
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">                                                 and use it if possible. Still fall back to polling if there is no xmpp push
</span><span class="cx">                                                 advertised. --&gt;
</span><span class="cx">                                         &lt;key&gt;supportPush&lt;/key&gt;
</span><del>-                                        &lt;true/&gt;
</del><ins>+                                        &lt;false /&gt;
</ins><span class="cx"> 
</span><span class="cx">                                         &lt;key&gt;supportAmpPush&lt;/key&gt;
</span><span class="cx">                                         &lt;true/&gt;
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">                                                 &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">                                                 &lt;dict&gt;
</span><span class="cx">                                                         &lt;key&gt;enabled&lt;/key&gt;
</span><del>-                                                        &lt;false/&gt;
</del><ins>+                                                        &lt;true/&gt;
</ins><span class="cx"> 
</span><span class="cx">                                                         &lt;!-- Define the interval (in seconds) at which this profile will use
</span><span class="cx">                                                                 its client to create a new event. --&gt;
</span><span class="lines">@@ -144,13 +144,13 @@
</span><span class="cx">                                                                                 &lt;!-- Half of all events will be non-recurring --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;none&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;50&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Daily and weekly are pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;daily&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;10&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weekly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;20&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;monthly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;2&lt;/integer&gt;
</span><span class="lines">@@ -160,7 +160,7 @@
</span><span class="cx">                                                                                 &lt;integer&gt;2&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weeklylimit&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;5&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Work days pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;workdays&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;10&lt;/integer&gt;
</span><span class="lines">@@ -247,13 +247,13 @@
</span><span class="cx">                                                                                 &lt;!-- Half of all events will be non-recurring --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;none&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;50&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Daily and weekly are pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;daily&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;25&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weekly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;25&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;monthly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;0&lt;/integer&gt;
</span><span class="lines">@@ -263,7 +263,7 @@
</span><span class="cx">                                                                                 &lt;integer&gt;0&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weeklylimit&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;0&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Work days pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;workdays&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;0&lt;/integer&gt;
</span><span class="lines">@@ -273,99 +273,6 @@
</span><span class="cx">                                                 &lt;/dict&gt;
</span><span class="cx">                                         &lt;/dict&gt;
</span><span class="cx"> 
</span><del>-                                        &lt;!-- Picks a random event and changes the title --&gt;
-                                        &lt;dict&gt;
-                                                &lt;key&gt;class&lt;/key&gt;
-                                                &lt;string&gt;contrib.performance.loadtest.profiles.TitleChanger&lt;/string&gt;
-
-                                                &lt;key&gt;params&lt;/key&gt;
-                                                &lt;dict&gt;
-                                                        &lt;key&gt;enabled&lt;/key&gt;
-                                                        &lt;false/&gt;
-
-                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
-                                                                its client to create a new event. --&gt;
-                                                        &lt;key&gt;interval&lt;/key&gt;
-                                                        &lt;integer&gt;10&lt;/integer&gt;
-
-                                                &lt;/dict&gt;
-                                        &lt;/dict&gt;
-
-                                        &lt;!-- Picks a random event and attaches --&gt;
-                                        &lt;dict&gt;
-                                                &lt;key&gt;class&lt;/key&gt;
-                                                &lt;string&gt;contrib.performance.loadtest.profiles.Attacher&lt;/string&gt;
-
-                                                &lt;key&gt;params&lt;/key&gt;
-                                                &lt;dict&gt;
-                                                        &lt;key&gt;enabled&lt;/key&gt;
-                                                        &lt;false/&gt;
-
-                                                        &lt;!-- Define the interval (in seconds) at which this profile will use
-                                                                its client to create a new event. --&gt;
-                                                        &lt;key&gt;interval&lt;/key&gt;
-                                                        &lt;integer&gt;10&lt;/integer&gt;
-
-                                                        &lt;!-- Define the attachment size distribution. --&gt;
-                                                        &lt;key&gt;fileSizeDistribution&lt;/key&gt;
-                                                        &lt;dict&gt;
-                                                                &lt;key&gt;type&lt;/key&gt;
-                                                                &lt;string&gt;contrib.performance.stats.NormalDistribution&lt;/string&gt;
-                                                                &lt;key&gt;params&lt;/key&gt;
-                                                                &lt;dict&gt;
-                                                                        &lt;!-- mu gives the mean of the normal distribution (in seconds). --&gt;
-                                                                        &lt;key&gt;mu&lt;/key&gt;
-                                                                        &lt;integer&gt;500000&lt;/integer&gt;
-
-                                                                        &lt;!-- and sigma gives its standard deviation. --&gt;
-                                                                        &lt;key&gt;sigma&lt;/key&gt;
-                                                                        &lt;integer&gt;100000&lt;/integer&gt;
-                                                                &lt;/dict&gt;
-                                                        &lt;/dict&gt;
-
-                                                &lt;/dict&gt;
-                                        &lt;/dict&gt;
-
-                                        &lt;!-- Removes events from calendars exceeding a threshold --&gt;
-                                        &lt;dict&gt;
-                                                &lt;key&gt;class&lt;/key&gt;
-                                                &lt;string&gt;contrib.performance.loadtest.profiles.EventCountLimiter&lt;/string&gt;
-
-                                                &lt;key&gt;params&lt;/key&gt;
-                                                &lt;dict&gt;
-                                                        &lt;key&gt;enabled&lt;/key&gt;
-                                                        &lt;false/&gt;
-
-                                                        &lt;!-- Define the interval (in seconds) at which this profile will check
-                                                                for too-large collections. --&gt;
-                                                        &lt;key&gt;interval&lt;/key&gt;
-                                                        &lt;integer&gt;60&lt;/integer&gt;
-
-                                                        &lt;!-- The upper bound. --&gt;
-                                                        &lt;key&gt;eventCountLimit&lt;/key&gt;
-                                                        &lt;integer&gt;10&lt;/integer&gt;
-
-                                                &lt;/dict&gt;
-                                        &lt;/dict&gt;
-
-
-                                        &lt;!-- Shares calendars --&gt;
-                                        &lt;dict&gt;
-                                                &lt;key&gt;class&lt;/key&gt;
-                                                &lt;string&gt;contrib.performance.loadtest.profiles.CalendarSharer&lt;/string&gt;
-
-                                                &lt;key&gt;params&lt;/key&gt;
-                                                &lt;dict&gt;
-                                                        &lt;key&gt;enabled&lt;/key&gt;
-                                                        &lt;true/&gt;
-
-                                                        &lt;!-- Define the interval (in seconds) at which this profile will share calendars. --&gt;
-                                                        &lt;key&gt;interval&lt;/key&gt;
-                                                        &lt;integer&gt;60&lt;/integer&gt;
-
-                                                &lt;/dict&gt;
-                                        &lt;/dict&gt;
-
</del><span class="cx">                                         &lt;!-- This profile invites some number of new attendees to new events. --&gt;
</span><span class="cx">                                         &lt;dict&gt;
</span><span class="cx">                                                 &lt;key&gt;class&lt;/key&gt;
</span><span class="lines">@@ -374,7 +281,7 @@
</span><span class="cx">                                                 &lt;key&gt;params&lt;/key&gt;
</span><span class="cx">                                                 &lt;dict&gt;
</span><span class="cx">                                                         &lt;key&gt;enabled&lt;/key&gt;
</span><del>-                                                        &lt;false/&gt;
</del><ins>+                                                        &lt;true/&gt;
</ins><span class="cx"> 
</span><span class="cx">                                                         &lt;!-- Define the frequency at which new invitations will be sent out. --&gt;
</span><span class="cx">                                                         &lt;key&gt;sendInvitationDistribution&lt;/key&gt;
</span><span class="lines">@@ -385,7 +292,7 @@
</span><span class="cx">                                                                 &lt;dict&gt;
</span><span class="cx">                                                                         &lt;!-- mu gives the mean of the normal distribution (in seconds). --&gt;
</span><span class="cx">                                                                         &lt;key&gt;mu&lt;/key&gt;
</span><del>-                                                                        &lt;integer&gt;10&lt;/integer&gt;
</del><ins>+                                                                        &lt;integer&gt;60&lt;/integer&gt;
</ins><span class="cx"> 
</span><span class="cx">                                                                         &lt;!-- and sigma gives its standard deviation. --&gt;
</span><span class="cx">                                                                         &lt;key&gt;sigma&lt;/key&gt;
</span><span class="lines">@@ -394,12 +301,12 @@
</span><span class="cx">                                                         &lt;/dict&gt;
</span><span class="cx"> 
</span><span class="cx">                                                         &lt;!-- Define the distribution of who will be invited to an event.
</span><del>-
</del><ins>+                                                        
</ins><span class="cx">                                                                 When inviteeClumping is turned on each invitee is based on a sample of
</span><span class="cx">                                                                 users &quot;close to&quot; the organizer based on account index. If the clumping
</span><span class="cx">                                                                 is too &quot;tight&quot; for the requested number of attendees, then invites for
</span><span class="cx">                                                                 those larger numbers will simply fail (the sim will report that situation).
</span><del>-
</del><ins>+                                                                
</ins><span class="cx">                                                                 When inviteeClumping is off invitees will be sampled across an entire
</span><span class="cx">                                                                 range of account indexes. In this case the distribution ought to be a
</span><span class="cx">                                                                 UniformIntegerDistribution with min=0 and max set to the number of accounts.
</span><span class="lines">@@ -423,13 +330,13 @@
</span><span class="cx">                                                         &lt;true/&gt;
</span><span class="cx"> 
</span><span class="cx">                                                         &lt;!-- Define the distribution of how many attendees will be invited to an event.
</span><del>-
</del><ins>+                                                        
</ins><span class="cx">                                                                 LogNormal is the best fit to observed data.
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">                                                                 For LogNormal &quot;mode&quot; is the peak, &quot;mean&quot; is the mean value.        For invites,
</span><span class="cx">                                                                 mode should typically be 1, and mean whatever matches the user behavior.
</span><del>-                                                                Our typical mean is 6.
</del><ins>+                                                                Our typical mean is 6.                                                         
</ins><span class="cx">                                                              --&gt;
</span><span class="cx">                                                         &lt;key&gt;inviteeCountDistribution&lt;/key&gt;
</span><span class="cx">                                                         &lt;dict&gt;
</span><span class="lines">@@ -511,13 +418,13 @@
</span><span class="cx">                                                                                 &lt;!-- Half of all events will be non-recurring --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;none&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;50&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Daily and weekly are pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;daily&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;10&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weekly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;20&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Monthly, yearly, daily &amp; weekly limit not so common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;monthly&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;2&lt;/integer&gt;
</span><span class="lines">@@ -527,7 +434,7 @@
</span><span class="cx">                                                                                 &lt;integer&gt;2&lt;/integer&gt;
</span><span class="cx">                                                                                 &lt;key&gt;weeklylimit&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;5&lt;/integer&gt;
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 &lt;!-- Work days pretty common --&gt;
</span><span class="cx">                                                                                 &lt;key&gt;workdays&lt;/key&gt;
</span><span class="cx">                                                                                 &lt;integer&gt;10&lt;/integer&gt;
</span><span class="lines">@@ -552,7 +459,7 @@
</span><span class="cx">                                                                 accepting it.
</span><span class="cx"> 
</span><span class="cx">                                                                 For LogNormal &quot;mode&quot; is the peak, &quot;median&quot; is the 50% cummulative value
</span><del>-                                                                (i.e., half of the user have accepted by that time).
</del><ins>+                                                                (i.e., half of the user have accepted by that time).                                                                
</ins><span class="cx">                                                         --&gt;
</span><span class="cx">                                                         &lt;key&gt;acceptDelayDistribution&lt;/key&gt;
</span><span class="cx">                                                         &lt;dict&gt;
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestconfigplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/config.plist (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/config.plist        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.plist        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -21,7 +21,7 @@
</span><span class="cx">         &lt;dict&gt;
</span><span class="cx">                 &lt;!-- Identify the server to be load tested. --&gt;
</span><span class="cx">                 &lt;key&gt;server&lt;/key&gt;
</span><del>-                &lt;string&gt;https://localhost:8443&lt;/string&gt;
</del><ins>+                &lt;string&gt;https://127.0.0.1:8443&lt;/string&gt;
</ins><span class="cx"> 
</span><span class="cx">                 &lt;!-- The template URI for doing initial principal lookup on. --&gt;
</span><span class="cx">                 &lt;key&gt;principalPathTemplate&lt;/key&gt;
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx">                         &lt;dict&gt;
</span><span class="cx">                                 &lt;!-- groups gives the total number of groups of clients to introduce. --&gt;
</span><span class="cx">                                 &lt;key&gt;groups&lt;/key&gt;
</span><del>-                                &lt;integer&gt;1&lt;/integer&gt;
</del><ins>+                                &lt;integer&gt;20&lt;/integer&gt;
</ins><span class="cx"> 
</span><span class="cx">                                 &lt;!-- groupSize is the number of clients in each group of clients. It's
</span><span class="cx">                                         really only a &quot;smooth&quot; ramp up if this is pretty small. --&gt;
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">                 &lt;!-- Define some log observers to report on the load test. --&gt;
</span><span class="cx">                 &lt;key&gt;observers&lt;/key&gt;
</span><span class="cx">                 &lt;array&gt;
</span><del>-                        &lt;!-- ReportStatistics generates an end-of-run summary of the HTTP requests
</del><ins>+                        &lt;!-- ReportStatistics generates an end-of-run summary of the HTTP requests 
</ins><span class="cx">                                 made, their timings, and their results. --&gt;
</span><span class="cx">                         &lt;dict&gt;
</span><span class="cx">                                 &lt;key&gt;type&lt;/key&gt;
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">                                         &lt;!-- The thresholds for each request type --&gt;
</span><span class="cx">                                         &lt;key&gt;thresholdsPath&lt;/key&gt;
</span><span class="cx">                                         &lt;string&gt;contrib/performance/loadtest/thresholds.json&lt;/string&gt;
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         &lt;!-- The benchmarks for overall QoS --&gt;
</span><span class="cx">                                         &lt;key&gt;benchmarksPath&lt;/key&gt;
</span><span class="cx">                                         &lt;string&gt;contrib/performance/loadtest/benchmarks.json&lt;/string&gt;
</span><span class="lines">@@ -138,8 +138,8 @@
</span><span class="cx">                                         &lt;real&gt;1.0&lt;/real&gt;
</span><span class="cx">                                 &lt;/dict&gt;
</span><span class="cx">                         &lt;/dict&gt;
</span><del>-
-                        &lt;!-- RequestLogger generates a realtime log of all HTTP requests made
</del><ins>+        
+                        &lt;!-- RequestLogger generates a realtime log of all HTTP requests made 
</ins><span class="cx">                                 during the load test. --&gt;
</span><span class="cx">                         &lt;dict&gt;
</span><span class="cx">                                 &lt;key&gt;type&lt;/key&gt;
</span><span class="lines">@@ -148,9 +148,9 @@
</span><span class="cx">                                 &lt;dict&gt;
</span><span class="cx">                                 &lt;/dict&gt;
</span><span class="cx">                         &lt;/dict&gt;
</span><del>-
-                        &lt;!-- OperationLogger generates an end-of-run summary of the gross operations
-                                performed (logical operations which may span more than one HTTP request,
</del><ins>+        
+                        &lt;!-- OperationLogger generates an end-of-run summary of the gross operations 
+                                performed (logical operations which may span more than one HTTP request, 
</ins><span class="cx">                                 such as inviting an attendee to an event). --&gt;
</span><span class="cx">                         &lt;dict&gt;
</span><span class="cx">                                 &lt;key&gt;type&lt;/key&gt;
</span><span class="lines">@@ -160,11 +160,11 @@
</span><span class="cx">                                         &lt;!-- The thresholds for each operation type --&gt;
</span><span class="cx">                                         &lt;key&gt;thresholdsPath&lt;/key&gt;
</span><span class="cx">                                         &lt;string&gt;contrib/performance/loadtest/thresholds.json&lt;/string&gt;
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         &lt;!-- The % of operations beyond the lag cut-off that constitute a failed test --&gt;
</span><span class="cx">                                         &lt;key&gt;lagCutoff&lt;/key&gt;
</span><span class="cx">                                         &lt;real&gt;1.0&lt;/real&gt;
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         &lt;!-- The % of failures that constitute a failed test --&gt;
</span><span class="cx">                                         &lt;key&gt;failCutoff&lt;/key&gt;
</span><span class="cx">                                         &lt;real&gt;1.0&lt;/real&gt;
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesticalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/ical.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/ical.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/ical.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -18,10 +18,7 @@
</span><span class="cx"> 
</span><span class="cx"> from caldavclientlibrary.protocol.caldav.definitions import caldavxml
</span><span class="cx"> from caldavclientlibrary.protocol.caldav.definitions import csxml
</span><del>-from caldavclientlibrary.protocol.calendarserver.invite import AddInvitees, RemoveInvitee, InviteUser
-from caldavclientlibrary.protocol.calendarserver.notifications import InviteNotification
</del><span class="cx"> from caldavclientlibrary.protocol.url import URL
</span><del>-from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
</del><span class="cx"> from caldavclientlibrary.protocol.webdav.definitions import davxml
</span><span class="cx"> from caldavclientlibrary.protocol.webdav.propfindparser import PropFindParser
</span><span class="cx"> 
</span><span class="lines">@@ -48,27 +45,22 @@
</span><span class="cx"> from twisted.python.util import FancyEqMixin
</span><span class="cx"> from twisted.web.client import Agent, ContentDecoderAgent, GzipDecoder, \
</span><span class="cx">     _DeprecatedToCurrentPolicyForHTTPS
</span><del>-from twisted.web.http import (
-    OK, MULTI_STATUS, CREATED, NO_CONTENT, PRECONDITION_FAILED,
-    MOVED_PERMANENTLY, FORBIDDEN, FOUND, NOT_FOUND
-)
</del><ins>+from twisted.web.http import OK, MULTI_STATUS, CREATED, NO_CONTENT, PRECONDITION_FAILED, MOVED_PERMANENTLY, \
+    FORBIDDEN, FOUND
</ins><span class="cx"> from twisted.web.http_headers import Headers
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav.ical import Component, Property
</span><span class="cx"> 
</span><span class="cx"> from urlparse import urlparse, urlunparse, urlsplit, urljoin
</span><span class="cx"> from uuid import uuid4
</span><del>-from xml.etree.ElementTree import ElementTree, Element, SubElement, QName
</del><ins>+from xml.etree import ElementTree
</ins><span class="cx"> 
</span><del>-from StringIO import StringIO
-
</del><span class="cx"> import json
</span><span class="cx"> import os
</span><span class="cx"> import random
</span><span class="cx"> 
</span><del>-QName.__repr__ = lambda self: '&lt;QName %r&gt;' % (self.text,)
</del><ins>+ElementTree.QName.__repr__ = lambda self: '&lt;QName %r&gt;' % (self.text,)
</ins><span class="cx"> 
</span><del>-
</del><span class="cx"> def loadRequestBody(clientType, label):
</span><span class="cx">     return FilePath(__file__).sibling('request-data').child(clientType).child(label + '.request').getContent()
</span><span class="cx"> 
</span><span class="lines">@@ -255,152 +247,19 @@
</span><span class="cx">                 calendar.changeToken = &quot;&quot;
</span><span class="cx">         return calendar
</span><span class="cx"> 
</span><del>-    @staticmethod
-    def addInviteeXML(uid, summary, readwrite=True):
-        return AddInvitees(None, '/', [uid], readwrite, summary=summary).request_data.text
</del><span class="cx"> 
</span><span class="cx"> 
</span><del>-    @staticmethod
-    def removeInviteeXML(uid):
-        invitee = InviteUser()
-        # Usually an InviteUser is populated through .parseFromUser, but we only care about a uid
-        invitee.user_uid = uid
-        return RemoveInvitee(None, '/', invitee).request_data.text
-
-
-# class Notification(object):
-#     def __init__(self, serializeBasePath, url, etag, body=None):
-#         self.serializeBasePath = serializeBasePath
-#         self.url = url
-#         self.etag = etag
-#         self.body = body
-
-
-#     def serializePath(self):
-#         if self.serializeBasePath:
-#             parentPath = os.path.join(self.serializeBasePath, &quot;notifications&quot;)
-#             if not os.path.exists(parentPath):
-#                 os.makedirs(parentPath)
-#             return os.path.join(parentPath, self.url.split(&quot;/&quot;)[-1])
-#         else:
-#             return None
-
-
-#     def serialize(self):
-#         &quot;&quot;&quot;
-#         Create a dict of the data so we can serialize as JSON.
-#         &quot;&quot;&quot;
-
-#         result = {}
-#         for attr in (&quot;url&quot;, &quot;etag&quot;):
-#             result[attr] = getattr(self, attr)
-#         return result
-
-
-#     @staticmethod
-#     def deserialize(serializeLocation, data):
-#         &quot;&quot;&quot;
-#         Convert dict (deserialized from JSON) into an L{Event}.
-#         &quot;&quot;&quot;
-
-#         event = Notification(serializeLocation, None, None)
-#         for attr in (&quot;url&quot;, &quot;etag&quot;):
-#             setattr(event, attr, u2str(data[attr]))
-#         return event
-
-
-#     @property
-#     def body(self):
-#         &quot;&quot;&quot;
-#         Data always read from disk - never cached in the object.
-#         &quot;&quot;&quot;
-#         path = self.serializePath()
-#         if path and os.path.exists(path):
-#             f = open(path)
-#             content = f.read()
-#             f.close()
-#             return content
-#         else:
-#             return None
-
-
-#     @body.setter
-#     def body(self, content):
-#         &quot;&quot;&quot;
-#         Data always written to disk - never cached on the object.
-#         &quot;&quot;&quot;
-#         path = self.serializePath()
-#         if path:
-#             if content is None:
-#                 os.remove(path)
-#             else:
-#                 f = open(path, &quot;w&quot;)
-#                 f.write(content)
-#                 f.close()
-
-
-#     def removed(self):
-#         &quot;&quot;&quot;
-#         Resource no longer exists on the server - remove associated data.
-#         &quot;&quot;&quot;
-#         path = self.serializePath()
-#         if path and os.path.exists(path):
-#             os.remove(path)
-
-
-class NotificationCollection(object):
-    def __init__(self, url, changeToken):
-        self.url = url
-        self.changeToken = changeToken
-        self.notifications = {}
-        self.name = &quot;notification&quot;
-
-    def serialize(self):
-        &quot;&quot;&quot;
-        Create a dict of the data so we can serialize as JSON.
-        &quot;&quot;&quot;
-
-        result = {}
-        for attr in (&quot;url&quot;, &quot;changeToken&quot;):
-            result[attr] = getattr(self, attr)
-        result[&quot;notifications&quot;] = sorted(self.notifications.keys())
-        return result
-
-
-    @staticmethod
-    def deserialize(data, notifications):
-        &quot;&quot;&quot;
-        Convert dict (deserialized from JSON) into an L{Calendar}.
-        &quot;&quot;&quot;
-
-        coll = NotificationCollection(None, None)
-        for attr in (&quot;url&quot;, &quot;changeToken&quot;):
-            setattr(coll, attr, u2str(data[attr]))
-
-        for notification in data[&quot;notifications&quot;]:
-            url = urljoin(coll.url, notification)
-            if url in notifications:
-                coll.notifications[notification] = notifications[url]
-            else:
-                # Ughh - a notification is missing - force changeToken to empty to trigger full resync
-                coll.changeToken = &quot;&quot;
-        return coll
-
-
-
</del><span class="cx"> class BaseClient(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Base interface for all simulated clients.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    user = None                     # User account details
-    _events = None                  # Cache of events keyed by href
-    _calendars = None               # Cache of calendars keyed by href
-    _notifications = None           # Cache of notifications keyed by href
-    _notificationCollection = None  # Cache of the notification collection
-    started = False                 # Whether or not startup() has been executed
-    _client_type = None             # Type of this client used in logging
-    _client_id = None               # Unique id for the client itself
</del><ins>+    user = None         # User account details
+    _events = None      # Cache of events keyed by href
+    _calendars = None   # Cache of calendars keyed by href
+    started = False     # Whether or not startup() has been executed
+    _client_type = None # Type of this client used in logging
+    _client_id = None   # Unique id for the client itself
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _setEvent(self, href, event):
</span><span class="lines">@@ -422,21 +281,6 @@
</span><span class="cx">         del self._calendars[calendar + '/'].events[basePath]
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def _setNotification(self, href, notification):
-        &quot;&quot;&quot;
-        Cache the provided notification
-        &quot;&quot;&quot;
-        self._notifications[href] = notification
-
-
-    def _removeNotification(self, href):
-        &quot;&quot;&quot;
-        Remove notification from local cache.
-        &quot;&quot;&quot;
-        self._notifications[href].removed()
-        del self._notifications[href]
-
-
</del><span class="cx">     def addEvent(self, href, calendar):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Called when a profile needs to add an event (no scheduling).
</span><span class="lines">@@ -566,8 +410,6 @@
</span><span class="cx">     _POLL_NOTIFICATION_PROPFIND = None
</span><span class="cx">     _POLL_NOTIFICATION_PROPFIND_D1 = None
</span><span class="cx"> 
</span><del>-    _NOTIFICATION_SYNC_REPORT = None
-
</del><span class="cx">     _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = None
</span><span class="cx">     _POST_AVAILABILITY = None
</span><span class="cx"> 
</span><span class="lines">@@ -611,8 +453,6 @@
</span><span class="cx">             calendarHomePollInterval = self.CALENDAR_HOME_POLL_INTERVAL
</span><span class="cx">         self.calendarHomePollInterval = calendarHomePollInterval
</span><span class="cx"> 
</span><del>-        self.calendarHomeHref = None
-
</del><span class="cx">         self.supportPush = supportPush
</span><span class="cx"> 
</span><span class="cx">         self.supportAmpPush = supportAmpPush
</span><span class="lines">@@ -890,10 +730,8 @@
</span><span class="cx">             depth='1',
</span><span class="cx">             method_label=&quot;PROPFIND{home}&quot;,
</span><span class="cx">         )
</span><del>-        calendars, notificationCollection = self._extractCalendars(
-            result, calendarHomeSet
-        )
-        returnValue((calendars, notificationCollection, result,))
</del><ins>+        calendars = self._extractCalendars(result, calendarHomeSet)
+        returnValue((calendars, result,))
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><span class="lines">@@ -939,10 +777,6 @@
</span><span class="cx">         that from the response.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         calendars = []
</span><del>-        notificationCollection = None
-
-        changeTag = davxml.sync_token if self.supportSync else csxml.getctag
-
</del><span class="cx">         for href in results:
</span><span class="cx"> 
</span><span class="cx">             if href == calendarHome:
</span><span class="lines">@@ -976,6 +810,7 @@
</span><span class="cx">                             for comp in nodes[caldavxml.supported_calendar_component_set]:
</span><span class="cx">                                 componentTypes.add(comp.get(&quot;name&quot;).upper())
</span><span class="cx"> 
</span><ins>+                    changeTag = davxml.sync_token if self.supportSync else csxml.getctag
</ins><span class="cx">                     calendars.append(Calendar(
</span><span class="cx">                         nodeType.tag,
</span><span class="cx">                         componentTypes,
</span><span class="lines">@@ -984,16 +819,9 @@
</span><span class="cx">                         textProps.get(changeTag, None),
</span><span class="cx">                     ))
</span><span class="cx">                     break
</span><del>-                elif nodeType.tag == csxml.notification:
-                    textProps = results[href].getTextProperties()
-                    notificationCollection = NotificationCollection(
-                        href,
-                        textProps.get(changeTag, None)
-                    )
</del><ins>+        return calendars
</ins><span class="cx"> 
</span><del>-        return calendars, notificationCollection
</del><span class="cx"> 
</span><del>-
</del><span class="cx">     def _updateCalendar(self, calendar, newToken):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Update the local cached data for a calendar in an appropriate manner.
</span><span class="lines">@@ -1213,7 +1041,6 @@
</span><span class="cx">         try:
</span><span class="cx">             result = yield self._newOperation(&quot;push&quot; if push else &quot;poll&quot;, self._poll(calendarHomeSet, firstTime))
</span><span class="cx">         finally:
</span><del>-            print(&quot;*** BACK FROM NEW OPERATION, result=&quot;, result)
</del><span class="cx">             if result:
</span><span class="cx">                 try:
</span><span class="cx">                     self._checking.remove(calendarHomeSet)
</span><span class="lines">@@ -1223,132 +1050,12 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @inlineCallbacks
</span><del>-    def _updateNotifications(self, oldToken, newToken):
-
-        fullSync = not oldToken
-
-        # Get the list of notificatinon xml resources
-
-        result = yield self._report(
-            self._notificationCollection.url,
-            self._NOTIFICATION_SYNC_REPORT % {'sync-token': oldToken},
-            depth='1',
-            allowedStatus=(MULTI_STATUS, FORBIDDEN,),
-            otherTokens=True,
-            method_label=&quot;REPORT{sync}&quot; if oldToken else &quot;REPORT{sync-init}&quot;,
-        )
-        if result is None:
-            if not fullSync:
-                fullSync = True
-                result = yield self._report(
-                    self._notificationCollection.url,
-                    self._NOTIFICATION_SYNC_REPORT % {'sync-token': ''},
-                    depth='1',
-                    otherTokens=True,
-                    method_label=&quot;REPORT{sync}&quot; if oldToken else &quot;REPORT{sync-init}&quot;,
-                )
-            else:
-                raise IncorrectResponseCode((MULTI_STATUS,), None)
-
-        result, others = result
-
-        # Scan for the sharing invites
-        inviteNotifications = []
-        toDelete = []
-        for responseHref in result:
-            if responseHref == self._notificationCollection.url:
-                continue
-
-            # try:
-            #     etag = result[responseHref].getTextProperties()[davxml.getetag]
-            # except KeyError:
-            #     # XXX Ignore things with no etag?  Seems to be dropbox.
-            #     continue
-
-            toDelete.append(responseHref)
-
-            if result[responseHref].getStatus() / 100 == 2:
-                # Get the notification
-                response = yield self._request(
-                    OK,
-                    'GET',
-                    self.root + responseHref.encode('utf-8'),
-                    method_label=&quot;GET{notification}&quot;,
-                )
-                body = yield readBody(response)
-                node = ElementTree(file=StringIO(body)).getroot()
-                if node.tag == str(csxml.notification):
-                    nurl = URL(url=responseHref)
-                    for child in node.getchildren():
-                        if child.tag == str(csxml.invite_notification):
-                            if child.find(str(csxml.invite_noresponse)) is not None:
-                                inviteNotifications.append(
-                                    InviteNotification().parseFromNotification(
-                                        nurl, child
-                                    )
-                                )
-
-        # Accept the invites
-        for notification in inviteNotifications:
-            # Create an invite-reply
-            &quot;&quot;&quot;
-            &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
-            &lt;C:invite-reply xmlns:C=&quot;http://calendarserver.org/ns/&quot;&gt;
-              &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;urn:x-uid:10000000-0000-0000-0000-000000000002&lt;/A:href&gt;
-              &lt;C:invite-accepted/&gt;
-              &lt;C:hosturl&gt;
-                &lt;A:href xmlns:A=&quot;DAV:&quot;&gt;/calendars/__uids__/10000000-0000-0000-0000-000000000001/A1DDC58B-651E-4B1C-872A-C6588CA09ADB&lt;/A:href&gt;
-              &lt;/C:hosturl&gt;
-              &lt;C:in-reply-to&gt;d2683fa9-7a50-4390-82bb-cbcea5e0fa86&lt;/C:in-reply-to&gt;
-              &lt;C:summary&gt;to share&lt;/C:summary&gt;
-            &lt;/C:invite-reply&gt;
-            &quot;&quot;&quot;
-            reply = Element(csxml.invite_reply)
-            href = SubElement(reply, davxml.href)
-            href.text = notification.user_uid
-            SubElement(reply, csxml.invite_accepted)
-            hosturl = SubElement(reply, csxml.hosturl)
-            href = SubElement(hosturl, davxml.href)
-            href.text = notification.hosturl
-            inReplyTo = SubElement(reply, csxml.in_reply_to)
-            inReplyTo.text = notification.uid
-            summary = SubElement(reply, csxml.summary)
-            summary.text = notification.summary
-
-            xmldoc = BetterElementTree(reply)
-            os = StringIO()
-            xmldoc.writeUTF8(os)
-            # Post to my calendar home
-            response = yield self.postXML(
-                self.calendarHomeHref,
-                os.getvalue(),
-                &quot;POST{invite-accept}&quot;
-            )
-
-        # Delete all the notification resources
-        for responseHref in toDelete:
-            response = yield self._request(
-                (NO_CONTENT, NOT_FOUND),
-                'DELETE',
-                self.root + responseHref.encode('utf-8'),
-                method_label=&quot;DELETE{invite}&quot;,
-            )
-
-        self._notificationCollection.changeToken = newToken
-
-
-
-    @inlineCallbacks
</del><span class="cx">     def _poll(self, calendarHomeSet, firstTime):
</span><del>-        &quot;&quot;&quot;
-        This gets called during a normal poll or in response to a push
-        &quot;&quot;&quot;
-
</del><span class="cx">         if calendarHomeSet in self._checking:
</span><span class="cx">             returnValue(False)
</span><span class="cx">         self._checking.add(calendarHomeSet)
</span><span class="cx"> 
</span><del>-        calendars, notificationCollection, results = yield self._calendarHomePropfind(calendarHomeSet)
</del><ins>+        calendars, results = yield self._calendarHomePropfind(calendarHomeSet)
</ins><span class="cx"> 
</span><span class="cx">         # First time operations
</span><span class="cx">         if firstTime:
</span><span class="lines">@@ -1366,24 +1073,12 @@
</span><span class="cx">                 # Calendar changed - reload it
</span><span class="cx">                 yield self._updateCalendar(self._calendars[cal.url], newToken)
</span><span class="cx"> 
</span><del>-        if notificationCollection is not None:
-            if self._notificationCollection:
-                oldToken = self._notificationCollection.changeToken
-            else:
-                oldToken = &quot;&quot;
-            self._notificationCollection = notificationCollection
-            newToken = notificationCollection.changeToken
-            yield self._updateNotifications(oldToken, newToken)
</del><ins>+        # When there is no sync REPORT, clients have to do a full PROPFIND
+        # on the notification collection because there is no ctag
+        if self.notificationURL is not None and not self.supportSync:
+            yield self._notificationPropfind(self.notificationURL)
+            yield self._notificationChangesPropfind(self.notificationURL)
</ins><span class="cx"> 
</span><del>-        # FIXME: isn't sync report the new norm, and therefore we can remove
-        # the following?
-
-        # # When there is no sync REPORT, clients have to do a full PROPFIND
-        # # on the notification collection because there is no ctag
-        # if self.notificationURL is not None and not self.supportSync:
-        #     yield self._notificationPropfind(self.notificationURL)
-        #     yield self._notificationChangesPropfind(self.notificationURL)
-
</del><span class="cx">         # One time delegate expansion
</span><span class="cx">         if firstTime:
</span><span class="cx">             yield self._pollFirstTime2()
</span><span class="lines">@@ -1570,8 +1265,6 @@
</span><span class="cx">             calendarHome = hrefs[caldavxml.calendar_home_set].toString()
</span><span class="cx">             if calendarHome is None:
</span><span class="cx">                 raise MissingCalendarHome
</span><del>-            else:
-                self.calendarHomeHref = calendarHome
</del><span class="cx">             yield self._checkCalendarsForEvents(calendarHome, firstTime=True)
</span><span class="cx">             returnValue(calendarHome)
</span><span class="cx">         calendarHome = yield self._newOperation(&quot;startup: %s&quot; % (self.title,), startup())
</span><span class="lines">@@ -1636,7 +1329,6 @@
</span><span class="cx">             &quot;principalURL&quot;: self.principalURL,
</span><span class="cx">             &quot;calendars&quot;: [calendar.serialize() for calendar in sorted(self._calendars.values(), key=lambda x:x.name)],
</span><span class="cx">             &quot;events&quot;: [event.serialize() for event in sorted(self._events.values(), key=lambda x:x.url)],
</span><del>-            &quot;notificationCollection&quot; : self._notificationCollection.serialize(),
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         # Write JSON data
</span><span class="lines">@@ -1760,11 +1452,18 @@
</span><span class="cx">             elif attendee.hasParameter('EMAIL'):
</span><span class="cx">                 email = attendee.parameterValue('EMAIL').encode(&quot;utf-8&quot;)
</span><span class="cx"> 
</span><del>-            search = &quot;&lt;C:search-token&gt;{}&lt;/C:search-token&gt;&quot;.format(prefix)
-            body = self._CALENDARSERVER_PRINCIPAL_SEARCH_REPORT.format(
-                context=&quot;attendee&quot;, searchTokens=search)
</del><ins>+            # First try to discover some names to supply to the
+            # auto-completion
</ins><span class="cx">             yield self._report(
</span><del>-                '/principals/', body, depth=None, method_label=&quot;REPORT{cpsearch}&quot;
</del><ins>+                self.principalCollection,
+                self._USER_LIST_PRINCIPAL_PROPERTY_SEARCH % {
+                    'displayname': prefix,
+                    'email': prefix,
+                    'firstname': prefix,
+                    'lastname': prefix,
+                },
+                depth=None,
+                method_label=&quot;REPORT{psearch}&quot;,
</ins><span class="cx">             )
</span><span class="cx"> 
</span><span class="cx">             # Now learn about the attendee's availability
</span><span class="lines">@@ -1776,7 +1475,6 @@
</span><span class="cx">             )
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def changeEventAttendee(self, href, oldAttendee, newAttendee):
</span><span class="cx">         event = self._events[href]
</span><span class="lines">@@ -1824,7 +1522,7 @@
</span><span class="cx">         self._removeEvent(href)
</span><span class="cx"> 
</span><span class="cx">         response = yield self._request(
</span><del>-            (NO_CONTENT, NOT_FOUND),
</del><ins>+            NO_CONTENT,
</ins><span class="cx">             'DELETE',
</span><span class="cx">             self.root + href.encode('utf-8'),
</span><span class="cx">             method_label=&quot;DELETE{event}&quot;,
</span><span class="lines">@@ -2004,42 +1702,7 @@
</span><span class="cx">         returnValue(body)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    @inlineCallbacks
-    def postAttachment(self, href, content):
-        url = self.root + &quot;{0}?{1}&quot;.format(href, &quot;action=attachment-add&quot;)
-        filename = 'file-{}.txt'.format(len(content))
-        headers = Headers({
-            'Content-Disposition': ['attachment; filename=&quot;{}&quot;'.format(filename)]
-        })
-        response = yield self._request(
-            CREATED,
-            'POST',
-            url,
-            headers=headers,
-            body=StringProducer(content),
-            method_label=&quot;POST{attach}&quot;
-        )
-        body = yield readBody(response)
-        returnValue(body)
</del><span class="cx"> 
</span><del>-
-    @inlineCallbacks
-    def postXML(self, href, content, label):
-        headers = Headers({
-            'content-type': ['text/xml']
-        })
-        response = yield self._request(
-            (OK, CREATED, MULTI_STATUS),
-            'POST',
-            self.root + href,
-            headers=headers,
-            body=StringProducer(content),
-            method_label=label
-        )
-        body = yield readBody(response)
-        returnValue(body)
-
-
</del><span class="cx"> class OS_X_10_6(BaseAppleClient):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Implementation of the OS X 10.6 iCal network behavior.
</span><span class="lines">@@ -2205,99 +1868,7 @@
</span><span class="cx">         returnValue(principal)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-class OS_X_10_11(BaseAppleClient):
-    &quot;&quot;&quot;
-    Implementation of the OS X 10.11 Calendar.app network behavior.
-    &quot;&quot;&quot;
</del><span class="cx"> 
</span><del>-    _client_type = &quot;OS X 10.11&quot;
-
-    USER_AGENT = &quot;Mac+OS+X/10.11 (15A283) CalendarAgent/361&quot;
-
-    # The default interval, used if none is specified in external
-    # configuration.  This is also the actual value used by El
-    # Capital Calendar.app.
-    CALENDAR_HOME_POLL_INTERVAL = 15 * 60  # in seconds
-
-    # The maximum number of resources to retrieve in a single multiget
-    MULTIGET_BATCH_SIZE = 50
-
-    # Override and turn on if client supports Sync REPORT
-    _SYNC_REPORT = True
-
-    # Override and turn off if client does not support attendee lookups
-    _ATTENDEE_LOOKUPS = True
-
-    # Request body data
-    _LOAD_PATH = &quot;OS_X_10_11&quot;
-
-    _STARTUP_WELL_KNOWN = loadRequestBody(_LOAD_PATH, 'startup_well_known_propfind')
-    _STARTUP_PRINCIPAL_PROPFIND_INITIAL = loadRequestBody(_LOAD_PATH, 'startup_principal_initial_propfind')
-    _STARTUP_PRINCIPAL_PROPFIND = loadRequestBody(_LOAD_PATH, 'startup_principal_propfind')
-    _STARTUP_PRINCIPALS_REPORT = loadRequestBody(_LOAD_PATH, 'startup_principals_report')
-    _STARTUP_PRINCIPAL_EXPAND = loadRequestBody(_LOAD_PATH, 'startup_principal_expand')
-
-    _STARTUP_CREATE_CALENDAR = loadRequestBody(_LOAD_PATH, 'startup_create_calendar')
-    _STARTUP_PROPPATCH_CALENDAR_COLOR = loadRequestBody(_LOAD_PATH, 'startup_calendar_color_proppatch')
-    # _STARTUP_PROPPATCH_CALENDAR_NAME = loadRequestBody(_LOAD_PATH, 'startup_calendar_displayname_proppatch')
-    _STARTUP_PROPPATCH_CALENDAR_ORDER = loadRequestBody(_LOAD_PATH, 'startup_calendar_order_proppatch')
-    _STARTUP_PROPPATCH_CALENDAR_TIMEZONE = loadRequestBody(_LOAD_PATH, 'startup_calendar_timezone_proppatch')
-
-    _POLL_CALENDARHOME_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendarhome_depth1_propfind')
-    _POLL_CALENDAR_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
-    _POLL_CALENDAR_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_calendar_depth1_propfind')
-    _POLL_CALENDAR_MULTIGET_REPORT = loadRequestBody('OS_X_10_7', 'poll_calendar_multiget')
-    _POLL_CALENDAR_MULTIGET_REPORT_HREF = loadRequestBody('OS_X_10_7', 'poll_calendar_multiget_hrefs')
-    _POLL_CALENDAR_SYNC_REPORT = loadRequestBody('OS_X_10_7', 'poll_calendar_sync')
-    _POLL_NOTIFICATION_PROPFIND = loadRequestBody(_LOAD_PATH, 'poll_calendar_propfind')
-    _POLL_NOTIFICATION_PROPFIND_D1 = loadRequestBody(_LOAD_PATH, 'poll_notification_depth1_propfind')
-
-    _NOTIFICATION_SYNC_REPORT = loadRequestBody(_LOAD_PATH, 'notification_sync')
-
-    _USER_LIST_PRINCIPAL_PROPERTY_SEARCH = loadRequestBody('OS_X_10_7', 'user_list_principal_property_search')
-    _POST_AVAILABILITY = loadRequestBody('OS_X_10_7', 'post_availability')
-
-    _CALENDARSERVER_PRINCIPAL_SEARCH_REPORT = loadRequestBody(_LOAD_PATH, 'principal_search_report')
-
-
-    def _addDefaultHeaders(self, headers):
-        &quot;&quot;&quot;
-        Add the clients default set of headers to ones being used in a request.
-        Default is to add User-Agent, sub-classes should override to add other
-        client specific things, Accept etc.
-        &quot;&quot;&quot;
-
-        super(OS_X_10_11, self)._addDefaultHeaders(headers)
-        headers.setRawHeaders('Accept', ['*/*'])
-        headers.setRawHeaders('Accept-Language', ['en-us'])
-        headers.setRawHeaders('Accept-Encoding', ['gzip,deflate'])
-        headers.setRawHeaders('Connection', ['keep-alive'])
-
-
-    @inlineCallbacks
-    def startup(self):
-        # Try to read data from disk - if it succeeds self.principalURL will be set
-        self.deserialize()
-
-        if self.principalURL is None:
-            # PROPFIND well-known with redirect
-            response = yield self._startupPropfindWellKnown()
-            hrefs = response.getHrefProperties()
-            if davxml.current_user_principal in hrefs:
-                self.principalURL = hrefs[davxml.current_user_principal].toString()
-            elif davxml.principal_URL in hrefs:
-                self.principalURL = hrefs[davxml.principal_URL].toString()
-            else:
-                # PROPFIND principal path to retrieve actual principal-URL
-                response = yield self._principalPropfindInitial(self.record.uid)
-                hrefs = response.getHrefProperties()
-                self.principalURL = hrefs[davxml.principal_URL].toString()
-
-        # Using the actual principal URL, retrieve principal information
-        principal = yield self._extractPrincipalDetails()
-        returnValue(principal)
-
-
</del><span class="cx"> class iOS_5(BaseAppleClient):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Implementation of the iOS 5 network behavior.
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestpopulationpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/population.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -162,11 +162,10 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> class CalendarClientSimulator(object):
</span><del>-    def __init__(self, records, populator, random, parameters, reactor, server,
</del><ins>+    def __init__(self, records, populator, parameters, reactor, server,
</ins><span class="cx">                  principalPathTemplate, serializationPath, workerIndex=0, workerCount=1):
</span><span class="cx">         self._records = records
</span><span class="cx">         self.populator = populator
</span><del>-        self._random = random
</del><span class="cx">         self.reactor = reactor
</span><span class="cx">         self.server = server
</span><span class="cx">         self.principalPathTemplate = principalPathTemplate
</span><span class="lines">@@ -185,31 +184,6 @@
</span><span class="cx">         return self._records[index]
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def getRandomUserRecord(self, besides=None):
-        count = len(self._records)
-
-        if count == 0:
-            # No records!
-            return None
-
-        if count == 1 and besides == 0:
-            # There is only one item and caller doesn't want it!
-            return None
-
-        for i in xrange(100):
-            # Try to find one that is not &quot;besides&quot;
-            n = self._random.randint(0, count - 1)
-            if besides != n:
-                # Got it.
-                break
-        else:
-            # Give up
-            return None
-        print(&quot;SELECTION, besides=&quot;, besides, &quot;count=&quot;, count, &quot;n=&quot;, n)
-        return self._records[n]
-
-
-
</del><span class="cx">     def _nextUserNumber(self):
</span><span class="cx">         result = self._user
</span><span class="cx">         self._user += 1
</span><span class="lines">@@ -664,7 +638,7 @@
</span><span class="cx">     parameters.addClient(
</span><span class="cx">         1, ClientType(OS_X_10_6, [Eventer, Inviter, Accepter]))
</span><span class="cx">     simulator = CalendarClientSimulator(
</span><del>-        populator, r, parameters, reactor, '127.0.0.1', 8008)
</del><ins>+        populator, parameters, reactor, '127.0.0.1', 8008)
</ins><span class="cx"> 
</span><span class="cx">     arrivalPolicy = SmoothRampUp(groups=10, groupSize=1, interval=3)
</span><span class="cx">     arrivalPolicy.run(reactor, simulator)
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestprofilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> from twisted.python import context
</span><span class="cx"> from twisted.python.log import msg
</span><span class="cx"> from twisted.python.failure import Failure
</span><del>-from twisted.internet.defer import Deferred, succeed, fail, inlineCallbacks, returnValue
</del><ins>+from twisted.internet.defer import Deferred, succeed, fail
</ins><span class="cx"> from twisted.internet.task import LoopingCall
</span><span class="cx"> from twisted.web.http import PRECONDITION_FAILED
</span><span class="cx"> 
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> from contrib.performance.stats import NearFutureDistribution, NormalDistribution, UniformDiscreteDistribution, mean, median
</span><span class="cx"> from contrib.performance.stats import LogNormalDistribution, RecurrenceDistribution
</span><span class="cx"> from contrib.performance.loadtest.logger import SummarizingMixin
</span><del>-from contrib.performance.loadtest.ical import Calendar, IncorrectResponseCode
</del><ins>+from contrib.performance.loadtest.ical import IncorrectResponseCode
</ins><span class="cx"> 
</span><span class="cx"> from pycalendar.datetime import DateTime
</span><span class="cx"> from pycalendar.duration import Duration
</span><span class="lines">@@ -78,46 +78,9 @@
</span><span class="cx">             cal
</span><span class="cx">             for cal
</span><span class="cx">             in self._client._calendars.itervalues()
</span><del>-            if cal.resourceType == calendarType and componentType in cal.componentTypes
-        ]
</del><ins>+            if cal.resourceType == calendarType and componentType in cal.componentTypes]
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-    def _getRandomCalendarOfType(self, componentType):
-        &quot;&quot;&quot;
-        Return a random L{Calendar} object from the current user
-        or C{None} if there are no calendars to work with
-        &quot;&quot;&quot;
-        calendars = self._calendarsOfType(caldavxml.calendar, componentType)
-        if not calendars:
-            return None
-        # Choose a random calendar
-        calendar = self.random.choice(calendars)
-        return calendar
-
-
-    def _getRandomEventOfType(self, componentType):
-        &quot;&quot;&quot;
-        Return a random L{Event} object from the current user
-        or C{None} if there are no events to work with
-        &quot;&quot;&quot;
-        calendars = self._calendarsOfType(caldavxml.calendar, componentType)
-        while calendars:
-            calendar = self.random.choice(calendars)
-            calendars.remove(calendar)
-            if not calendar.events:
-                continue
-
-            events = calendar.events.keys()
-            while events:
-                href = self.random.choice(events)
-                events.remove(href)
-                event = calendar.events[href]
-                if not event.component:
-                    continue
-                return event
-        return None
-
-
</del><span class="cx">     def _isSelfAttendee(self, attendee):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Try to match one of the attendee's identifiers against one of
</span><span class="lines">@@ -682,191 +645,38 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _addEvent(self):
</span><del>-        # Don't perform any operations until the client is up and running
</del><span class="cx">         if not self._client.started:
</span><span class="cx">             return succeed(None)
</span><span class="cx"> 
</span><del>-        calendar = self._getRandomCalendarOfType('VEVENT')
</del><ins>+        calendars = self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;)
</ins><span class="cx"> 
</span><del>-        # Copy the template event and fill in some of its fields
-        # to make a new event to create on the calendar.
-        vcalendar = self._eventTemplate.duplicate()
-        vevent = vcalendar.mainComponent()
-        uid = str(uuid4())
-        dtstart = self._eventStartDistribution.sample()
-        dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
-        vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
-        vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
-        vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
-        vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
-        vevent.replaceProperty(Property(&quot;UID&quot;, uid))
</del><ins>+        while calendars:
+            calendar = self.random.choice(calendars)
+            calendars.remove(calendar)
</ins><span class="cx"> 
</span><del>-        rrule = self._recurrenceDistribution.sample()
-        if rrule is not None:
-            vevent.addProperty(Property(None, None, None, pycalendar=rrule))
</del><ins>+            # Copy the template event and fill in some of its fields
+            # to make a new event to create on the calendar.
+            vcalendar = self._eventTemplate.duplicate()
+            vevent = vcalendar.mainComponent()
+            uid = str(uuid4())
+            dtstart = self._eventStartDistribution.sample()
+            dtend = dtstart + Duration(seconds=self._eventDurationDistribution.sample())
+            vevent.replaceProperty(Property(&quot;CREATED&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
+            vevent.replaceProperty(Property(&quot;DTSTART&quot;, dtstart))
+            vevent.replaceProperty(Property(&quot;DTEND&quot;, dtend))
+            vevent.replaceProperty(Property(&quot;UID&quot;, uid))
</ins><span class="cx"> 
</span><del>-        href = '%s%s.ics' % (calendar.url, uid)
-        d = self._client.addEvent(href, vcalendar)
-        return self._newOperation(&quot;create&quot;, d)
</del><ins>+            rrule = self._recurrenceDistribution.sample()
+            if rrule is not None:
+                vevent.addProperty(Property(None, None, None, pycalendar=rrule))
</ins><span class="cx"> 
</span><ins>+            href = '%s%s.ics' % (calendar.url, uid)
+            d = self._client.addEvent(href, vcalendar)
+            return self._newOperation(&quot;create&quot;, d)
</ins><span class="cx"> 
</span><del>-class EventUpdaterBase(ProfileBase):
</del><span class="cx"> 
</span><del>-    @inlineCallbacks
-    def action(self):
-        # Don't perform any operations until the client is up and running
-        if not self._client.started:
-            returnValue(None)
</del><span class="cx"> 
</span><del>-        event = self._getRandomEventOfType('VEVENT')
-        if not event:
-            returnValue(None)
-        component = event.component
-        vevent = component.mainComponent()
-
-        label = yield self.modifyEvent(event.url, vevent)
-        vevent.replaceProperty(Property(&quot;DTSTAMP&quot;, DateTime.getNowUTC()))
-
-        event.component = component
-        yield self._newOperation(
-            label,
-            self._client.changeEvent(event.url)
-        )
-
-
-    def run(self):
-        self._call = LoopingCall(self.action)
-        self._call.clock = self._reactor
-        return self._call.start(self._interval)
-
-
-    def modifyEvent(self, href, vevent):
-        &quot;&quot;&quot;Overriden by subclasses&quot;&quot;&quot;
-        pass
-
-
-class TitleChanger(EventUpdaterBase):
-
-    def setParameters(
-        self,
-        enabled=True,
-        interval=60,
-        titleLengthDistribution=NormalDistribution(10, 2)
-    ):
-        self.enabled = enabled
-        self._interval = interval
-        self._titleLength = titleLengthDistribution
-
-    def modifyEvent(self, _ignore_href, vevent):
-        length = max(5, int(self._titleLength.sample()))
-        vevent.replaceProperty(Property(&quot;SUMMARY&quot;, &quot;Event&quot; + &quot;.&quot; * (length - 5)))
-        return succeed(&quot;update{title}&quot;)
-
-
-class Attacher(EventUpdaterBase):
-
-    def setParameters(
-        self,
-        enabled=True,
-        interval=60,
-        fileSizeDistribution=NormalDistribution(1024, 1),
-    ):
-        self.enabled = enabled
-        self._interval = interval
-        self._fileSize = fileSizeDistribution
-
-    @inlineCallbacks
-    def modifyEvent(self, href, vevent):
-        fileSize = int(self._fileSize.sample())
-        yield self._client.postAttachment(href, 'x' * fileSize)
-        returnValue(&quot;attach{files}&quot;)
-
-
-class EventCountLimiter(EventUpdaterBase):
-    &quot;&quot;&quot;
-    Examines the number of events in each calendar collection, and when that
-    count exceeds eventCountLimit, events are randomly removed until the count
-    falls back to the limit.
-    &quot;&quot;&quot;
-
-    def setParameters(
-        self,
-        enabled=True,
-        interval=60,
-        eventCountLimit=1000
-    ):
-        self.enabled = enabled
-        self._interval = interval
-        self._limit = eventCountLimit
-
-    @inlineCallbacks
-    def action(self):
-        # Don't perform any operations until the client is up and running
-        if not self._client.started:
-            returnValue(None)
-
-        for calendar in self._calendarsOfType(caldavxml.calendar, &quot;VEVENT&quot;):
-            while len(calendar.events) &gt; self._limit:
-                event = calendar.events[self.random.choice(calendar.events.keys())]
-                yield self._client.deleteEvent(event.url)
-
-
-
-class CalendarSharer(ProfileBase):
-    &quot;&quot;&quot;
-    A Calendar user who shares and un-shares other users to calendars.
-    &quot;&quot;&quot;
-    def setParameters(
-        self,
-        enabled=True,
-        interval=60
-    ):
-        self.enabled = enabled
-        self._interval = interval
-
-
-    def run(self):
-        self._call = LoopingCall(self.action)
-        self._call.clock = self._reactor
-        return self._call.start(self._interval)
-
-
-    @inlineCallbacks
-    def action(self):
-        # Don't perform any operations until the client is up and running
-        if not self._client.started:
-            returnValue(None)
-
-        yield self.shareCalendar()
-
-
-    @inlineCallbacks
-    def shareCalendar(self):
-
-        # pick a calendar
-        calendar = self._getRandomCalendarOfType('VEVENT')
-        if not calendar:
-            returnValue(None)
-
-        # pick a random sharee
-        shareeRecord = self._sim.getRandomUserRecord(besides=self._number)
-        if shareeRecord is None:
-            returnValue(None)
-
-        # POST the sharing invite
-        mailto = &quot;mailto:{}&quot;.format(shareeRecord.email)
-        body = Calendar.addInviteeXML(mailto, calendar.name, readwrite=True)
-        yield self._client.postXML(
-            calendar.url,
-            body,
-            label=&quot;POST{share-calendar}&quot;
-        )
-
-
-
-# Is the purpose of this profile &quot;EventUpdater&quot; simply to keep updating the same
-# resource over and over?
-
</del><span class="cx"> class EventUpdater(ProfileBase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A Calendar user who creates a new event, and then updates its alarm.
</span><span class="lines">@@ -931,7 +741,6 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _initEvent(self):
</span><del>-        # Don't perform any operations until the client is up and running
</del><span class="cx">         if not self._client.started:
</span><span class="cx">             return succeed(None)
</span><span class="cx"> 
</span><span class="lines">@@ -1031,7 +840,6 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _addTask(self):
</span><del>-        # Don't perform any operations until the client is up and running
</del><span class="cx">         if not self._client.started:
</span><span class="cx">             return succeed(None)
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestsimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/sim.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/sim.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/sim.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -285,8 +285,7 @@
</span><span class="cx">             if 'clientDataSerialization' in config:
</span><span class="cx">                 serializationPath = config['clientDataSerialization']['Path']
</span><span class="cx">                 if not config['clientDataSerialization']['UseOldData']:
</span><del>-                    if isdir(serializationPath):
-                        shutil.rmtree(serializationPath)
</del><ins>+                    shutil.rmtree(serializationPath)
</ins><span class="cx">                 serializationPath = config['clientDataSerialization']['Path']
</span><span class="cx">                 if not isdir(serializationPath):
</span><span class="cx">                     try:
</span><span class="lines">@@ -413,7 +412,6 @@
</span><span class="cx">         return CalendarClientSimulator(
</span><span class="cx">             self.records,
</span><span class="cx">             populator,
</span><del>-            Random(),
</del><span class="cx">             self.parameters,
</span><span class="cx">             self.reactor,
</span><span class="cx">             self.server,
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesttest_profilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_profiles.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -40,38 +40,38 @@
</span><span class="cx"> import os
</span><span class="cx"> 
</span><span class="cx"> SIMPLE_EVENT = &quot;&quot;&quot;\
</span><del>-BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//Apple Inc.//iCal 4.0.3//EN
-CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:America/New_York
-BEGIN:DAYLIGHT
-TZOFFSETFROM:-0500
-RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
-DTSTART:20070311T020000
-TZNAME:EDT
-TZOFFSETTO:-0400
-END:DAYLIGHT
-BEGIN:STANDARD
-TZOFFSETFROM:-0400
-RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
-DTSTART:20071104T020000
-TZNAME:EST
-TZOFFSETTO:-0500
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-CREATED:20101018T155431Z
-UID:C98AD237-55AD-4F7D-9009-0D355D835822
-DTEND;TZID=America/New_York:20101021T130000
-TRANSP:OPAQUE
-SUMMARY:Simple event
-DTSTART;TZID=America/New_York:20101021T120000
-DTSTAMP:20101018T155438Z
-SEQUENCE:2
-END:VEVENT
-END:VCALENDAR
</del><ins>+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Apple Inc.//iCal 4.0.3//EN
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:America/New_York
+BEGIN:DAYLIGHT
+TZOFFSETFROM:-0500
+RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
+DTSTART:20070311T020000
+TZNAME:EDT
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:-0400
+RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
+DTSTART:20071104T020000
+TZNAME:EST
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20101018T155431Z
+UID:C98AD237-55AD-4F7D-9009-0D355D835822
+DTEND;TZID=America/New_York:20101021T130000
+TRANSP:OPAQUE
+SUMMARY:Simple event
+DTSTART;TZID=America/New_York:20101021T120000
+DTSTAMP:20101018T155438Z
+SEQUENCE:2
+END:VEVENT
+END:VCALENDAR
</ins><span class="cx"> &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx"> INVITED_EVENT = &quot;&quot;&quot;\
</span><span class="lines">@@ -347,7 +347,7 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def setUp(self):
</span><span class="cx">         self.sim = CalendarClientSimulator(
</span><del>-            AnyUser(), Populator(None), None, None, None, None, None, None)
</del><ins>+            AnyUser(), Populator(None), None, None, None, None, None)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _simpleAccount(self, userNumber, eventText):
</span><span class="lines">@@ -546,7 +546,7 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def setUp(self):
</span><span class="cx">         self.sim = CalendarClientSimulator(
</span><del>-            AnyUser(), Populator(None), None, None, None, None, None, None)
</del><ins>+            AnyUser(), Populator(None), None, None, None, None, None)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def _simpleAccount(self, userNumber, eventText):
</span><span class="lines">@@ -716,7 +716,7 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def setUp(self):
</span><span class="cx">         self.sim = CalendarClientSimulator(
</span><del>-            AnyUser(), Populator(None), None, None, None, None, None, None)
</del><ins>+            AnyUser(), Populator(None), None, None, None, None, None)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_enabled(self):
</span><span class="lines">@@ -983,7 +983,7 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     def setUp(self):
</span><span class="cx">         self.sim = CalendarClientSimulator(
</span><del>-            AnyUser(), Populator(None), None, None, None, None, None, None)
</del><ins>+            AnyUser(), Populator(None), None, None, None, None, None)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def test_enabled(self):
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtesttest_simpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/test_sim.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/test_sim.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/contrib/performance/loadtest/test_sim.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         calsim = CalendarClientSimulator(
</span><span class="cx">             [self._user('alice'), self._user('bob'), self._user('carol')],
</span><del>-            Populator(None), None, None, None, 'http://example.org:1234/', None, None)
</del><ins>+            Populator(None), None, None, 'http://example.org:1234/', None, None)
</ins><span class="cx">         users = sorted([
</span><span class="cx">             calsim._createUser(0)[0],
</span><span class="cx">             calsim._createUser(1)[0],
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         calsim = CalendarClientSimulator(
</span><span class="cx">             [self._user('alice')],
</span><del>-            Populator(None), None, None, None, 'http://example.org:1234/', None, None)
</del><ins>+            Populator(None), None, None, 'http://example.org:1234/', None, None)
</ins><span class="cx">         user, auth = calsim._createUser(0)
</span><span class="cx">         self.assertEqual(
</span><span class="cx">             auth['basic'].passwd.find_user_password('Test Realm', 'http://example.org:1234/')[1],
</span><span class="lines">@@ -182,7 +182,7 @@
</span><span class="cx">             [ProfileType(BrokenProfile, {'runResult': profileRunResult})])
</span><span class="cx">         )
</span><span class="cx">         sim = CalendarClientSimulator(
</span><del>-            [self._user('alice')], Populator(None), None, params, None, 'http://example.com:1234/', None, None)
</del><ins>+            [self._user('alice')], Populator(None), params, None, 'http://example.com:1234/', None, None)
</ins><span class="cx">         sim.add(1, 1)
</span><span class="cx">         sim.stop()
</span><span class="cx">         clientRunResult.errback(RuntimeError(&quot;Some fictional client problem&quot;))
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py (15165 => 15166)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/stdconfig.py        2015-10-05 21:18:27 UTC (rev 15165)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py        2015-10-05 21:24:18 UTC (rev 15166)
</span><span class="lines">@@ -85,12 +85,8 @@
</span><span class="cx">             &quot;fullNames&quot;: [&quot;cn&quot;, ],
</span><span class="cx">             &quot;emailAddresses&quot;: [&quot;mail&quot;, ],
</span><span class="cx">             &quot;memberDNs&quot;: [&quot;uniqueMember&quot;, ],
</span><del>-            &quot;hasCalendars&quot;: [],
-            &quot;autoScheduleMode&quot;: [],
-            &quot;autoAcceptGroup&quot;: [],
</del><span class="cx">             &quot;readWriteProxy&quot;: [&quot;icsContact&quot;, ],
</span><span class="cx">             &quot;readOnlyProxy&quot;: [&quot;icsSecondaryOwners&quot;, ],
</span><del>-            &quot;serviceNodeUID&quot;: [],
</del><span class="cx">         },
</span><span class="cx">         &quot;extraFilters&quot;: {
</span><span class="cx">             &quot;users&quot;: &quot;&quot;,
</span></span></pre>
</div>
</div>

</body>
</html>