[Checkins] SVN: relstorage/trunk/ Made compatible with ZODB 3.10 and fixed a MySQL deadlock caused by somebody changing the default transaction isolation mode.

Shane Hathaway shane at hathawaymix.org
Sat Jun 19 18:01:34 EDT 2010


Log message for revision 113702:
  Made compatible with ZODB 3.10 and fixed a MySQL deadlock caused by somebody changing the default transaction isolation mode.
  

Changed:
  U   relstorage/trunk/CHANGES.txt
  U   relstorage/trunk/README.txt
  U   relstorage/trunk/buildout.cfg
  U   relstorage/trunk/relstorage/__init__.py
  U   relstorage/trunk/relstorage/adapters/mysql.py
  U   relstorage/trunk/relstorage/options.py
  U   relstorage/trunk/relstorage/storage.py
  U   relstorage/trunk/relstorage/tests/RecoveryStorage.py
  U   relstorage/trunk/setup.py

-=-
Modified: relstorage/trunk/CHANGES.txt
===================================================================
--- relstorage/trunk/CHANGES.txt	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/CHANGES.txt	2010-06-19 22:01:34 UTC (rev 113702)
@@ -2,12 +2,27 @@
 ------------
 
 - History-preserving storages now replace objects on restore instead of
-  just inserting them.
+  just inserting them.  This should solve problems people were
+  having with the zodbconvert utility.
 
 - Oracle: call the DBMS_LOCK.REQUEST function directly instead of using
-  a small package.  The small relstorage_util package was confusing to DBAs
-  and provided no real security advantage.
+  a small package named ``relstorage_util``. The ``relstorage_util``
+  package was designed as a secure way to access the DBMS_LOCK package,
+  but the package turned out to be confusing to DBAs and provided no
+  real security advantage. Existing deployments of RelStorage 1.4.x on
+  Oracle need to do the following:
 
+      GRANT EXECUTE ON DBMS_LOCK TO <zodb_user>;
+
+  You can also drop the ``relstorage_util`` package (but keep the
+  ``relstorage_op`` package).
+
+- Made compatible with ZODB 3.10.
+
+- MySQL: specify the transaction isolation mode for every connection,
+  since the default is apparently not necessarily "read committed"
+  anymore.
+
 1.4.0b3 (2010-02-02)
 --------------------
 

Modified: relstorage/trunk/README.txt
===================================================================
--- relstorage/trunk/README.txt	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/README.txt	2010-06-19 22:01:34 UTC (rev 113702)
@@ -119,7 +119,8 @@
 
 You need to create a database user and grant execute privileges on
 the DBMS_LOCK package to that user.
-Here are some sample SQL statements for creating the database user::
+Here are some sample SQL statements for creating the database user
+and granting the required permissions::
 
     CREATE USER zodb IDENTIFIED BY mypassword;
     GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE SEQUENCE TO zodb;
@@ -476,7 +477,8 @@
         RelStorage caches pickled objects in memory, similar to a ZEO
         cache. This cache is shared between threads. This parameter
         configures the approximate maximum amount of memory the cache
-        should consume, in megabytes.  It defaults to 10.
+        should consume, in megabytes.  It defaults to 10.  Set to
+        0 to disable the in-memory cache.
 
 ``cache-delta-size-limit``
         This is an advanced option. RelStorage uses a system of

Modified: relstorage/trunk/buildout.cfg
===================================================================
--- relstorage/trunk/buildout.cfg	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/buildout.cfg	2010-06-19 22:01:34 UTC (rev 113702)
@@ -5,7 +5,7 @@
 eggs = relstorage
        psycopg2
        MySQL-python
-       ZODB3<3.10.0a1
+       ZODB3 [test]
 
 [test]
 recipe = zc.recipe.testrunner

Modified: relstorage/trunk/relstorage/__init__.py
===================================================================
--- relstorage/trunk/relstorage/__init__.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/relstorage/__init__.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -13,18 +13,18 @@
 ##############################################################################
 """relstorage package"""
 
