[CalendarServer-changes] [9528] CalendarServer/trunk/contrib/performance
source_changes at macosforge.org
source_changes at macosforge.org
Mon Aug 6 09:47:35 PDT 2012
Revision: 9528
http://trac.macosforge.org/projects/calendarserver/changeset/9528
Author: cdaboo at apple.com
Date: 2012-08-06 09:47:35 -0700 (Mon, 06 Aug 2012)
Log Message:
-----------
New benchmark tool to examine SQL statement count, rows returned and time against various HTTP requests,
Added Paths:
-----------
CalendarServer/trunk/contrib/performance/sqlusage/
CalendarServer/trunk/contrib/performance/sqlusage/__init__.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/
CalendarServer/trunk/contrib/performance/sqlusage/requests/__init__.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/httpTests.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/multiget.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/propfind.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py
CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py
CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py
Added: CalendarServer/trunk/contrib/performance/sqlusage/__init__.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/__init__.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/__init__.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,19 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+SQL usage analysis tool.
+"""
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/__init__.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/__init__.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/__init__.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,19 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+SQL usage requests.
+"""
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/httpTests.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/httpTests.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/httpTests.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,98 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+"""
+Defines a set of HTTP requests to execute and return results.
+"""
+
+class HTTPTestBase(object):
+ """
+ Base class for an HTTP request that executes and results are returned for.
+ """
+
+ class SQLResults(object):
+
+ def __init__(self, count, rows, timing):
+ self.count = count
+ self.rows = rows
+ self.timing = timing
+
+ def __init__(self, label, session, href, logFilePath):
+ """
+ @param label: label used to identify the test
+ @type label: C{str}
+ """
+ self.label = label
+ self.session = session
+ self.baseHref = href
+ self.logFilePath = logFilePath
+ self.result = None
+
+ def execute(self):
+ """
+ Execute the HTTP request and read the results.
+ """
+
+ self.prepare()
+ self.clearLog()
+ self.doRequest()
+ self.collectResults()
+ self.cleanup()
+ return self.result
+
+ def prepare(self):
+ """
+ Do some setup prior to the real request.
+ """
+ pass
+
+ def clearLog(self):
+ """
+ Clear the server's SQL log file.
+ """
+ open(self.logFilePath, "w").write("")
+
+ def doRequest(self):
+ """
+ Execute the actual HTTP request. Sub-classes override.
+ """
+ raise NotImplementedError
+
+ def collectResults(self):
+ """
+ Parse the server log file to extract the details we need.
+ """
+
+ def extractInt(line):
+ pos = line.find(": ")
+ return int(line[pos+2:])
+
+ def extractFloat(line):
+ pos = line.find(": ")
+ return float(line[pos+2:])
+
+ data = open(self.logFilePath).read()
+ lines = data.splitlines()
+ count = extractInt(lines[4])
+ rows = extractInt(lines[5])
+ timing = extractFloat(lines[6])
+ self.result = HTTPTestBase.SQLResults(count, rows, timing)
+
+ def cleanup(self):
+ """
+ Do some cleanup after the real request.
+ """
+ pass
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/multiget.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/multiget.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/multiget.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,56 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.caldav.definitions import caldavxml
+from caldavclientlibrary.protocol.caldav.multiget import Multiget
+from caldavclientlibrary.protocol.http.data.string import ResponseDataString
+from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
+from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
+from twext.web2.dav.util import joinURL
+
+class MultigetTest(HTTPTestBase):
+ """
+ A multiget operation
+ """
+
+ def __init__(self, label, session, href, logFilePath, count):
+ super(MultigetTest, self).__init__(label, session, href, logFilePath)
+ self.count = count
+
+ def doRequest(self):
+ """
+ Execute the actual HTTP request.
+ """
+ hrefs = [joinURL(self.baseHref, "%d.ics" % (i+1,)) for i in range(self.count)]
+ props = (
+ davxml.getetag,
+ caldavxml.calendar_data,
+ caldavxml.schedule_tag,
+ )
+
+ # Create CalDAV multiget
+ request = Multiget(self.session, self.baseHref, hrefs, props)
+ result = ResponseDataString()
+ request.setOutput(result)
+
+ # Process it
+ self.session.runSession(request)
+
+ # If its a 207 we want to parse the XML
+ if request.getStatusCode() == statuscodes.MultiStatus:
+ pass
+ else:
+ raise RuntimeError("Muliget request failed: %s" % (request.getStatusCode(),))
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/propfind.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/propfind.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/propfind.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.http.data.string import ResponseDataString
+from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes,\
+ headers
+from caldavclientlibrary.protocol.webdav.propfind import PropFind
+from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
+
+class PropfindTest(HTTPTestBase):
+ """
+ A propfind operation
+ """
+
+ def __init__(self, label, session, href, logFilePath, depth=1):
+ super(PropfindTest, self).__init__(label, session, href, logFilePath)
+ self.depth = headers.Depth1 if depth == 1 else headers.Depth0
+
+ def doRequest(self):
+ """
+ Execute the actual HTTP request.
+ """
+ props = (
+ davxml.getetag,
+ davxml.getcontenttype,
+ )
+
+ # Create WebDAV propfind
+ request = PropFind(self.session, self.baseHref, self.depth, props)
+ result = ResponseDataString()
+ request.setOutput(result)
+
+ # Process it
+ self.session.runSession(request)
+
+ # If its a 207 we want to parse the XML
+ if request.getStatusCode() == statuscodes.MultiStatus:
+ pass
+ else:
+ raise RuntimeError("Propfind request failed: %s" % (request.getStatusCode(),))
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/query.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,110 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.webdav.definitions import davxml, statuscodes
+from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
+from twext.web2.dav.util import joinURL
+from pycalendar.datetime import PyCalendarDateTime
+from caldavclientlibrary.protocol.caldav.query import QueryVEVENTTimeRange
+from caldavclientlibrary.protocol.http.data.string import ResponseDataString
+
+ICAL = """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART:%s
+DURATION:PT1H
+SUMMARY:event 1
+UID:sync-collection-%d-ics
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+class QueryTest(HTTPTestBase):
+ """
+ A sync operation
+ """
+
+ def __init__(self, label, session, href, logFilePath, count):
+ super(QueryTest, self).__init__(label, session, href, logFilePath)
+ self.count = count
+
+ def prepare(self):
+ """
+ Do some setup prior to the real request.
+ """
+ # Add resources to create required number of changes
+ self.start = PyCalendarDateTime.getNowUTC()
+ self.start.setHHMMSS(12, 0, 0)
+ self.end = self.start.duplicate()
+ self.end.offsetHours(1)
+ for i in range(self.count):
+ href = joinURL(self.baseHref, "tr-query-%d.ics" % (i+1,))
+ self.session.writeData(URL(path=href), ICAL % (self.start.getText(), i+1,), "text/calendar")
+
+ def doRequest(self):
+ """
+ Execute the actual HTTP request.
+ """
+ props = (
+ davxml.getetag,
+ davxml.getcontenttype,
+ )
+
+ # Create CalDAV query
+ request = QueryVEVENTTimeRange(self.session, self.baseHref, self.start.getText(), self.end.getText(), props)
+ result = ResponseDataString()
+ request.setOutput(result)
+
+ # Process it
+ self.session.runSession(request)
+
+ # If its a 207 we want to parse the XML
+ if request.getStatusCode() == statuscodes.MultiStatus:
+ pass
+ else:
+ raise RuntimeError("Query request failed: %s" % (request.getStatusCode(),))
+
+ def cleanup(self):
+ """
+ Do some cleanup after the real request.
+ """
+ # Remove created resources
+ for i in range(self.count):
+ href = joinURL(self.baseHref, "tr-query-%d.ics" % (i+1,))
+ self.session.deleteResource(URL(path=href))
Added: CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/requests/sync.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,102 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+from contrib.performance.sqlusage.requests.httpTests import HTTPTestBase
+from twext.web2.dav.util import joinURL
+from pycalendar.datetime import PyCalendarDateTime
+
+ICAL = """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:%d0101T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:sync-collection-%d-ics
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+class SyncTest(HTTPTestBase):
+ """
+ A sync operation
+ """
+
+ def __init__(self, label, session, href, logFilePath, full, count):
+ super(SyncTest, self).__init__(label, session, href, logFilePath)
+ self.full = full
+ self.count = count
+ self.synctoken = ""
+
+ def prepare(self):
+ """
+ Do some setup prior to the real request.
+ """
+ if not self.full:
+ # Get current sync token
+ results, _ignore_bad = self.session.getProperties(URL(path=self.baseHref), (davxml.sync_token,))
+ self.synctoken = results[davxml.sync_token]
+
+ # Add resources to create required number of changes
+ now = PyCalendarDateTime.getNowUTC()
+ for i in range(self.count):
+ href = joinURL(self.baseHref, "sync-collection-%d.ics" % (i+1,))
+ self.session.writeData(URL(path=href), ICAL % (now.getYear() + 1, i+1,), "text/calendar")
+
+ def doRequest(self):
+ """
+ Execute the actual HTTP request.
+ """
+ props = (
+ davxml.getetag,
+ davxml.getcontenttype,
+ )
+
+ # Run sync collection
+ self.session.syncCollection(URL(path=self.baseHref), self.synctoken, props)
+
+ def cleanup(self):
+ """
+ Do some cleanup after the real request.
+ """
+ if not self.full:
+ # Remove created resources
+ for i in range(self.count):
+ href = joinURL(self.baseHref, "sync-collection-%d.ics" % (i+1,))
+ self.session.deleteResource(URL(path=href))
Added: CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py
===================================================================
--- CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py (rev 0)
+++ CalendarServer/trunk/contrib/performance/sqlusage/sqlusage.py 2012-08-06 16:47:35 UTC (rev 9528)
@@ -0,0 +1,214 @@
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from StringIO import StringIO
+from caldavclientlibrary.client.clientsession import CalDAVSession
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+from calendarserver.tools import tables
+from contrib.performance.sqlusage.requests.multiget import MultigetTest
+from contrib.performance.sqlusage.requests.propfind import PropfindTest
+from contrib.performance.sqlusage.requests.query import QueryTest
+from contrib.performance.sqlusage.requests.sync import SyncTest
+from pycalendar.datetime import PyCalendarDateTime
+from twext.web2.dav.util import joinURL
+import getopt
+import sys
+
+"""
+This tool is designed to analyze how SQL is being used for various HTTP requests.
+It will execute a series of HTTP requests against a test server configuration and
+count the total number of SQL statements per request, the total number of rows
+returned per request and the total SQL execution time per request. Each series
+will be repeated against a varying calendar size so the variation in SQL use
+with calendar size can be plotted.
+"""
+
+EVENT_COUNTS = (0, 1, 5, 10, 25, 50, 75, 100, 200, 300, 400, 500, 1000, 2000, 3000, 4000, 5000)
+
+ICAL = """BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+LAST-MODIFIED:20040110T032845Z
+TZID:US/Eastern
+BEGIN:DAYLIGHT
+DTSTART:20000404T020000
+RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
+TZNAME:EDT
+TZOFFSETFROM:-0500
+TZOFFSETTO:-0400
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20001026T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+TZNAME:EST
+TZOFFSETFROM:-0400
+TZOFFSETTO:-0500
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART;TZID=US/Eastern:%d0101T100000
+DURATION:PT1H
+SUMMARY:event 1
+UID:%d-ics
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+
+class SQLUsage(object):
+
+ def __init__(self, server, port, user, pswd, logFilePath):
+ self.server = server
+ self.port = port
+ self.user = user
+ self.pswd = pswd
+ self.logFilePath = logFilePath
+ self.requestLabels = []
+ self.results = {}
+ self.currentCount = 0
+
+ self.userhref = "/calendars/users/%s/" % (self.user,)
+
+ def runLoop(self):
+
+ # Make the session
+ session = CalDAVSession(self.server, self.port, user=self.user, pswd=self.pswd, root="/")
+
+ # Set of requests to execute
+ requests = [
+ MultigetTest("multiget-1", session, joinURL(self.userhref, "calendar/"), self.logFilePath, 1),
+ MultigetTest("multiget-50", session, joinURL(self.userhref, "calendar/"), self.logFilePath, 50),
+ PropfindTest("propfind-cal", session, joinURL(self.userhref, "calendar/"), self.logFilePath, 1),
+ SyncTest("sync-full", session, joinURL(self.userhref, "calendar/"), self.logFilePath, True, 0),
+ SyncTest("sync-1", session, joinURL(self.userhref, "calendar/"), self.logFilePath, False, 1),
+ QueryTest("query-1", session, joinURL(self.userhref, "calendar/"), self.logFilePath, 1),
+ QueryTest("query-10", session, joinURL(self.userhref, "calendar/"), self.logFilePath, 10),
+ ]
+ self.requestLabels = [request.label for request in requests]
+
+ # Warm-up server by doing calendar home and calendar propfinds
+ props = (davxml.resourcetype,)
+ session.getPropertiesOnHierarchy(URL(path=self.userhref), props)
+ session.getPropertiesOnHierarchy(URL(path=joinURL(self.userhref, "calendar/")), props)
+
+ # Now loop over sets of events
+ for count in EVENT_COUNTS:
+ print "Testing count = %d" % (count,)
+ self.ensureEvents(session, count)
+ result = {}
+ for request in requests:
+ result[request.label] = request.execute()
+ self.results[count] = result
+
+ def report(self):
+
+ self._printReport("SQL Statement Count", "count", "%d")
+ self._printReport("SQL Rows Returned", "rows", "%d")
+ self._printReport("SQL Time", "timing", "%.3f")
+
+ def _printReport(self, title, attr, colFormat):
+ table = tables.Table()
+
+ print title
+ headers = ["Events"] + sorted([label for label in self.requestLabels])
+ table.addHeader(headers)
+ formats = [tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY)] + \
+ [tables.Table.ColumnFormat(colFormat, tables.Table.ColumnFormat.RIGHT_JUSTIFY)] * len(self.requestLabels)
+ table.setDefaultColumnFormats(formats)
+ for k in sorted(self.results.keys()):
+ row = [k] + [getattr(self.results[k][item], attr) for item in sorted(self.results[k].keys())]
+ table.addRow(row)
+ os = StringIO()
+ table.printTable(os=os)
+ print os.getvalue()
+ print
+
+ def ensureEvents(self, session, n):
+ """
+ Make sure the required number of events are present in the calendar.
+
+ @param n: number of events
+ @type n: C{int}
+ """
+ now = PyCalendarDateTime.getNowUTC()
+ for i in range(n - self.currentCount):
+ index = self.currentCount + i + 1
+ href = joinURL(self.userhref, "calendar", "%d.ics" % (index,))
+ session.writeData(URL(path=href), ICAL % (now.getYear() + 1, index,), "text/calendar")
+
+ self.currentCount = n
+
+def usage(error_msg=None):
+ if error_msg:
+ print error_msg
+
+ print """Usage: sqlusage.py [options] [FILE]
+Options:
+ -h Print this help and exit
+ --server Server hostname
+ --port Server port
+ --user User name
+ --pswd Password
+
+Arguments:
+ FILE File name for sqlstats.log to analyze.
+
+Description:
+This utility will analyze the output of s pg_stat_statement table.
+"""
+
+ if error_msg:
+ raise ValueError(error_msg)
+ else:
+ sys.exit(0)
+
+if __name__ == '__main__':
+
+ server = "localhost"
+ port = 8008
+ user = "user01"
+ pswd = "user01"
+ file = "sqlstats.logs"
+
+ options, args = getopt.getopt(sys.argv[1:], "h", ["server", "port", "user", "pswd",])
+
+ for option, value in options:
+ if option == "-h":
+ usage()
+ elif option == "--server":
+ server = value
+ elif option == "--port":
+ port = int(value)
+ elif option == "--user":
+ user = value
+ elif option == "--pswd":
+ pswd = value
+ else:
+ usage("Unrecognized option: %s" % (option,))
+
+ # Process arguments
+ if len(args) == 1:
+ file = args[0]
+ elif len(args) != 0:
+ usage("Must zero or one file arguments")
+
+ sql = SQLUsage(server, port, user, pswd, file)
+ sql.runLoop()
+ sql.report()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120806/e3dd3ea8/attachment-0001.html>
More information about the calendarserver-changes
mailing list