[CalendarServer-changes] [8119] CalendarServer/trunk/txdav/common/datastore

source_changes at macosforge.org source_changes at macosforge.org
Mon Sep 26 10:16:17 PDT 2011


Revision: 8119
          http://trac.macosforge.org/projects/calendarserver/changeset/8119
Author:   cdaboo at apple.com
Date:     2011-09-26 10:16:16 -0700 (Mon, 26 Sep 2011)
Log Message:
-----------
When upgrading, split each SQL statement in the upgrade files into separate execSQLs.

Modified Paths:
--------------
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/util.py

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2011-09-23 21:25:08 UTC (rev 8118)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2011-09-26 17:16:16 UTC (rev 8119)
@@ -61,6 +61,7 @@
 
 from twext.python.clsprop import classproperty
 from twext.enterprise.ienterprise import AlreadyFinishedError
+from twext.enterprise.dal.parseschema import significant
 from twext.enterprise.dal.syntax import Delete
 from twext.enterprise.dal.syntax import Insert
 from twext.enterprise.dal.syntax import Len
@@ -78,6 +79,10 @@
 from twistedcaldav.dateops import datetimeMktime, parseSQLTimestamp,\
     pyCalendarTodatetime
 
+from sqlparse import parse
+import collections
+import time
+
 current_sql_schema = getModule(__name__).filePath.sibling("sql_schema").child("current.sql").getContent()
 
 log = Logger()
@@ -166,7 +171,40 @@
             migrating,
         )
 
+class TransactionStatsCollector(object):
+    
+    def __init__(self):
+        self.count = collections.defaultdict(int)
+        self.times = collections.defaultdict(float)
+        self.tstamp = None
+        self.statement = None
+    
+    def startStatement(self, sql):
+        self.statement = sql
+        self.tstamp = time.time()
+        self.count[self.statement] += 1
 
+    def endStatement(self):
+        self.times[self.statement] += time.time() - self.tstamp
+        self.statement = None
+        self.tstamp = None
+        
+    def printReport(self):
+        
+        print "*** SQL Stats ***"
+        print 
+        print "Unique statements: %d" % (len(self.count,),)
+        print "Total statements: %d" % (sum(self.count.values()),)
+        print "Total time (ms): %.3f" % (sum(self.times.values()) * 1000.0,)
+        print
+        for k, v in self.count.items():
+            print k
+            print "Count: %s" % (v,)
+            print "Total Time (ms): %.3f" % (self.times[k] * 1000.0,)
+            if v > 1:
+                print "Average Time (ms): %.3f" % (self.times[k] * 1000.0 / v,)
+            print
+        print "***"
 
 class CommonStoreTransaction(object):
     """
@@ -209,6 +247,8 @@
         self._sqlTxn = sqlTxn
         self.paramstyle = sqlTxn.paramstyle
         self.dialect = sqlTxn.dialect
+        
+        self._stats = None #TransactionStatsCollector()
 
 
     def store(self):
@@ -366,13 +406,32 @@
             # caller shouldn't be paying attention anyway.
             block.end()
 
-
+    @inlineCallbacks
     def execSQL(self, *a, **kw):
         """
         Execute some SQL (delegate to L{IAsyncTransaction}).
         """
-        return self._sqlTxn.execSQL(*a, **kw)
+        if self._stats:        
+            self._stats.startStatement(a[0])
+        results = (yield self._sqlTxn.execSQL(*a, **kw))
+        if self._stats:        
+            self._stats.endStatement()
+        returnValue(results)
 
+    @inlineCallbacks
+    def execSQLBlock(self, sql):
+        """
+        Execute a block of SQL by parsing it out into individual statements and execute
+        each of those.
+        """
+        parsed = parse(sql)
+        for stmt in parsed:
+            while stmt.tokens and not significant(stmt.tokens[0]):
+                stmt.tokens.pop(0)
+            if not stmt.tokens:
+                continue
+            stmt = str(stmt).rstrip(";")
+            yield self.execSQL(stmt)
 
     def commit(self):
         """
@@ -382,6 +441,10 @@
             for operation in self._postCommitOperations:
                 operation()
             return ignored
+
+        if self._stats:        
+            self._stats.printReport()
+
         return self._sqlTxn.commit().addCallback(postCommit)
 
 

Modified: CalendarServer/trunk/txdav/common/datastore/util.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/util.py	2011-09-23 21:25:08 UTC (rev 8118)
+++ CalendarServer/trunk/txdav/common/datastore/util.py	2011-09-26 17:16:16 UTC (rev 8119)
@@ -370,7 +370,7 @@
         """
         self.log_warn("Applying schema upgrade: %s" % (fp.basename(),))
         sql = fp.getContent()
-        yield sqlTxn.execSQL(sql)
+        yield sqlTxn.execSQLBlock(sql)
         
     def startService(self):
         """
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110926/78563327/attachment.html>


More information about the calendarserver-changes mailing list