[CalendarServer-changes] [6593] CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/ datastore
source_changes at macosforge.org
source_changes at macosforge.org
Wed Nov 10 18:52:32 PST 2010
Revision: 6593
http://trac.macosforge.org/projects/calendarserver/changeset/6593
Author: glyph at apple.com
Date: 2010-11-10 18:52:29 -0800 (Wed, 10 Nov 2010)
Log Message:
-----------
Internal refactoring of DB-API vs. postgres-subprocess code.
Modified Paths:
--------------
CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/subpostgres.py
Added Paths:
-----------
CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/dbapiclient.py
Added: CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/dbapiclient.py
===================================================================
--- CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/dbapiclient.py (rev 0)
+++ CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/dbapiclient.py 2010-11-11 02:52:29 UTC (rev 6593)
@@ -0,0 +1,149 @@
+##
+# Copyright (c) 2010 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.
+##
+
+"""
+General utility client code for interfacing with DB-API 2.0 modules.
+"""
+
+class DiagnosticCursorWrapper(object):
+ """
+ Diagnostic wrapper around a DB-API 2.0 cursor for debugging connection
+ status.
+ """
+
+ def __init__(self, realCursor, connectionWrapper):
+ self.realCursor = realCursor
+ self.connectionWrapper = connectionWrapper
+
+
+ @property
+ def rowcount(self):
+ return self.realCursor.rowcount
+
+
+ @property
+ def description(self):
+ return self.realCursor.description
+
+
+ def execute(self, sql, args=()):
+ self.connectionWrapper.state = 'executing %r' % (sql,)
+# Use log.debug
+# sys.stdout.write(
+# "Really executing SQL %r in thread %r\n" %
+# ((sql % tuple(args)), thread.get_ident())
+# )
+ self.realCursor.execute(sql, args)
+
+
+ def close(self):
+ self.realCursor.close()
+
+
+ def fetchall(self):
+ results = self.realCursor.fetchall()
+# Use log.debug
+# sys.stdout.write(
+# "Really fetching results %r thread %r\n" %
+# (results, thread.get_ident())
+# )
+ return results
+
+
+
+class DiagnosticConnectionWrapper(object):
+ """
+ Diagnostic wrapper around a DB-API 2.0 connection for debugging connection
+ status.
+ """
+
+ def __init__(self, realConnection, label):
+ self.realConnection = realConnection
+ self.label = label
+ self.state = 'idle (start)'
+
+
+ def cursor(self):
+ return DiagnosticCursorWrapper(self.realConnection.cursor(), self)
+
+
+ def close(self):
+ self.realConnection.close()
+ self.state = 'closed'
+
+
+ def commit(self):
+ self.realConnection.commit()
+ self.state = 'idle (after commit)'
+
+
+ def rollback(self):
+ self.realConnection.rollback()
+ self.state = 'idle (after rollback)'
+
+
+
+class DBAPIConnector(object):
+ """
+ A simple wrapper for DB-API connectors.
+
+ @ivar dbModule: the DB-API module to use.
+ """
+
+ def __init__(self, dbModule, preflight, *connectArgs, **connectKw):
+ self.dbModule = dbModule
+ self.connectArgs = connectArgs
+ self.connectKw = connectKw
+ self.preflight = preflight
+
+
+ def connect(self, label="<unlabeled>"):
+ connection = self.dbModule.connect(*self.connectArgs, **self.connectKw)
+ w = DiagnosticConnectionWrapper(connection, label)
+ self.preflight(w)
+ return w
+
+
+
+def postgresPreflight(connection):
+ """
+ Pre-flight function for PostgreSQL connections: enable standard conforming
+ strings, and set a non-infinite statement timeout.
+ """
+ c = connection.cursor()
+
+ # Turn on standard conforming strings. This option is _required_ if
+ # you want to get correct behavior out of parameter-passing with the
+ # pgdb module. If it is not set then the server is potentially
+ # vulnerable to certain types of SQL injection.
+ c.execute("set standard_conforming_strings=on")
+
+ # Abort any second that takes more than 30 seconds (30000ms) to
+ # execute. This is necessary as a temporary workaround since it's
+ # hypothetically possible that different database operations could
+ # block each other, while executing SQL in the same process (in the
+ # same thread, since SQL executes in the main thread now). It's
+ # preferable to see some exceptions while we're in this state than to
+ # have the entire worker process hang.
+ c.execute("set statement_timeout=30000")
+
+ # pgdb (as per DB-API 2.0) automatically puts the connection into a
+ # 'executing a transaction' state when _any_ statement is executed on
+ # it (even these not-touching-any-data statements); make sure to commit
+ # first so that the application sees a fresh transaction, and the
+ # connection can safely be pooled without executing anything on it.
+ connection.commit()
+ c.close()
Modified: CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/subpostgres.py
===================================================================
--- CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/subpostgres.py 2010-11-11 02:47:00 UTC (rev 6592)
+++ CalendarServer/branches/users/glyph/dont-start-postgres/txdav/base/datastore/subpostgres.py 2010-11-11 02:52:29 UTC (rev 6593)
@@ -36,6 +36,8 @@
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor
from twisted.internet.defer import Deferred
+from txdav.base.datastore.dbapiclient import DBAPIConnector
+from txdav.base.datastore.dbapiclient import postgresPreflight
from txdav.base.datastore.asyncsqlpool import BaseSqlTxn
from twisted.application.service import MultiService
@@ -47,84 +49,6 @@
_MAGIC_READY_COOKIE = "database system is ready to accept connections"
-class DiagnosticCursorWrapper(object):
- """
- Diagnostic wrapper around a DB-API 2.0 cursor for debugging connection
- status.
- """
-
- def __init__(self, realCursor, connectionWrapper):
- self.realCursor = realCursor
- self.connectionWrapper = connectionWrapper
-
-
- @property
- def rowcount(self):
- return self.realCursor.rowcount
-
-
- @property
- def description(self):
- return self.realCursor.description
-
-
- def execute(self, sql, args=()):
- self.connectionWrapper.state = 'executing %r' % (sql,)
-# Use log.debug
-# sys.stdout.write(
-# "Really executing SQL %r in thread %r\n" %
-# ((sql % tuple(args)), thread.get_ident())
-# )
- self.realCursor.execute(sql, args)
-
-
- def close(self):
- self.realCursor.close()
-
-
- def fetchall(self):
- results = self.realCursor.fetchall()
-# Use log.debug
-# sys.stdout.write(
-# "Really fetching results %r thread %r\n" %
-# (results, thread.get_ident())
-# )
- return results
-
-
-
-class DiagnosticConnectionWrapper(object):
- """
- Diagnostic wrapper around a DB-API 2.0 connection for debugging connection
- status.
- """
-
- def __init__(self, realConnection, label):
- self.realConnection = realConnection
- self.label = label
- self.state = 'idle (start)'
-
-
- def cursor(self):
- return DiagnosticCursorWrapper(self.realConnection.cursor(), self)
-
-
- def close(self):
- self.realConnection.close()
- self.state = 'closed'
-
-
- def commit(self):
- self.realConnection.commit()
- self.state = 'idle (after commit)'
-
-
- def rollback(self):
- self.realConnection.rollback()
- self.state = 'idle (after rollback)'
-
-
-
class _PostgresMonitor(ProcessProtocol):
"""
A monitoring protocol which watches the postgres subprocess.
@@ -335,10 +259,7 @@
self.shutdownDeferred.callback(None)
- def produceConnection(self, label="<unlabeled>", databaseName=None):
- """
- Produce a DB-API 2.0 connection pointed at this database.
- """
+ def _connectorFor(self, databaseName=None):
if databaseName is None:
databaseName = self.databaseName
@@ -347,36 +268,16 @@
pwd.getpwuid(self.uid).pw_name)
else:
dsn = "%s:dbname=%s" % (self.host, databaseName)
- connection = pgdb.connect(dsn)
+ return DBAPIConnector(pgdb, postgresPreflight, dsn)
- w = DiagnosticConnectionWrapper(connection, label)
- c = w.cursor()
- # Turn on standard conforming strings. This option is _required_ if
- # you want to get correct behavior out of parameter-passing with the
- # pgdb module. If it is not set then the server is potentially
- # vulnerable to certain types of SQL injection.
- c.execute("set standard_conforming_strings=on")
+ def produceConnection(self, label="<unlabeled>", databaseName=None):
+ """
+ Produce a DB-API 2.0 connection pointed at this database.
+ """
+ return self._connectorFor(databaseName).connect(label)
- # Abort any second that takes more than 30 seconds (30000ms) to
- # execute. This is necessary as a temporary workaround since it's
- # hypothetically possible that different database operations could
- # block each other, while executing SQL in the same process (in the
- # same thread, since SQL executes in the main thread now). It's
- # preferable to see some exceptions while we're in this state than to
- # have the entire worker process hang.
- c.execute("set statement_timeout=30000")
- # pgdb (as per DB-API 2.0) automatically puts the connection into a
- # 'executing a transaction' state when _any_ statement is executed on
- # it (even these not-touching-any-data statements); make sure to commit
- # first so that the application sees a fresh transaction, and the
- # connection can safely be pooled without executing anything on it.
- w.commit()
- c.close()
- return w
-
-
def produceLocalTransaction(self, label="<unlabeled>"):
"""
Create a L{IAsyncTransaction} based on a thread in the current process.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101110/a6ec0bd2/attachment-0001.html>
More information about the calendarserver-changes
mailing list