<!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>[15348] CalendarServer/trunk/contrib/performance/loadtest</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/15348">15348</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2015-11-30 13:22:41 -0800 (Mon, 30 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Multi-pod support for the sim.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunkcontribperformanceloadtestaccountscsv">CalendarServer/trunk/contrib/performance/loadtest/accounts.csv</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestconfigdistplist">CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist</a></li>
<li><a href="#CalendarServertrunkcontribperformanceloadtestconfigplist">CalendarServer/trunk/contrib/performance/loadtest/config.plist</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunkcontribperformanceloadtestaccountscsv"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/accounts.csv (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/accounts.csv        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/accounts.csv        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -1,99 +1,198 @@
</span><del>-user01,user01,User 01,user01@example.com,10000000-0000-0000-0000-000000000001
-user02,user02,User 02,user02@example.com,10000000-0000-0000-0000-000000000002
-user03,user03,User 03,user03@example.com,10000000-0000-0000-0000-000000000003
-user04,user04,User 04,user04@example.com,10000000-0000-0000-0000-000000000004
-user05,user05,User 05,user05@example.com,10000000-0000-0000-0000-000000000005
-user06,user06,User 06,user06@example.com,10000000-0000-0000-0000-000000000006
-user07,user07,User 07,user07@example.com,10000000-0000-0000-0000-000000000007
-user08,user08,User 08,user08@example.com,10000000-0000-0000-0000-000000000008
-user09,user09,User 09,user09@example.com,10000000-0000-0000-0000-000000000009
-user10,user10,User 10,user10@example.com,10000000-0000-0000-0000-000000000010
-user11,user11,User 11,user11@example.com,10000000-0000-0000-0000-000000000011
-user12,user12,User 12,user12@example.com,10000000-0000-0000-0000-000000000012
-user13,user13,User 13,user13@example.com,10000000-0000-0000-0000-000000000013
-user14,user14,User 14,user14@example.com,10000000-0000-0000-0000-000000000014
-user15,user15,User 15,user15@example.com,10000000-0000-0000-0000-000000000015
-user16,user16,User 16,user16@example.com,10000000-0000-0000-0000-000000000016
-user17,user17,User 17,user17@example.com,10000000-0000-0000-0000-000000000017
-user18,user18,User 18,user18@example.com,10000000-0000-0000-0000-000000000018
-user19,user19,User 19,user19@example.com,10000000-0000-0000-0000-000000000019
-user20,user20,User 20,user20@example.com,10000000-0000-0000-0000-000000000020
-user21,user21,User 21,user21@example.com,10000000-0000-0000-0000-000000000021
-user22,user22,User 22,user22@example.com,10000000-0000-0000-0000-000000000022
-user23,user23,User 23,user23@example.com,10000000-0000-0000-0000-000000000023
-user24,user24,User 24,user24@example.com,10000000-0000-0000-0000-000000000024
-user25,user25,User 25,user25@example.com,10000000-0000-0000-0000-000000000025
-user26,user26,User 26,user26@example.com,10000000-0000-0000-0000-000000000026
-user27,user27,User 27,user27@example.com,10000000-0000-0000-0000-000000000027
-user28,user28,User 28,user28@example.com,10000000-0000-0000-0000-000000000028
-user29,user29,User 29,user29@example.com,10000000-0000-0000-0000-000000000029
-user30,user30,User 30,user30@example.com,10000000-0000-0000-0000-000000000030
-user31,user31,User 31,user31@example.com,10000000-0000-0000-0000-000000000031
-user32,user32,User 32,user32@example.com,10000000-0000-0000-0000-000000000032
-user33,user33,User 33,user33@example.com,10000000-0000-0000-0000-000000000033
-user34,user34,User 34,user34@example.com,10000000-0000-0000-0000-000000000034
-user35,user35,User 35,user35@example.com,10000000-0000-0000-0000-000000000035
-user36,user36,User 36,user36@example.com,10000000-0000-0000-0000-000000000036
-user37,user37,User 37,user37@example.com,10000000-0000-0000-0000-000000000037
-user38,user38,User 38,user38@example.com,10000000-0000-0000-0000-000000000038
-user39,user39,User 39,user39@example.com,10000000-0000-0000-0000-000000000039
-user40,user40,User 40,user40@example.com,10000000-0000-0000-0000-000000000040
-user41,user41,User 41,user41@example.com,10000000-0000-0000-0000-000000000041
-user42,user42,User 42,user42@example.com,10000000-0000-0000-0000-000000000042
-user43,user43,User 43,user43@example.com,10000000-0000-0000-0000-000000000043
-user44,user44,User 44,user44@example.com,10000000-0000-0000-0000-000000000044
-user45,user45,User 45,user45@example.com,10000000-0000-0000-0000-000000000045
-user46,user46,User 46,user46@example.com,10000000-0000-0000-0000-000000000046
-user47,user47,User 47,user47@example.com,10000000-0000-0000-0000-000000000047
-user48,user48,User 48,user48@example.com,10000000-0000-0000-0000-000000000048
-user49,user49,User 49,user49@example.com,10000000-0000-0000-0000-000000000049
-user50,user50,User 50,user50@example.com,10000000-0000-0000-0000-000000000050
-user51,user51,User 51,user51@example.com,10000000-0000-0000-0000-000000000051
-user52,user52,User 52,user52@example.com,10000000-0000-0000-0000-000000000052
-user53,user53,User 53,user53@example.com,10000000-0000-0000-0000-000000000053
-user54,user54,User 54,user54@example.com,10000000-0000-0000-0000-000000000054
-user55,user55,User 55,user55@example.com,10000000-0000-0000-0000-000000000055
-user56,user56,User 56,user56@example.com,10000000-0000-0000-0000-000000000056
-user57,user57,User 57,user57@example.com,10000000-0000-0000-0000-000000000057
-user58,user58,User 58,user58@example.com,10000000-0000-0000-0000-000000000058
-user59,user59,User 59,user59@example.com,10000000-0000-0000-0000-000000000059
-user60,user60,User 60,user60@example.com,10000000-0000-0000-0000-000000000060
-user61,user61,User 61,user61@example.com,10000000-0000-0000-0000-000000000061
-user62,user62,User 62,user62@example.com,10000000-0000-0000-0000-000000000062
-user63,user63,User 63,user63@example.com,10000000-0000-0000-0000-000000000063
-user64,user64,User 64,user64@example.com,10000000-0000-0000-0000-000000000064
-user65,user65,User 65,user65@example.com,10000000-0000-0000-0000-000000000065
-user66,user66,User 66,user66@example.com,10000000-0000-0000-0000-000000000066
-user67,user67,User 67,user67@example.com,10000000-0000-0000-0000-000000000067
-user68,user68,User 68,user68@example.com,10000000-0000-0000-0000-000000000068
-user69,user69,User 69,user69@example.com,10000000-0000-0000-0000-000000000069
-user70,user70,User 70,user70@example.com,10000000-0000-0000-0000-000000000070
-user71,user71,User 71,user71@example.com,10000000-0000-0000-0000-000000000071
-user72,user72,User 72,user72@example.com,10000000-0000-0000-0000-000000000072
-user73,user73,User 73,user73@example.com,10000000-0000-0000-0000-000000000073
-user74,user74,User 74,user74@example.com,10000000-0000-0000-0000-000000000074
-user75,user75,User 75,user75@example.com,10000000-0000-0000-0000-000000000075
-user76,user76,User 76,user76@example.com,10000000-0000-0000-0000-000000000076
-user77,user77,User 77,user77@example.com,10000000-0000-0000-0000-000000000077
-user78,user78,User 78,user78@example.com,10000000-0000-0000-0000-000000000078
-user79,user79,User 79,user79@example.com,10000000-0000-0000-0000-000000000079
-user80,user80,User 80,user80@example.com,10000000-0000-0000-0000-000000000080
-user81,user81,User 81,user81@example.com,10000000-0000-0000-0000-000000000081
-user82,user82,User 82,user82@example.com,10000000-0000-0000-0000-000000000082
-user83,user83,User 83,user83@example.com,10000000-0000-0000-0000-000000000083
-user84,user84,User 84,user84@example.com,10000000-0000-0000-0000-000000000084
-user85,user85,User 85,user85@example.com,10000000-0000-0000-0000-000000000085
-user86,user86,User 86,user86@example.com,10000000-0000-0000-0000-000000000086
-user87,user87,User 87,user87@example.com,10000000-0000-0000-0000-000000000087
-user88,user88,User 88,user88@example.com,10000000-0000-0000-0000-000000000088
-user89,user89,User 89,user89@example.com,10000000-0000-0000-0000-000000000089
-user90,user90,User 90,user90@example.com,10000000-0000-0000-0000-000000000090
-user91,user91,User 91,user91@example.com,10000000-0000-0000-0000-000000000091
-user92,user92,User 92,user92@example.com,10000000-0000-0000-0000-000000000092
-user93,user93,User 93,user93@example.com,10000000-0000-0000-0000-000000000093
-user94,user94,User 94,user94@example.com,10000000-0000-0000-0000-000000000094
-user95,user95,User 95,user95@example.com,10000000-0000-0000-0000-000000000095
-user96,user96,User 96,user96@example.com,10000000-0000-0000-0000-000000000096
-user97,user97,User 97,user97@example.com,10000000-0000-0000-0000-000000000097
-user98,user98,User 98,user98@example.com,10000000-0000-0000-0000-000000000098
-user99,user99,User 99,user99@example.com,10000000-0000-0000-0000-000000000099
</del><ins>+user01,user01,User 01,user01@example.com,10000000-0000-0000-0000-000000000001,PodA
+user02,user02,User 02,user02@example.com,10000000-0000-0000-0000-000000000002,PodA
+user03,user03,User 03,user03@example.com,10000000-0000-0000-0000-000000000003,PodA
+user04,user04,User 04,user04@example.com,10000000-0000-0000-0000-000000000004,PodA
+user05,user05,User 05,user05@example.com,10000000-0000-0000-0000-000000000005,PodA
+user06,user06,User 06,user06@example.com,10000000-0000-0000-0000-000000000006,PodA
+user07,user07,User 07,user07@example.com,10000000-0000-0000-0000-000000000007,PodA
+user08,user08,User 08,user08@example.com,10000000-0000-0000-0000-000000000008,PodA
+user09,user09,User 09,user09@example.com,10000000-0000-0000-0000-000000000009,PodA
+user10,user10,User 10,user10@example.com,10000000-0000-0000-0000-000000000010,PodA
+user11,user11,User 11,user11@example.com,10000000-0000-0000-0000-000000000011,PodA
+user12,user12,User 12,user12@example.com,10000000-0000-0000-0000-000000000012,PodA
+user13,user13,User 13,user13@example.com,10000000-0000-0000-0000-000000000013,PodA
+user14,user14,User 14,user14@example.com,10000000-0000-0000-0000-000000000014,PodA
+user15,user15,User 15,user15@example.com,10000000-0000-0000-0000-000000000015,PodA
+user16,user16,User 16,user16@example.com,10000000-0000-0000-0000-000000000016,PodA
+user17,user17,User 17,user17@example.com,10000000-0000-0000-0000-000000000017,PodA
+user18,user18,User 18,user18@example.com,10000000-0000-0000-0000-000000000018,PodA
+user19,user19,User 19,user19@example.com,10000000-0000-0000-0000-000000000019,PodA
+user20,user20,User 20,user20@example.com,10000000-0000-0000-0000-000000000020,PodA
+user21,user21,User 21,user21@example.com,10000000-0000-0000-0000-000000000021,PodA
+user22,user22,User 22,user22@example.com,10000000-0000-0000-0000-000000000022,PodA
+user23,user23,User 23,user23@example.com,10000000-0000-0000-0000-000000000023,PodA
+user24,user24,User 24,user24@example.com,10000000-0000-0000-0000-000000000024,PodA
+user25,user25,User 25,user25@example.com,10000000-0000-0000-0000-000000000025,PodA
+user26,user26,User 26,user26@example.com,10000000-0000-0000-0000-000000000026,PodA
+user27,user27,User 27,user27@example.com,10000000-0000-0000-0000-000000000027,PodA
+user28,user28,User 28,user28@example.com,10000000-0000-0000-0000-000000000028,PodA
+user29,user29,User 29,user29@example.com,10000000-0000-0000-0000-000000000029,PodA
+user30,user30,User 30,user30@example.com,10000000-0000-0000-0000-000000000030,PodA
+user31,user31,User 31,user31@example.com,10000000-0000-0000-0000-000000000031,PodA
+user32,user32,User 32,user32@example.com,10000000-0000-0000-0000-000000000032,PodA
+user33,user33,User 33,user33@example.com,10000000-0000-0000-0000-000000000033,PodA
+user34,user34,User 34,user34@example.com,10000000-0000-0000-0000-000000000034,PodA
+user35,user35,User 35,user35@example.com,10000000-0000-0000-0000-000000000035,PodA
+user36,user36,User 36,user36@example.com,10000000-0000-0000-0000-000000000036,PodA
+user37,user37,User 37,user37@example.com,10000000-0000-0000-0000-000000000037,PodA
+user38,user38,User 38,user38@example.com,10000000-0000-0000-0000-000000000038,PodA
+user39,user39,User 39,user39@example.com,10000000-0000-0000-0000-000000000039,PodA
+user40,user40,User 40,user40@example.com,10000000-0000-0000-0000-000000000040,PodA
+user41,user41,User 41,user41@example.com,10000000-0000-0000-0000-000000000041,PodA
+user42,user42,User 42,user42@example.com,10000000-0000-0000-0000-000000000042,PodA
+user43,user43,User 43,user43@example.com,10000000-0000-0000-0000-000000000043,PodA
+user44,user44,User 44,user44@example.com,10000000-0000-0000-0000-000000000044,PodA
+user45,user45,User 45,user45@example.com,10000000-0000-0000-0000-000000000045,PodA
+user46,user46,User 46,user46@example.com,10000000-0000-0000-0000-000000000046,PodA
+user47,user47,User 47,user47@example.com,10000000-0000-0000-0000-000000000047,PodA
+user48,user48,User 48,user48@example.com,10000000-0000-0000-0000-000000000048,PodA
+user49,user49,User 49,user49@example.com,10000000-0000-0000-0000-000000000049,PodA
+user50,user50,User 50,user50@example.com,10000000-0000-0000-0000-000000000050,PodA
+user51,user51,User 51,user51@example.com,10000000-0000-0000-0000-000000000051,PodA
+user52,user52,User 52,user52@example.com,10000000-0000-0000-0000-000000000052,PodA
+user53,user53,User 53,user53@example.com,10000000-0000-0000-0000-000000000053,PodA
+user54,user54,User 54,user54@example.com,10000000-0000-0000-0000-000000000054,PodA
+user55,user55,User 55,user55@example.com,10000000-0000-0000-0000-000000000055,PodA
+user56,user56,User 56,user56@example.com,10000000-0000-0000-0000-000000000056,PodA
+user57,user57,User 57,user57@example.com,10000000-0000-0000-0000-000000000057,PodA
+user58,user58,User 58,user58@example.com,10000000-0000-0000-0000-000000000058,PodA
+user59,user59,User 59,user59@example.com,10000000-0000-0000-0000-000000000059,PodA
+user60,user60,User 60,user60@example.com,10000000-0000-0000-0000-000000000060,PodA
+user61,user61,User 61,user61@example.com,10000000-0000-0000-0000-000000000061,PodA
+user62,user62,User 62,user62@example.com,10000000-0000-0000-0000-000000000062,PodA
+user63,user63,User 63,user63@example.com,10000000-0000-0000-0000-000000000063,PodA
+user64,user64,User 64,user64@example.com,10000000-0000-0000-0000-000000000064,PodA
+user65,user65,User 65,user65@example.com,10000000-0000-0000-0000-000000000065,PodA
+user66,user66,User 66,user66@example.com,10000000-0000-0000-0000-000000000066,PodA
+user67,user67,User 67,user67@example.com,10000000-0000-0000-0000-000000000067,PodA
+user68,user68,User 68,user68@example.com,10000000-0000-0000-0000-000000000068,PodA
+user69,user69,User 69,user69@example.com,10000000-0000-0000-0000-000000000069,PodA
+user70,user70,User 70,user70@example.com,10000000-0000-0000-0000-000000000070,PodA
+user71,user71,User 71,user71@example.com,10000000-0000-0000-0000-000000000071,PodA
+user72,user72,User 72,user72@example.com,10000000-0000-0000-0000-000000000072,PodA
+user73,user73,User 73,user73@example.com,10000000-0000-0000-0000-000000000073,PodA
+user74,user74,User 74,user74@example.com,10000000-0000-0000-0000-000000000074,PodA
+user75,user75,User 75,user75@example.com,10000000-0000-0000-0000-000000000075,PodA
+user76,user76,User 76,user76@example.com,10000000-0000-0000-0000-000000000076,PodA
+user77,user77,User 77,user77@example.com,10000000-0000-0000-0000-000000000077,PodA
+user78,user78,User 78,user78@example.com,10000000-0000-0000-0000-000000000078,PodA
+user79,user79,User 79,user79@example.com,10000000-0000-0000-0000-000000000079,PodA
+user80,user80,User 80,user80@example.com,10000000-0000-0000-0000-000000000080,PodA
+user81,user81,User 81,user81@example.com,10000000-0000-0000-0000-000000000081,PodA
+user82,user82,User 82,user82@example.com,10000000-0000-0000-0000-000000000082,PodA
+user83,user83,User 83,user83@example.com,10000000-0000-0000-0000-000000000083,PodA
+user84,user84,User 84,user84@example.com,10000000-0000-0000-0000-000000000084,PodA
+user85,user85,User 85,user85@example.com,10000000-0000-0000-0000-000000000085,PodA
+user86,user86,User 86,user86@example.com,10000000-0000-0000-0000-000000000086,PodA
+user87,user87,User 87,user87@example.com,10000000-0000-0000-0000-000000000087,PodA
+user88,user88,User 88,user88@example.com,10000000-0000-0000-0000-000000000088,PodA
+user89,user89,User 89,user89@example.com,10000000-0000-0000-0000-000000000089,PodA
+user90,user90,User 90,user90@example.com,10000000-0000-0000-0000-000000000090,PodA
+user91,user91,User 91,user91@example.com,10000000-0000-0000-0000-000000000091,PodA
+user92,user92,User 92,user92@example.com,10000000-0000-0000-0000-000000000092,PodA
+user93,user93,User 93,user93@example.com,10000000-0000-0000-0000-000000000093,PodA
+user94,user94,User 94,user94@example.com,10000000-0000-0000-0000-000000000094,PodA
+user95,user95,User 95,user95@example.com,10000000-0000-0000-0000-000000000095,PodA
+user96,user96,User 96,user96@example.com,10000000-0000-0000-0000-000000000096,PodA
+user97,user97,User 97,user97@example.com,10000000-0000-0000-0000-000000000097,PodA
+user98,user98,User 98,user98@example.com,10000000-0000-0000-0000-000000000098,PodA
+user99,user99,User 99,user99@example.com,10000000-0000-0000-0000-000000000099,PodA
+puser01,puser01,Puser 01,puser01@example.com,60000000-0000-0000-0000-000000000001,PodB
+puser02,puser02,Puser 02,puser02@example.com,60000000-0000-0000-0000-000000000002,PodB
+puser03,puser03,Puser 03,puser03@example.com,60000000-0000-0000-0000-000000000003,PodB
+puser04,puser04,Puser 04,puser04@example.com,60000000-0000-0000-0000-000000000004,PodB
+puser05,puser05,Puser 05,puser05@example.com,60000000-0000-0000-0000-000000000005,PodB
+puser06,puser06,Puser 06,puser06@example.com,60000000-0000-0000-0000-000000000006,PodB
+puser07,puser07,Puser 07,puser07@example.com,60000000-0000-0000-0000-000000000007,PodB
+puser08,puser08,Puser 08,puser08@example.com,60000000-0000-0000-0000-000000000008,PodB
+puser09,puser09,Puser 09,puser09@example.com,60000000-0000-0000-0000-000000000009,PodB
+puser10,puser10,Puser 10,puser10@example.com,60000000-0000-0000-0000-000000000010,PodB
+puser11,puser11,Puser 11,puser11@example.com,60000000-0000-0000-0000-000000000011,PodB
+puser12,puser12,Puser 12,puser12@example.com,60000000-0000-0000-0000-000000000012,PodB
+puser13,puser13,Puser 13,puser13@example.com,60000000-0000-0000-0000-000000000013,PodB
+puser14,puser14,Puser 14,puser14@example.com,60000000-0000-0000-0000-000000000014,PodB
+puser15,puser15,Puser 15,puser15@example.com,60000000-0000-0000-0000-000000000015,PodB
+puser16,puser16,Puser 16,puser16@example.com,60000000-0000-0000-0000-000000000016,PodB
+puser17,puser17,Puser 17,puser17@example.com,60000000-0000-0000-0000-000000000017,PodB
+puser18,puser18,Puser 18,puser18@example.com,60000000-0000-0000-0000-000000000018,PodB
+puser19,puser19,Puser 19,puser19@example.com,60000000-0000-0000-0000-000000000019,PodB
+puser20,puser20,Puser 20,puser20@example.com,60000000-0000-0000-0000-000000000020,PodB
+puser21,puser21,Puser 21,puser21@example.com,60000000-0000-0000-0000-000000000021,PodB
+puser22,puser22,Puser 22,puser22@example.com,60000000-0000-0000-0000-000000000022,PodB
+puser23,puser23,Puser 23,puser23@example.com,60000000-0000-0000-0000-000000000023,PodB
+puser24,puser24,Puser 24,puser24@example.com,60000000-0000-0000-0000-000000000024,PodB
+puser25,puser25,Puser 25,puser25@example.com,60000000-0000-0000-0000-000000000025,PodB
+puser26,puser26,Puser 26,puser26@example.com,60000000-0000-0000-0000-000000000026,PodB
+puser27,puser27,Puser 27,puser27@example.com,60000000-0000-0000-0000-000000000027,PodB
+puser28,puser28,Puser 28,puser28@example.com,60000000-0000-0000-0000-000000000028,PodB
+puser29,puser29,Puser 29,puser29@example.com,60000000-0000-0000-0000-000000000029,PodB
+puser30,puser30,Puser 30,puser30@example.com,60000000-0000-0000-0000-000000000030,PodB
+puser31,puser31,Puser 31,puser31@example.com,60000000-0000-0000-0000-000000000031,PodB
+puser32,puser32,Puser 32,puser32@example.com,60000000-0000-0000-0000-000000000032,PodB
+puser33,puser33,Puser 33,puser33@example.com,60000000-0000-0000-0000-000000000033,PodB
+puser34,puser34,Puser 34,puser34@example.com,60000000-0000-0000-0000-000000000034,PodB
+puser35,puser35,Puser 35,puser35@example.com,60000000-0000-0000-0000-000000000035,PodB
+puser36,puser36,Puser 36,puser36@example.com,60000000-0000-0000-0000-000000000036,PodB
+puser37,puser37,Puser 37,puser37@example.com,60000000-0000-0000-0000-000000000037,PodB
+puser38,puser38,Puser 38,puser38@example.com,60000000-0000-0000-0000-000000000038,PodB
+puser39,puser39,Puser 39,puser39@example.com,60000000-0000-0000-0000-000000000039,PodB
+puser40,puser40,Puser 40,puser40@example.com,60000000-0000-0000-0000-000000000040,PodB
+puser41,puser41,Puser 41,puser41@example.com,60000000-0000-0000-0000-000000000041,PodB
+puser42,puser42,Puser 42,puser42@example.com,60000000-0000-0000-0000-000000000042,PodB
+puser43,puser43,Puser 43,puser43@example.com,60000000-0000-0000-0000-000000000043,PodB
+puser44,puser44,Puser 44,puser44@example.com,60000000-0000-0000-0000-000000000044,PodB
+puser45,puser45,Puser 45,puser45@example.com,60000000-0000-0000-0000-000000000045,PodB
+puser46,puser46,Puser 46,puser46@example.com,60000000-0000-0000-0000-000000000046,PodB
+puser47,puser47,Puser 47,puser47@example.com,60000000-0000-0000-0000-000000000047,PodB
+puser48,puser48,Puser 48,puser48@example.com,60000000-0000-0000-0000-000000000048,PodB
+puser49,puser49,Puser 49,puser49@example.com,60000000-0000-0000-0000-000000000049,PodB
+puser50,puser50,Puser 50,puser50@example.com,60000000-0000-0000-0000-000000000050,PodB
+puser51,puser51,Puser 51,puser51@example.com,60000000-0000-0000-0000-000000000051,PodB
+puser52,puser52,Puser 52,puser52@example.com,60000000-0000-0000-0000-000000000052,PodB
+puser53,puser53,Puser 53,puser53@example.com,60000000-0000-0000-0000-000000000053,PodB
+puser54,puser54,Puser 54,puser54@example.com,60000000-0000-0000-0000-000000000054,PodB
+puser55,puser55,Puser 55,puser55@example.com,60000000-0000-0000-0000-000000000055,PodB
+puser56,puser56,Puser 56,puser56@example.com,60000000-0000-0000-0000-000000000056,PodB
+puser57,puser57,Puser 57,puser57@example.com,60000000-0000-0000-0000-000000000057,PodB
+puser58,puser58,Puser 58,puser58@example.com,60000000-0000-0000-0000-000000000058,PodB
+puser59,puser59,Puser 59,puser59@example.com,60000000-0000-0000-0000-000000000059,PodB
+puser60,puser60,Puser 60,puser60@example.com,60000000-0000-0000-0000-000000000060,PodB
+puser61,puser61,Puser 61,puser61@example.com,60000000-0000-0000-0000-000000000061,PodB
+puser62,puser62,Puser 62,puser62@example.com,60000000-0000-0000-0000-000000000062,PodB
+puser63,puser63,Puser 63,puser63@example.com,60000000-0000-0000-0000-000000000063,PodB
+puser64,puser64,Puser 64,puser64@example.com,60000000-0000-0000-0000-000000000064,PodB
+puser65,puser65,Puser 65,puser65@example.com,60000000-0000-0000-0000-000000000065,PodB
+puser66,puser66,Puser 66,puser66@example.com,60000000-0000-0000-0000-000000000066,PodB
+puser67,puser67,Puser 67,puser67@example.com,60000000-0000-0000-0000-000000000067,PodB
+puser68,puser68,Puser 68,puser68@example.com,60000000-0000-0000-0000-000000000068,PodB
+puser69,puser69,Puser 69,puser69@example.com,60000000-0000-0000-0000-000000000069,PodB
+puser70,puser70,Puser 70,puser70@example.com,60000000-0000-0000-0000-000000000070,PodB
+puser71,puser71,Puser 71,puser71@example.com,60000000-0000-0000-0000-000000000071,PodB
+puser72,puser72,Puser 72,puser72@example.com,60000000-0000-0000-0000-000000000072,PodB
+puser73,puser73,Puser 73,puser73@example.com,60000000-0000-0000-0000-000000000073,PodB
+puser74,puser74,Puser 74,puser74@example.com,60000000-0000-0000-0000-000000000074,PodB
+puser75,puser75,Puser 75,puser75@example.com,60000000-0000-0000-0000-000000000075,PodB
+puser76,puser76,Puser 76,puser76@example.com,60000000-0000-0000-0000-000000000076,PodB
+puser77,puser77,Puser 77,puser77@example.com,60000000-0000-0000-0000-000000000077,PodB
+puser78,puser78,Puser 78,puser78@example.com,60000000-0000-0000-0000-000000000078,PodB
+puser79,puser79,Puser 79,puser79@example.com,60000000-0000-0000-0000-000000000079,PodB
+puser80,puser80,Puser 80,puser80@example.com,60000000-0000-0000-0000-000000000080,PodB
+puser81,puser81,Puser 81,puser81@example.com,60000000-0000-0000-0000-000000000081,PodB
+puser82,puser82,Puser 82,puser82@example.com,60000000-0000-0000-0000-000000000082,PodB
+puser83,puser83,Puser 83,puser83@example.com,60000000-0000-0000-0000-000000000083,PodB
+puser84,puser84,Puser 84,puser84@example.com,60000000-0000-0000-0000-000000000084,PodB
+puser85,puser85,Puser 85,puser85@example.com,60000000-0000-0000-0000-000000000085,PodB
+puser86,puser86,Puser 86,puser86@example.com,60000000-0000-0000-0000-000000000086,PodB
+puser87,puser87,Puser 87,puser87@example.com,60000000-0000-0000-0000-000000000087,PodB
+puser88,puser88,Puser 88,puser88@example.com,60000000-0000-0000-0000-000000000088,PodB
+puser89,puser89,Puser 89,puser89@example.com,60000000-0000-0000-0000-000000000089,PodB
+puser90,puser90,Puser 90,puser90@example.com,60000000-0000-0000-0000-000000000090,PodB
+puser91,puser91,Puser 91,puser91@example.com,60000000-0000-0000-0000-000000000091,PodB
+puser92,puser92,Puser 92,puser92@example.com,60000000-0000-0000-0000-000000000092,PodB
+puser93,puser93,Puser 93,puser93@example.com,60000000-0000-0000-0000-000000000093,PodB
+puser94,puser94,Puser 94,puser94@example.com,60000000-0000-0000-0000-000000000094,PodB
+puser95,puser95,Puser 95,puser95@example.com,60000000-0000-0000-0000-000000000095,PodB
+puser96,puser96,Puser 96,puser96@example.com,60000000-0000-0000-0000-000000000096,PodB
+puser97,puser97,Puser 97,puser97@example.com,60000000-0000-0000-0000-000000000097,PodB
+puser98,puser98,Puser 98,puser98@example.com,60000000-0000-0000-0000-000000000098,PodB
+puser99,puser99,Puser 99,puser99@example.com,60000000-0000-0000-0000-000000000099,PodB
</ins></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestconfigdistplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.dist.plist        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -32,10 +32,47 @@
</span><span class="cx">                         &lt;string&gt;./bin/python contrib/performance/loadtest/ampsim.py&lt;/string&gt;
</span><span class="cx">                 &lt;/array&gt;
</span><span class="cx"> 
</span><del>-                &lt;!-- Identify the server to be load tested. --&gt;
-                &lt;key&gt;server&lt;/key&gt;
-                &lt;string&gt;https://127.0.0.1:8443&lt;/string&gt;
</del><ins>+                &lt;!-- Identify all the servers to be load tested. --&gt;
+                &lt;key&gt;servers&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;key&gt;PodA&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;true/&gt;
</ins><span class="cx"> 
</span><ins>+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;https://localhost:8443&lt;/string&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8100&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                        &lt;key&gt;PodB&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;false/&gt;
+
+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;https://localhost:8543&lt;/string&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8101&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                &lt;/dict&gt;
+
</ins><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="cx">                 &lt;string&gt;/principals/users/%s/&lt;/string&gt;
</span><span class="lines">@@ -50,15 +87,6 @@
</span><span class="cx">                         &lt;integer&gt;8080&lt;/integer&gt;
</span><span class="cx">                 &lt;/dict&gt;
</span><span class="cx"> 
</span><del>-                &lt;!--  Define whether server supports stats socket. --&gt;
-                &lt;key&gt;serverStats&lt;/key&gt;
-                &lt;dict&gt;
-                        &lt;key&gt;enabled&lt;/key&gt;
-                        &lt;true/&gt;
-                        &lt;key&gt;Port&lt;/key&gt;
-                        &lt;integer&gt;8100&lt;/integer&gt;
-                &lt;/dict&gt;
-
</del><span class="cx">                 &lt;!--  Define whether client data should be re-used. It will always be saved to the specified path.--&gt;
</span><span class="cx">                 &lt;key&gt;clientDataSerialization&lt;/key&gt;
</span><span class="cx">                 &lt;dict&gt;
</span><span class="lines">@@ -88,6 +116,11 @@
</span><span class="cx">                                         a relative path. This isn't a great solution. --&gt;
</span><span class="cx">                                 &lt;key&gt;path&lt;/key&gt;
</span><span class="cx">                                 &lt;string&gt;contrib/performance/loadtest/accounts.csv&lt;/string&gt;
</span><ins>+
+                                &lt;!-- When there are accounts for multiple pods, interleave the accounts for each
+                                        pod so that the arrival mechanism will cycle clients between each pod. --&gt;
+                                &lt;key&gt;interleavePods&lt;/key&gt;
+                                &lt;true/&gt;
</ins><span class="cx">                         &lt;/dict&gt;
</span><span class="cx">                 &lt;/dict&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestconfigplist"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/config.plist (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/config.plist        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/config.plist        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -19,10 +19,47 @@
</span><span class="cx"> &lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
</span><span class="cx"> &lt;plist version=&quot;1.0&quot;&gt;
</span><span class="cx">         &lt;dict&gt;
</span><del>-                &lt;!-- Identify the server to be load tested. --&gt;
-                &lt;key&gt;server&lt;/key&gt;
-                &lt;string&gt;https://localhost:8443&lt;/string&gt;
</del><ins>+                &lt;!-- Identify all the servers to be load tested. --&gt;
+                &lt;key&gt;servers&lt;/key&gt;
+                &lt;dict&gt;
+                        &lt;key&gt;PodA&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;true/&gt;
</ins><span class="cx"> 
</span><ins>+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;https://localhost:8443&lt;/string&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8100&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                        &lt;key&gt;PodB&lt;/key&gt;
+                        &lt;dict&gt;
+                                &lt;key&gt;enabled&lt;/key&gt;
+                                &lt;false/&gt;
+
+                                &lt;!-- Identify the server to be load tested. --&gt;
+                                &lt;key&gt;uri&lt;/key&gt;
+                                &lt;string&gt;https://localhost:8543&lt;/string&gt;
+
+                                &lt;!--  Define whether server supports stats socket. --&gt;
+                                &lt;key&gt;stats&lt;/key&gt;
+                                &lt;dict&gt;
+                                        &lt;key&gt;enabled&lt;/key&gt;
+                                        &lt;true/&gt;
+                                        &lt;key&gt;Port&lt;/key&gt;
+                                        &lt;integer&gt;8101&lt;/integer&gt;
+                                &lt;/dict&gt;
+                        &lt;/dict&gt;
+                &lt;/dict&gt;
+
</ins><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="cx">                 &lt;string&gt;/principals/users/%s/&lt;/string&gt;
</span><span class="lines">@@ -37,15 +74,6 @@
</span><span class="cx">                         &lt;integer&gt;8080&lt;/integer&gt;
</span><span class="cx">                 &lt;/dict&gt;
</span><span class="cx"> 
</span><del>-                &lt;!--  Define whether server supports stats socket. --&gt;
-                &lt;key&gt;serverStats&lt;/key&gt;
-                &lt;dict&gt;
-                        &lt;key&gt;enabled&lt;/key&gt;
-                        &lt;true/&gt;
-                        &lt;key&gt;Port&lt;/key&gt;
-                        &lt;integer&gt;8100&lt;/integer&gt;
-                &lt;/dict&gt;
-
</del><span class="cx">                 &lt;!--  Define whether client data should be re-used. It will always be saved to the specified path.--&gt;
</span><span class="cx">                 &lt;key&gt;clientDataSerialization&lt;/key&gt;
</span><span class="cx">                 &lt;dict&gt;
</span><span class="lines">@@ -75,6 +103,11 @@
</span><span class="cx">                                         a relative path. This isn't a great solution. --&gt;
</span><span class="cx">                                 &lt;key&gt;path&lt;/key&gt;
</span><span class="cx">                                 &lt;string&gt;contrib/performance/loadtest/accounts.csv&lt;/string&gt;
</span><ins>+
+                                &lt;!-- When there are accounts for multiple pods, interleave the accounts for each
+                                        pod so that the arrival mechanism will cycle clients between each pod. --&gt;
+                                &lt;key&gt;interleavePods&lt;/key&gt;
+                                &lt;true/&gt;
</ins><span class="cx">                         &lt;/dict&gt;
</span><span class="cx">                 &lt;/dict&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestpopulationpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/population.py (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/population.py        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/population.py        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -162,13 +162,13 @@
</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, random, parameters, reactor, servers,
</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><span class="cx">         self._random = random
</span><span class="cx">         self.reactor = reactor
</span><del>-        self.server = server
</del><ins>+        self.servers = servers
</ins><span class="cx">         self.principalPathTemplate = principalPathTemplate
</span><span class="cx">         self.serializationPath = serializationPath
</span><span class="cx">         self._pop = self.populator.populate(parameters)
</span><span class="lines">@@ -220,16 +220,16 @@
</span><span class="cx">         authBasic = HTTPBasicAuthHandler(password_mgr=HTTPPasswordMgrWithDefaultRealm())
</span><span class="cx">         authBasic.add_password(
</span><span class="cx">             realm=None,
</span><del>-            uri=self.server,
</del><ins>+            uri=self.servers[record.podID][&quot;uri&quot;],
</ins><span class="cx">             user=user.encode('utf-8'),
</span><span class="cx">             passwd=record.password.encode('utf-8'))
</span><span class="cx">         authDigest = HTTPDigestAuthHandler(passwd=HTTPPasswordMgrWithDefaultRealm())
</span><span class="cx">         authDigest.add_password(
</span><span class="cx">             realm=None,
</span><del>-            uri=self.server,
</del><ins>+            uri=self.servers[record.podID][&quot;uri&quot;],
</ins><span class="cx">             user=user.encode('utf-8'),
</span><span class="cx">             passwd=record.password.encode('utf-8'))
</span><del>-        return user, {&quot;basic&quot;: authBasic, &quot;digest&quot;: authDigest, }
</del><ins>+        return record, user, {&quot;basic&quot;: authBasic, &quot;digest&quot;: authDigest, }
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def stop(self):
</span><span class="lines">@@ -260,15 +260,15 @@
</span><span class="cx">                     # runs the same arrival policy).
</span><span class="cx">                     continue
</span><span class="cx"> 
</span><del>-                _ignore_user, auth = self._createUser(number)
</del><ins>+                record, _ignore_user, auth = self._createUser(number)
</ins><span class="cx"> 
</span><span class="cx">                 reactor = loggedReactor(self.reactor)
</span><span class="cx">                 client = clientType.new(
</span><span class="cx">                     reactor,
</span><del>-                    self.server,
</del><ins>+                    self.servers[record.podID][&quot;uri&quot;],
</ins><span class="cx">                     self.principalPathTemplate,
</span><span class="cx">                     self.serializationPath,
</span><del>-                    self.getUserRecord(number),
</del><ins>+                    record,
</ins><span class="cx">                     auth,
</span><span class="cx">                 )
</span><span class="cx">                 self.clients.append(client)
</span><span class="lines">@@ -407,7 +407,7 @@
</span><span class="cx">     _fail_cut_off = 1.0     # % of total count at which failed requests will cause a failure
</span><span class="cx"> 
</span><span class="cx">     _fields_init = [
</span><del>-        ('request', -25, '%-25s'),
</del><ins>+        ('request', -30, '%-30s'),
</ins><span class="cx">         ('count', 8, '%8s'),
</span><span class="cx">         ('failed', 8, '%8s'),
</span><span class="cx">     ]
</span><span class="lines">@@ -427,7 +427,7 @@
</span><span class="cx">         self._failed_clients = []
</span><span class="cx">         self._failed_sim = collections.defaultdict(int)
</span><span class="cx">         self._startTime = datetime.now()
</span><del>-        self._expired_data = None
</del><ins>+        self._expired_data = {}
</ins><span class="cx"> 
</span><span class="cx">         # Load parameters from config
</span><span class="cx">         if &quot;thresholdsPath&quot; in params:
</span><span class="lines">@@ -496,7 +496,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def simExpired(self, event):
</span><del>-        self._expired_data = event['reason']
</del><ins>+        self._expired_data[event['podID']] = event['reason']
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def printMiscellaneous(self, output, items):
</span><span class="lines">@@ -576,14 +576,14 @@
</span><span class="cx">         self.printMiscellaneous(output, items)
</span><span class="cx">         output.write(&quot;\n&quot;)
</span><span class="cx"> 
</span><del>-        if self._expired_data is not None:
</del><ins>+        for podID, data in self._expired_data.items():
</ins><span class="cx">             items = {
</span><del>-                &quot;Req/sec&quot; : &quot;%.1f&quot; % (self._expired_data[0],),
-                &quot;Response&quot;: &quot;%.1f (ms)&quot; % (self._expired_data[1],),
-                &quot;Slots&quot;: &quot;%.2f&quot; % (self._expired_data[2],),
-                &quot;CPU&quot;: &quot;%.1f%%&quot; % (self._expired_data[3],),
</del><ins>+                &quot;Req/sec&quot; : &quot;%.1f&quot; % (data[0],),
+                &quot;Response&quot;: &quot;%.1f (ms)&quot; % (data[1],),
+                &quot;Slots&quot;: &quot;%.2f&quot; % (data[2],),
+                &quot;CPU&quot;: &quot;%.1f%%&quot; % (data[3],),
</ins><span class="cx">             }
</span><del>-            output.write(&quot;* Server (Last 5 minutes)\n&quot;)
</del><ins>+            output.write(&quot;* Server {podID} (Last 5 minutes)\n&quot;.format(podID=podID))
</ins><span class="cx">             self.printMiscellaneous(output, items)
</span><span class="cx">             output.write(&quot;\n&quot;)
</span><span class="cx">         output.write(&quot;* Details\n&quot;)
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestprofilespy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/profiles.py (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/profiles.py        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -662,6 +662,7 @@
</span><span class="cx">         return succeed(&quot;update{title}&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class DescriptionChanger(EventUpdaterBase):
</span><span class="cx"> 
</span><span class="cx">     def setParameters(
</span><span class="lines">@@ -681,6 +682,7 @@
</span><span class="cx">         return succeed(&quot;update{description}&quot;)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class Attacher(EventUpdaterBase):
</span><span class="cx"> 
</span><span class="cx">     def setParameters(
</span><span class="lines">@@ -998,6 +1000,7 @@
</span><span class="cx">             return self._newOperation(&quot;create&quot;, d)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class Resetter(ProfileBase):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     A Calendar user who resets their account and re-downloads everything.
</span><span class="lines">@@ -1026,6 +1029,7 @@
</span><span class="cx">         return self._client.reset()
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class OperationLogger(SummarizingMixin):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Profiles will initiate operations which may span multiple requests.  Start
</span><span class="lines">@@ -1053,7 +1057,7 @@
</span><span class="cx">     _fail_cut_off = 1.0     # % of total count at which failed requests will cause a failure
</span><span class="cx"> 
</span><span class="cx">     _fields_init = [
</span><del>-        ('operation', -25, '%-25s'),
</del><ins>+        ('operation', -30, '%-30s'),
</ins><span class="cx">         ('count', 8, '%8s'),
</span><span class="cx">         ('failed', 8, '%8s'),
</span><span class="cx">     ]
</span></span></pre></div>
<a id="CalendarServertrunkcontribperformanceloadtestsimpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/contrib/performance/loadtest/sim.py (15347 => 15348)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/contrib/performance/loadtest/sim.py        2015-11-30 20:25:51 UTC (rev 15347)
+++ CalendarServer/trunk/contrib/performance/loadtest/sim.py        2015-11-30 21:22:41 UTC (rev 15348)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx"> ##
</span><span class="cx"> from __future__ import print_function
</span><span class="cx"> 
</span><del>-from collections import namedtuple
</del><ins>+from collections import namedtuple, defaultdict
</ins><span class="cx"> from os import environ, mkdir
</span><span class="cx"> from os.path import isdir
</span><span class="cx"> from plistlib import readPlist
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> from sys import argv, stdout
</span><span class="cx"> from urlparse import urlsplit
</span><span class="cx"> from xml.parsers.expat import ExpatError
</span><ins>+import itertools
</ins><span class="cx"> import json
</span><span class="cx"> import shutil
</span><span class="cx"> import socket
</span><span class="lines">@@ -55,15 +56,20 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> class _DirectoryRecord(object):
</span><del>-    def __init__(self, uid, password, commonName, email, guid):
</del><ins>+    def __init__(self, uid, password, commonName, email, guid, podID=&quot;PodA&quot;):
</ins><span class="cx">         self.uid = uid
</span><span class="cx">         self.password = password
</span><span class="cx">         self.commonName = commonName
</span><span class="cx">         self.email = email
</span><span class="cx">         self.guid = guid
</span><ins>+        self.podID = podID
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+    def __repr__(self):
+        return &quot;user='{}'&quot;.format(self.uid)
</ins><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> def safeDivision(value, total, factor=1):
</span><span class="cx">     return value * factor / total if total else 0
</span><span class="cx"> 
</span><span class="lines">@@ -72,7 +78,7 @@
</span><span class="cx"> def generateRecords(
</span><span class="cx">     count, uidPattern=&quot;user%d&quot;, passwordPattern=&quot;user%d&quot;,
</span><span class="cx">     namePattern=&quot;User %d&quot;, emailPattern=&quot;user%d@example.com&quot;,
</span><del>-    guidPattern=&quot;user%d&quot;
</del><ins>+    guidPattern=&quot;user%d&quot;, podID=&quot;PodA&quot;,
</ins><span class="cx"> ):
</span><span class="cx">     for i in xrange(count):
</span><span class="cx">         i += 1
</span><span class="lines">@@ -81,22 +87,35 @@
</span><span class="cx">         name = namePattern % (i,)
</span><span class="cx">         email = emailPattern % (i,)
</span><span class="cx">         guid = guidPattern % (i,)
</span><del>-        yield _DirectoryRecord(uid, password, name, email, guid)
</del><ins>+        yield _DirectoryRecord(uid, password, name, email, guid, podID)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-def recordsFromCSVFile(path):
</del><ins>+def recordsFromCSVFile(path, interleavePods):
</ins><span class="cx">     if path:
</span><span class="cx">         pathObj = FilePath(path)
</span><span class="cx">     else:
</span><span class="cx">         pathObj = FilePath(__file__).sibling(&quot;accounts.csv&quot;)
</span><del>-    return [
</del><ins>+    records = [
</ins><span class="cx">         _DirectoryRecord(*line.decode('utf-8').split(u','))
</span><span class="cx">         for line
</span><del>-        in pathObj.getContent().splitlines()]
</del><ins>+        in pathObj.getContent().splitlines()
+    ]
</ins><span class="cx"> 
</span><ins>+    if interleavePods:
+        # For Pods we re-order the record list so that we alternate between the pods
+        recordsByPod = defaultdict(list)
+        for record in records:
+            recordsByPod[record.podID].append(record)
</ins><span class="cx"> 
</span><ins>+        records = []
+        for items in itertools.izip(*[recordsByPod[k] for k in sorted(recordsByPod.keys())]):
+            records.extend(items)
</ins><span class="cx"> 
</span><ins>+    return records
+
+
+
</ins><span class="cx"> class LagTrackingReactor(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     This reactor wraps another reactor and proxies all attribute
</span><span class="lines">@@ -228,15 +247,14 @@
</span><span class="cx">         user information about the accounts on the server being put
</span><span class="cx">         under load.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    def __init__(self, server, principalPathTemplate, webadminPort, serverStats, serializationPath, arrival, parameters, observers=None,
</del><ins>+    def __init__(self, servers, principalPathTemplate, webadminPort, serializationPath, arrival, parameters, observers=None,
</ins><span class="cx">                  records=None, reactor=None, runtime=None, workers=None,
</span><span class="cx">                  configTemplate=None, workerID=None, workerCount=1):
</span><span class="cx">         if reactor is None:
</span><span class="cx">             from twisted.internet import reactor
</span><del>-        self.server = server
</del><ins>+        self.servers = servers
</ins><span class="cx">         self.principalPathTemplate = principalPathTemplate
</span><span class="cx">         self.webadminPort = webadminPort
</span><del>-        self.serverStats = serverStats
</del><span class="cx">         self.serializationPath = serializationPath
</span><span class="cx">         self.arrival = arrival
</span><span class="cx">         self.parameters = parameters
</span><span class="lines">@@ -278,7 +296,7 @@
</span><span class="cx">             workerID = config.get(&quot;workerID&quot;, 0)
</span><span class="cx">             workerCount = config.get(&quot;workerCount&quot;, 1)
</span><span class="cx">             configTemplate = None
</span><del>-            server = config.get('server', 'http://127.0.0.1:8008')
</del><ins>+            servers = config.get('servers')
</ins><span class="cx">             principalPathTemplate = config.get('principalPathTemplate', '/principals/users/%s/')
</span><span class="cx">             serializationPath = None
</span><span class="cx"> 
</span><span class="lines">@@ -324,7 +342,7 @@
</span><span class="cx">                                                 [Eventer, Inviter, Accepter]))
</span><span class="cx">         else:
</span><span class="cx">             # Manager / observer process.
</span><del>-            server = ''
</del><ins>+            servers = {}
</ins><span class="cx">             principalPathTemplate = ''
</span><span class="cx">             serializationPath = None
</span><span class="cx">             arrival = None
</span><span class="lines">@@ -338,12 +356,6 @@
</span><span class="cx">             if config['webadmin']['enabled']:
</span><span class="cx">                 webadminPort = config['webadmin']['HTTPPort']
</span><span class="cx"> 
</span><del>-        serverStats = None
-        if 'serverStats' in config:
-            if config['serverStats']['enabled']:
-                serverStats = config['serverStats']
-                serverStats['server'] = config['server'] if 'server' in config else ''
-
</del><span class="cx">         observers = []
</span><span class="cx">         if 'observers' in config:
</span><span class="cx">             for observer in config['observers']:
</span><span class="lines">@@ -356,13 +368,13 @@
</span><span class="cx">             loader = config['accounts']['loader']
</span><span class="cx">             params = config['accounts']['params']
</span><span class="cx">             records.extend(namedAny(loader)(**params))
</span><ins>+            records = cls.filterRecords(records, servers)
</ins><span class="cx">             output.write(&quot;Loaded {0} accounts.\n&quot;.format(len(records)))
</span><span class="cx"> 
</span><span class="cx">         return cls(
</span><del>-            server,
</del><ins>+            servers,
</ins><span class="cx">             principalPathTemplate,
</span><span class="cx">             webadminPort,
</span><del>-            serverStats,
</del><span class="cx">             serializationPath,
</span><span class="cx">             arrival,
</span><span class="cx">             parameters,
</span><span class="lines">@@ -403,6 +415,22 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     @classmethod
</span><ins>+    def filterRecords(cls, records, servers):
+        &quot;&quot;&quot;
+        Remove records that do not correspond to an enabled pod.
+
+        @param records: list of records to process
+        @type records: L{list}
+        @param servers: dictionary of servers
+        @type servers: L{dict}
+        &quot;&quot;&quot;
+
+        # Get all enabled pod ids
+        enabled = set(filter(lambda podID: servers[podID][&quot;enabled&quot;], servers.keys()))
+        return filter(lambda record: record.podID in enabled, records)
+
+
+    @classmethod
</ins><span class="cx">     def main(cls, args=None):
</span><span class="cx">         simulator = cls.fromCommandLine(args)
</span><span class="cx">         raise SystemExit(simulator.run())
</span><span class="lines">@@ -416,7 +444,7 @@
</span><span class="cx">             Random(),
</span><span class="cx">             self.parameters,
</span><span class="cx">             self.reactor,
</span><del>-            self.server,
</del><ins>+            self.servers,
</ins><span class="cx">             self.principalPathTemplate,
</span><span class="cx">             self.serializationPath,
</span><span class="cx">             self.workerID,
</span><span class="lines">@@ -480,18 +508,19 @@
</span><span class="cx">         Capture server stats and stop.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-        if self.serverStats is not None:
-            _ignore_scheme, hostname, _ignore_path, _ignore_query, _ignore_fragment = urlsplit(self.serverStats[&quot;server&quot;])
-            data = self.readStatsSock((hostname.split(&quot;:&quot;)[0], self.serverStats[&quot;Port&quot;],), True)
-            if &quot;Failed&quot; not in data:
-                data = data[&quot;stats&quot;][&quot;5m&quot;] if &quot;stats&quot; in data else data[&quot;5 Minutes&quot;]
-                result = (
-                    safeDivision(float(data[&quot;requests&quot;]), 5 * 60),
-                    safeDivision(data[&quot;t&quot;], data[&quot;requests&quot;]),
-                    safeDivision(float(data[&quot;slots&quot;]), data[&quot;requests&quot;]),
-                    safeDivision(data[&quot;cpu&quot;], data[&quot;requests&quot;]),
-                )
-                msg(type=&quot;sim-expired&quot;, reason=result)
</del><ins>+        for podID, server in self.servers.items():
+            if server[&quot;enabled&quot;] and server[&quot;stats&quot;][&quot;enabled&quot;]:
+                _ignore_scheme, hostname, _ignore_path, _ignore_query, _ignore_fragment = urlsplit(server[&quot;uri&quot;])
+                data = self.readStatsSock((hostname.split(&quot;:&quot;)[0], server[&quot;stats&quot;][&quot;Port&quot;],), True)
+                if &quot;Failed&quot; not in data:
+                    data = data[&quot;stats&quot;][&quot;5m&quot;] if &quot;stats&quot; in data else data[&quot;5 Minutes&quot;]
+                    result = (
+                        safeDivision(float(data[&quot;requests&quot;]), 5 * 60),
+                        safeDivision(data[&quot;t&quot;], data[&quot;requests&quot;]),
+                        safeDivision(float(data[&quot;slots&quot;]), data[&quot;requests&quot;]),
+                        safeDivision(data[&quot;cpu&quot;], data[&quot;requests&quot;]),
+                    )
+                    msg(type=&quot;sim-expired&quot;, podID=podID, reason=result)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     def stopAndReport(self):
</span></span></pre>
</div>
</div>

</body>
</html>