-# perform a compatibility test
-try:
-    from ZODB.interfaces import IMVCCStorage
-    del IMVCCStorage
-except ImportError:
-    # see if the polling patch has been applied
-    from ZODB.Connection import Connection
-    if not hasattr(Connection, '_poll_invalidations'):
-        raise ImportError('RelStorage requires the invalidation polling '
-            'patch for ZODB.')
-    del Connection
-else:
-    # We're running a version of ZODB that knows what to do with
-    # MVCC storages, so no patch is necessary.
-    pass
+def check_compatible():
+    try:
+        from ZODB.interfaces import IMVCCStorage
+    except ImportError:
+        # see if the polling patch has been applied
+        from ZODB.Connection import Connection
+        if not hasattr(Connection, '_poll_invalidations'):
+            raise ImportError('RelStorage requires the invalidation polling '
+                'patch for ZODB.')
+    else:
+        # We're running a version of ZODB that knows what to do with
+        # MVCC storages, so no patch is necessary.
+        pass
+
+check_compatible()

Modified: relstorage/trunk/relstorage/adapters/mysql.py
===================================================================
--- relstorage/trunk/relstorage/adapters/mysql.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/relstorage/adapters/mysql.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -251,7 +251,7 @@
 
         This overrides a method.
         """
-        conn, cursor = self.open(transaction_mode=None)
+        conn, cursor = self.open()
         try:
             # This phase of packing works best with transactions
             # disabled.  It changes no user-facing data.

Modified: relstorage/trunk/relstorage/options.py
===================================================================
--- relstorage/trunk/relstorage/options.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/relstorage/options.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -12,6 +12,7 @@
 #
 ##############################################################################
 
+
 class Options(object):
     """Options for configuring and tuning RelStorage.
 
@@ -43,9 +44,21 @@
         self.cache_delta_size_limit = 10000
         self.commit_lock_timeout = 30
         self.commit_lock_id = 0
+        self.strict_tpc = default_strict_tpc
 
         for key, value in kwoptions.iteritems():
             if key in self.__dict__:
                 setattr(self, key, value)
             else:
                 raise TypeError("Unknown parameter: %s" % key)
+
+
+# Detect the version of ZODB and set default options accordingly.
+# ZODB does not seem to provide version information anywhere but in
+# setup.py, so the code below is a hack.  TODO: Bring this up on zodb-dev.
+
+default_strict_tpc = False
+
+from ZEO.zrpc.connection import Connection as __Connection
+if __Connection.current_protocol >= 'Z310':
+    default_strict_tpc = True

Modified: relstorage/trunk/relstorage/storage.py
===================================================================
--- relstorage/trunk/relstorage/storage.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/relstorage/storage.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -614,6 +614,9 @@
         self._lock_acquire()
         try:
             if self._transaction is transaction:
+                if self._options.strict_tpc:
+                    raise POSException.StorageTransactionError(
+                        "Duplicate tpc_begin calls for same transaction")
                 return
             self._lock_release()
             self._commit_lock_acquire()
@@ -759,6 +762,9 @@
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
+                if self._options.strict_tpc:
+                    raise POSException.StorageTransactionError(
+                        "tpc_vote called with wrong transaction")
                 return
             try:
                 return self._vote()
@@ -819,6 +825,9 @@
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
+                if self._options.strict_tpc:
+                    raise POSException.StorageTransactionError(
+                        "tpc_finish called with wrong transaction")
                 return
             try:
                 try:

Modified: relstorage/trunk/relstorage/tests/RecoveryStorage.py
===================================================================
--- relstorage/trunk/relstorage/tests/RecoveryStorage.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/relstorage/tests/RecoveryStorage.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -89,8 +89,20 @@
 
         # Make sure ther are no more records left in txn1 and txn2, meaning
         # they were the same length
-        self.assertRaises(IndexError, iter1.next)
-        self.assertRaises(IndexError, iter2.next)
+        try:
+            iter1.next()
+        except (IndexError, StopIteration):
+            pass
+        else:
+            self.fail("storage1 has more records")
+
+        try:
+            iter2.next()
+        except (IndexError, StopIteration):
+            pass
+        else:
+            self.fail("storage2 has more records")
+
         iter1.close()
         iter2.close()
 

Modified: relstorage/trunk/setup.py
===================================================================
--- relstorage/trunk/setup.py	2010-06-19 19:27:28 UTC (rev 113701)
+++ relstorage/trunk/setup.py	2010-06-19 22:01:34 UTC (rev 113702)
@@ -13,7 +13,7 @@
 ##############################################################################
 """A backend for ZODB that stores pickles in a relational database."""
 
-VERSION = "1.4.0b3"
+VERSION = "1.4.0c1"
 
 # The choices for the Trove Development Status line:
 # Development Status :: 5 - Production/Stable



More information about the checkins mailing list