<!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 {"status" : "OK"}
</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"> -->
</span><span class="cx">
</span><span class="cx"> <key>UserName</key>
</span><del>- <string>_calendar</string>
</del><ins>+ <string>calendar</string>
</ins><span class="cx">
</span><span class="cx"> <key>GroupName</key>
</span><del>- <string>_calendar</string>
</del><ins>+ <string>calendar</string>
</ins><span class="cx">
</span><span class="cx"> <key>ProcessType</key>
</span><span class="cx"> <string>Combined</string>
</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"> <key>AccountingCategories</key>
</span><span class="cx"> <dict>
</span><span class="cx"> <key>HTTP</key>
</span><del>- <true/>
</del><ins>+ <false/>
</ins><span class="cx"> <key>iTIP</key>
</span><span class="cx"> <false/>
</span><span class="cx"> <key>iTIP-VFREEBUSY</key>
</span><span class="lines">@@ -897,16 +897,12 @@
</span><span class="cx"> <!-- Support for Postgres -->
</span><span class="cx"> <key>Postgres</key>
</span><span class="cx"> <dict>
</span><del>- <key>ListenAddresses</key>
- <array>
- <string>127.0.0.1</string>
- </array>
</del><span class="cx"> <key>Options</key>
</span><span class="cx"> <array>
</span><del>- <!-- Optional extra logging for posgres -->
- <!-- <string>-c log_lock_waits=TRUE</string> -->
- <!-- <string>-c log_statement=all</string> -->
- <!-- <string>-c log_line_prefix='%t [%p]: [%l] '</string> -->
</del><ins>+         <!-- Optional extra logging for posgres -->
+         <!-- <string>-c log_lock_waits=TRUE</string> -->
+         <!-- <string>-c log_statement=all</string> -->
+         <!-- <string>-c log_line_prefix='%t [%p]: [%l] '</string> -->
</ins><span class="cx"> </array>
</span><span class="cx"> </dict>
</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">                                 <!-- Here is a OS X client simulator. -->
</span><span class="cx">                                 <key>software</key>
</span><del>-                                <string>contrib.performance.loadtest.ical.OS_X_10_11</string>
</del><ins>+                                <string>contrib.performance.loadtest.ical.OS_X_10_7</string>
</ins><span class="cx">
</span><del>-                                <!-- Arguments to use to initialize the OS_X_10_11 instance. -->
</del><ins>+                                <!-- Arguments to use to initialize the OS_X_10_7 instance. -->
</ins><span class="cx">                                 <key>params</key>
</span><span class="cx">                                 <dict>
</span><span class="cx">                                         <!-- Name that appears in logs. -->
</span><span class="cx">                                         <key>title</key>
</span><del>-                                        <string>10.11</string>
-
-                                        <!-- OS_X_10_11 can poll the calendar home at some interval. This is
</del><ins>+                                        <string>10.7</string>
+        
+                                        <!-- OS_X_10_7 can poll the calendar home at some interval. This is
</ins><span class="cx">                                                 in seconds. -->
</span><span class="cx">                                         <key>calendarHomePollInterval</key>
</span><span class="cx">                                         <integer>30</integer>
</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. -->
</span><span class="cx">                                         <key>supportPush</key>
</span><del>-                                        <true/>
</del><ins>+                                        <false />
</ins><span class="cx">
</span><span class="cx">                                         <key>supportAmpPush</key>
</span><span class="cx">                                         <true/>
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">                                                 <key>params</key>
</span><span class="cx">                                                 <dict>
</span><span class="cx">                                                         <key>enabled</key>
</span><del>-                                                        <false/>
</del><ins>+                                                        <true/>
</ins><span class="cx">
</span><span class="cx">                                                         <!-- Define the interval (in seconds) at which this profile will use
</span><span class="cx">                                                                 its client to create a new event. -->
</span><span class="lines">@@ -144,13 +144,13 @@
</span><span class="cx">                                                                                 <!-- Half of all events will be non-recurring -->
</span><span class="cx">                                                                                 <key>none</key>
</span><span class="cx">                                                                                 <integer>50</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Daily and weekly are pretty common -->
</span><span class="cx">                                                                                 <key>daily</key>
</span><span class="cx">                                                                                 <integer>10</integer>
</span><span class="cx">                                                                                 <key>weekly</key>
</span><span class="cx">                                                                                 <integer>20</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Monthly, yearly, daily & weekly limit not so common -->
</span><span class="cx">                                                                                 <key>monthly</key>
</span><span class="cx">                                                                                 <integer>2</integer>
</span><span class="lines">@@ -160,7 +160,7 @@
</span><span class="cx">                                                                                 <integer>2</integer>
</span><span class="cx">                                                                                 <key>weeklylimit</key>
</span><span class="cx">                                                                                 <integer>5</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Work days pretty common -->
</span><span class="cx">                                                                                 <key>workdays</key>
</span><span class="cx">                                                                                 <integer>10</integer>
</span><span class="lines">@@ -247,13 +247,13 @@
</span><span class="cx">                                                                                 <!-- Half of all events will be non-recurring -->
</span><span class="cx">                                                                                 <key>none</key>
</span><span class="cx">                                                                                 <integer>50</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Daily and weekly are pretty common -->
</span><span class="cx">                                                                                 <key>daily</key>
</span><span class="cx">                                                                                 <integer>25</integer>
</span><span class="cx">                                                                                 <key>weekly</key>
</span><span class="cx">                                                                                 <integer>25</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Monthly, yearly, daily & weekly limit not so common -->
</span><span class="cx">                                                                                 <key>monthly</key>
</span><span class="cx">                                                                                 <integer>0</integer>
</span><span class="lines">@@ -263,7 +263,7 @@
</span><span class="cx">                                                                                 <integer>0</integer>
</span><span class="cx">                                                                                 <key>weeklylimit</key>
</span><span class="cx">                                                                                 <integer>0</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Work days pretty common -->
</span><span class="cx">                                                                                 <key>workdays</key>
</span><span class="cx">                                                                                 <integer>0</integer>
</span><span class="lines">@@ -273,99 +273,6 @@
</span><span class="cx">                                                 </dict>
</span><span class="cx">                                         </dict>
</span><span class="cx">
</span><del>-                                        <!-- Picks a random event and changes the title -->
-                                        <dict>
-                                                <key>class</key>
-                                                <string>contrib.performance.loadtest.profiles.TitleChanger</string>
-
-                                                <key>params</key>
-                                                <dict>
-                                                        <key>enabled</key>
-                                                        <false/>
-
-                                                        <!-- Define the interval (in seconds) at which this profile will use
-                                                                its client to create a new event. -->
-                                                        <key>interval</key>
-                                                        <integer>10</integer>
-
-                                                </dict>
-                                        </dict>
-
-                                        <!-- Picks a random event and attaches -->
-                                        <dict>
-                                                <key>class</key>
-                                                <string>contrib.performance.loadtest.profiles.Attacher</string>
-
-                                                <key>params</key>
-                                                <dict>
-                                                        <key>enabled</key>
-                                                        <false/>
-
-                                                        <!-- Define the interval (in seconds) at which this profile will use
-                                                                its client to create a new event. -->
-                                                        <key>interval</key>
-                                                        <integer>10</integer>
-
-                                                        <!-- Define the attachment size distribution. -->
-                                                        <key>fileSizeDistribution</key>
-                                                        <dict>
-                                                                <key>type</key>
-                                                                <string>contrib.performance.stats.NormalDistribution</string>
-                                                                <key>params</key>
-                                                                <dict>
-                                                                        <!-- mu gives the mean of the normal distribution (in seconds). -->
-                                                                        <key>mu</key>
-                                                                        <integer>500000</integer>
-
-                                                                        <!-- and sigma gives its standard deviation. -->
-                                                                        <key>sigma</key>
-                                                                        <integer>100000</integer>
-                                                                </dict>
-                                                        </dict>
-
-                                                </dict>
-                                        </dict>
-
-                                        <!-- Removes events from calendars exceeding a threshold -->
-                                        <dict>
-                                                <key>class</key>
-                                                <string>contrib.performance.loadtest.profiles.EventCountLimiter</string>
-
-                                                <key>params</key>
-                                                <dict>
-                                                        <key>enabled</key>
-                                                        <false/>
-
-                                                        <!-- Define the interval (in seconds) at which this profile will check
-                                                                for too-large collections. -->
-                                                        <key>interval</key>
-                                                        <integer>60</integer>
-
-                                                        <!-- The upper bound. -->
-                                                        <key>eventCountLimit</key>
-                                                        <integer>10</integer>
-
-                                                </dict>
-                                        </dict>
-
-
-                                        <!-- Shares calendars -->
-                                        <dict>
-                                                <key>class</key>
-                                                <string>contrib.performance.loadtest.profiles.CalendarSharer</string>
-
-                                                <key>params</key>
-                                                <dict>
-                                                        <key>enabled</key>
-                                                        <true/>
-
-                                                        <!-- Define the interval (in seconds) at which this profile will share calendars. -->
-                                                        <key>interval</key>
-                                                        <integer>60</integer>
-
-                                                </dict>
-                                        </dict>
-
</del><span class="cx">                                         <!-- This profile invites some number of new attendees to new events. -->
</span><span class="cx">                                         <dict>
</span><span class="cx">                                                 <key>class</key>
</span><span class="lines">@@ -374,7 +281,7 @@
</span><span class="cx">                                                 <key>params</key>
</span><span class="cx">                                                 <dict>
</span><span class="cx">                                                         <key>enabled</key>
</span><del>-                                                        <false/>
</del><ins>+                                                        <true/>
</ins><span class="cx">
</span><span class="cx">                                                         <!-- Define the frequency at which new invitations will be sent out. -->
</span><span class="cx">                                                         <key>sendInvitationDistribution</key>
</span><span class="lines">@@ -385,7 +292,7 @@
</span><span class="cx">                                                                 <dict>
</span><span class="cx">                                                                         <!-- mu gives the mean of the normal distribution (in seconds). -->
</span><span class="cx">                                                                         <key>mu</key>
</span><del>-                                                                        <integer>10</integer>
</del><ins>+                                                                        <integer>60</integer>
</ins><span class="cx">
</span><span class="cx">                                                                         <!-- and sigma gives its standard deviation. -->
</span><span class="cx">                                                                         <key>sigma</key>
</span><span class="lines">@@ -394,12 +301,12 @@
</span><span class="cx">                                                         </dict>
</span><span class="cx">
</span><span class="cx">                                                         <!-- 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 "close to" the organizer based on account index. If the clumping
</span><span class="cx">                                                                 is too "tight" 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">                                                         <true/>
</span><span class="cx">
</span><span class="cx">                                                         <!-- 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 "mode" is the peak, "mean" 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">                                                          -->
</span><span class="cx">                                                         <key>inviteeCountDistribution</key>
</span><span class="cx">                                                         <dict>
</span><span class="lines">@@ -511,13 +418,13 @@
</span><span class="cx">                                                                                 <!-- Half of all events will be non-recurring -->
</span><span class="cx">                                                                                 <key>none</key>
</span><span class="cx">                                                                                 <integer>50</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Daily and weekly are pretty common -->
</span><span class="cx">                                                                                 <key>daily</key>
</span><span class="cx">                                                                                 <integer>10</integer>
</span><span class="cx">                                                                                 <key>weekly</key>
</span><span class="cx">                                                                                 <integer>20</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Monthly, yearly, daily & weekly limit not so common -->
</span><span class="cx">                                                                                 <key>monthly</key>
</span><span class="cx">                                                                                 <integer>2</integer>
</span><span class="lines">@@ -527,7 +434,7 @@
</span><span class="cx">                                                                                 <integer>2</integer>
</span><span class="cx">                                                                                 <key>weeklylimit</key>
</span><span class="cx">                                                                                 <integer>5</integer>
</span><del>-
</del><ins>+                                                                                
</ins><span class="cx">                                                                                 <!-- Work days pretty common -->
</span><span class="cx">                                                                                 <key>workdays</key>
</span><span class="cx">                                                                                 <integer>10</integer>
</span><span class="lines">@@ -552,7 +459,7 @@
</span><span class="cx">                                                                 accepting it.
</span><span class="cx">
</span><span class="cx">                                                                 For LogNormal "mode" is the peak, "median" 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">                                                         -->
</span><span class="cx">                                                         <key>acceptDelayDistribution</key>
</span><span class="cx">                                                         <dict>
</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">         <dict>
</span><span class="cx">                 <!-- Identify the server to be load tested. -->
</span><span class="cx">                 <key>server</key>
</span><del>-                <string>https://localhost:8443</string>
</del><ins>+                <string>https://127.0.0.1:8443</string>
</ins><span class="cx">
</span><span class="cx">                 <!-- The template URI for doing initial principal lookup on. -->
</span><span class="cx">                 <key>principalPathTemplate</key>
</span><span class="lines">@@ -96,7 +96,7 @@
</span><span class="cx">                         <dict>
</span><span class="cx">                                 <!-- groups gives the total number of groups of clients to introduce. -->
</span><span class="cx">                                 <key>groups</key>
</span><del>-                                <integer>1</integer>
</del><ins>+                                <integer>20</integer>
</ins><span class="cx">
</span><span class="cx">                                 <!-- groupSize is the number of clients in each group of clients. It's
</span><span class="cx">                                         really only a "smooth" ramp up if this is pretty small. -->
</span><span class="lines">@@ -118,7 +118,7 @@
</span><span class="cx">                 <!-- Define some log observers to report on the load test. -->
</span><span class="cx">                 <key>observers</key>
</span><span class="cx">                 <array>
</span><del>-                        <!-- ReportStatistics generates an end-of-run summary of the HTTP requests
</del><ins>+                        <!-- ReportStatistics generates an end-of-run summary of the HTTP requests
</ins><span class="cx">                                 made, their timings, and their results. -->
</span><span class="cx">                         <dict>
</span><span class="cx">                                 <key>type</key>
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">                                         <!-- The thresholds for each request type -->
</span><span class="cx">                                         <key>thresholdsPath</key>
</span><span class="cx">                                         <string>contrib/performance/loadtest/thresholds.json</string>
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         <!-- The benchmarks for overall QoS -->
</span><span class="cx">                                         <key>benchmarksPath</key>
</span><span class="cx">                                         <string>contrib/performance/loadtest/benchmarks.json</string>
</span><span class="lines">@@ -138,8 +138,8 @@
</span><span class="cx">                                         <real>1.0</real>
</span><span class="cx">                                 </dict>
</span><span class="cx">                         </dict>
</span><del>-
-                        <!-- RequestLogger generates a realtime log of all HTTP requests made
</del><ins>+        
+                        <!-- RequestLogger generates a realtime log of all HTTP requests made
</ins><span class="cx">                                 during the load test. -->
</span><span class="cx">                         <dict>
</span><span class="cx">                                 <key>type</key>
</span><span class="lines">@@ -148,9 +148,9 @@
</span><span class="cx">                                 <dict>
</span><span class="cx">                                 </dict>
</span><span class="cx">                         </dict>
</span><del>-
-                        <!-- OperationLogger generates an end-of-run summary of the gross operations
-                                performed (logical operations which may span more than one HTTP request,
</del><ins>+        
+                        <!-- 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). -->
</span><span class="cx">                         <dict>
</span><span class="cx">                                 <key>type</key>
</span><span class="lines">@@ -160,11 +160,11 @@
</span><span class="cx">                                         <!-- The thresholds for each operation type -->
</span><span class="cx">                                         <key>thresholdsPath</key>
</span><span class="cx">                                         <string>contrib/performance/loadtest/thresholds.json</string>
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         <!-- The % of operations beyond the lag cut-off that constitute a failed test -->
</span><span class="cx">                                         <key>lagCutoff</key>
</span><span class="cx">                                         <real>1.0</real>
</span><del>-
</del><ins>+                                        
</ins><span class="cx">                                         <!-- The % of failures that constitute a failed test -->
</span><span class="cx">                                         <key>failCutoff</key>
</span><span class="cx">                                         <real>1.0</real>
</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: '<QName %r>' % (self.text,)
</del><ins>+ElementTree.QName.__repr__ = lambda self: '<QName %r>' % (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 = ""
</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, "notifications")
-# if not os.path.exists(parentPath):
-# os.makedirs(parentPath)
-# return os.path.join(parentPath, self.url.split("/")[-1])
-# else:
-# return None
-
-
-# def serialize(self):
-# """
-# Create a dict of the data so we can serialize as JSON.
-# """
-
-# result = {}
-# for attr in ("url", "etag"):
-# result[attr] = getattr(self, attr)
-# return result
-
-
-# @staticmethod
-# def deserialize(serializeLocation, data):
-# """
-# Convert dict (deserialized from JSON) into an L{Event}.
-# """
-
-# event = Notification(serializeLocation, None, None)
-# for attr in ("url", "etag"):
-# setattr(event, attr, u2str(data[attr]))
-# return event
-
-
-# @property
-# def body(self):
-# """
-# Data always read from disk - never cached in the object.
-# """
-# 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):
-# """
-# Data always written to disk - never cached on the object.
-# """
-# path = self.serializePath()
-# if path:
-# if content is None:
-# os.remove(path)
-# else:
-# f = open(path, "w")
-# f.write(content)
-# f.close()
-
-
-# def removed(self):
-# """
-# Resource no longer exists on the server - remove associated data.
-# """
-# 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 = "notification"
-
- def serialize(self):
- """
- Create a dict of the data so we can serialize as JSON.
- """
-
- result = {}
- for attr in ("url", "changeToken"):
- result[attr] = getattr(self, attr)
- result["notifications"] = sorted(self.notifications.keys())
- return result
-
-
- @staticmethod
- def deserialize(data, notifications):
- """
- Convert dict (deserialized from JSON) into an L{Calendar}.
- """
-
- coll = NotificationCollection(None, None)
- for attr in ("url", "changeToken"):
- setattr(coll, attr, u2str(data[attr]))
-
- for notification in data["notifications"]:
- 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 = ""
- return coll
-
-
-
</del><span class="cx"> class BaseClient(object):
</span><span class="cx"> """
</span><span class="cx"> Base interface for all simulated clients.
</span><span class="cx"> """
</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):
- """
- Cache the provided notification
- """
- self._notifications[href] = notification
-
-
- def _removeNotification(self, href):
- """
- Remove notification from local cache.
- """
- self._notifications[href].removed()
- del self._notifications[href]
-
-
</del><span class="cx"> def addEvent(self, href, calendar):
</span><span class="cx"> """
</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="PROPFIND{home}",
</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"> """
</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("name").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"> """
</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("push" if push else "poll", self._poll(calendarHomeSet, firstTime))
</span><span class="cx"> finally:
</span><del>- print("*** BACK FROM NEW OPERATION, result=", 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="REPORT{sync}" if oldToken else "REPORT{sync-init}",
- )
- 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="REPORT{sync}" if oldToken else "REPORT{sync-init}",
- )
- 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="GET{notification}",
- )
- 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
- """
- <?xml version="1.0" encoding="UTF-8"?>
- <C:invite-reply xmlns:C="http://calendarserver.org/ns/">
- <A:href xmlns:A="DAV:">urn:x-uid:10000000-0000-0000-0000-000000000002</A:href>
- <C:invite-accepted/>
- <C:hosturl>
- <A:href xmlns:A="DAV:">/calendars/__uids__/10000000-0000-0000-0000-000000000001/A1DDC58B-651E-4B1C-872A-C6588CA09ADB</A:href>
- </C:hosturl>
- <C:in-reply-to>d2683fa9-7a50-4390-82bb-cbcea5e0fa86</C:in-reply-to>
- <C:summary>to share</C:summary>
- </C:invite-reply>
- """
- 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(),
- "POST{invite-accept}"
- )
-
- # 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="DELETE{invite}",
- )
-
- self._notificationCollection.changeToken = newToken
-
-
-
- @inlineCallbacks
</del><span class="cx"> def _poll(self, calendarHomeSet, firstTime):
</span><del>- """
- This gets called during a normal poll or in response to a push
- """
-
</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 = ""
- 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("startup: %s" % (self.title,), startup())
</span><span class="lines">@@ -1636,7 +1329,6 @@
</span><span class="cx"> "principalURL": self.principalURL,
</span><span class="cx"> "calendars": [calendar.serialize() for calendar in sorted(self._calendars.values(), key=lambda x:x.name)],
</span><span class="cx"> "events": [event.serialize() for event in sorted(self._events.values(), key=lambda x:x.url)],
</span><del>- "notificationCollection" : 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("utf-8")
</span><span class="cx">
</span><del>- search = "<C:search-token>{}</C:search-token>".format(prefix)
- body = self._CALENDARSERVER_PRINCIPAL_SEARCH_REPORT.format(
- context="attendee", 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="REPORT{cpsearch}"
</del><ins>+ self.principalCollection,
+ self._USER_LIST_PRINCIPAL_PROPERTY_SEARCH % {
+ 'displayname': prefix,
+ 'email': prefix,
+ 'firstname': prefix,
+ 'lastname': prefix,
+ },
+ depth=None,
+ method_label="REPORT{psearch}",
</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="DELETE{event}",
</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 + "{0}?{1}".format(href, "action=attachment-add")
- filename = 'file-{}.txt'.format(len(content))
- headers = Headers({
- 'Content-Disposition': ['attachment; filename="{}"'.format(filename)]
- })
- response = yield self._request(
- CREATED,
- 'POST',
- url,
- headers=headers,
- body=StringProducer(content),
- method_label="POST{attach}"
- )
- 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"> """
</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):
- """
- Implementation of the OS X 10.11 Calendar.app network behavior.
- """
</del><span class="cx">
</span><del>- _client_type = "OS X 10.11"
-
- USER_AGENT = "Mac+OS+X/10.11 (15A283) CalendarAgent/361"
-
- # 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 = "OS_X_10_11"
-
- _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):
- """
- 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.
- """
-
- 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"> """
</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 "besides"
- n = self._random.randint(0, count - 1)
- if besides != n:
- # Got it.
- break
- else:
- # Give up
- return None
- print("SELECTION, besides=", besides, "count=", count, "n=", 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):
- """
- Return a random L{Calendar} object from the current user
- or C{None} if there are no calendars to work with
- """
- 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):
- """
- Return a random L{Event} object from the current user
- or C{None} if there are no events to work with
- """
- 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"> """
</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, "VEVENT")
</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("CREATED", DateTime.getNowUTC()))
- vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
- vevent.replaceProperty(Property("DTSTART", dtstart))
- vevent.replaceProperty(Property("DTEND", dtend))
- vevent.replaceProperty(Property("UID", 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("CREATED", DateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTAMP", DateTime.getNowUTC()))
+ vevent.replaceProperty(Property("DTSTART", dtstart))
+ vevent.replaceProperty(Property("DTEND", dtend))
+ vevent.replaceProperty(Property("UID", uid))
</ins><span class="cx">
</span><del>- href = '%s%s.ics' % (calendar.url, uid)
- d = self._client.addEvent(href, vcalendar)
- return self._newOperation("create", 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("create", 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("DTSTAMP", 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):
- """Overriden by subclasses"""
- 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("SUMMARY", "Event" + "." * (length - 5)))
- return succeed("update{title}")
-
-
-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("attach{files}")
-
-
-class EventCountLimiter(EventUpdaterBase):
- """
- 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.
- """
-
- 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, "VEVENT"):
- while len(calendar.events) > self._limit:
- event = calendar.events[self.random.choice(calendar.events.keys())]
- yield self._client.deleteEvent(event.url)
-
-
-
-class CalendarSharer(ProfileBase):
- """
- A Calendar user who shares and un-shares other users to calendars.
- """
- 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 = "mailto:{}".format(shareeRecord.email)
- body = Calendar.addInviteeXML(mailto, calendar.name, readwrite=True)
- yield self._client.postXML(
- calendar.url,
- body,
- label="POST{share-calendar}"
- )
-
-
-
-# Is the purpose of this profile "EventUpdater" simply to keep updating the same
-# resource over and over?
-
</del><span class="cx"> class EventUpdater(ProfileBase):
</span><span class="cx"> """
</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 = """\
</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"> """
</span><span class="cx">
</span><span class="cx"> INVITED_EVENT = """\
</span><span class="lines">@@ -347,7 +347,7 @@
</span><span class="cx"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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"> """
</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("Some fictional client problem"))
</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"> "fullNames": ["cn", ],
</span><span class="cx"> "emailAddresses": ["mail", ],
</span><span class="cx"> "memberDNs": ["uniqueMember", ],
</span><del>- "hasCalendars": [],
- "autoScheduleMode": [],
- "autoAcceptGroup": [],
</del><span class="cx"> "readWriteProxy": ["icsContact", ],
</span><span class="cx"> "readOnlyProxy": ["icsSecondaryOwners", ],
</span><del>- "serviceNodeUID": [],
</del><span class="cx"> },
</span><span class="cx"> "extraFilters": {
</span><span class="cx"> "users": "",
</span></span></pre>
</div>
</div>
</body>
</html>