[Erp5-report] r35627 jm - in /erp5/trunk/products/ERP5Type: ./ patches/

nobody at svn.erp5.org nobody at svn.erp5.org
Tue May 25 19:20:54 CEST 2010


Author: jm
Date: Tue May 25 19:20:51 2010
New Revision: 35627

URL: http://svn.erp5.org?rev=35627&view=rev
Log:
Zope 2.8: prevent invalidations from being processed in any order

This fix requires that I/O for ZEO storages are processed only the main thread.

Added:
    erp5/trunk/products/ERP5Type/patches/ClientStorage.py
Modified:
    erp5/trunk/products/ERP5Type/ZopePatch.py

Modified: erp5/trunk/products/ERP5Type/ZopePatch.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/ZopePatch.py?rev=35627&r1=35626&r2=35627&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/ZopePatch.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/ZopePatch.py [utf8] Tue May 25 19:20:51 2010
@@ -59,6 +59,7 @@
 from Products.ERP5Type.patches import transforms
 from Products.ERP5Type.patches import OFSPdata
 from Products.ERP5Type.patches import make_hidden_input
+from Products.ERP5Type.patches import ClientStorage
 from Products.ERP5Type.patches import DemoStorage
 # BACK: Forward Compatibility with Zope 2.12 or CMF 2.2. Remove when we've
 # dropped support for older versions.

Added: erp5/trunk/products/ERP5Type/patches/ClientStorage.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/patches/ClientStorage.py?rev=35627&view=auto
==============================================================================
--- erp5/trunk/products/ERP5Type/patches/ClientStorage.py (added)
+++ erp5/trunk/products/ERP5Type/patches/ClientStorage.py [utf8] Tue May 25 19:20:51 2010
@@ -1,0 +1,97 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# Copyright (c) 2010 Nexedi SARL and Contributors. All Rights Reserved.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+# This is a backport of http://svn.zope.org/?rev=106514&view=rev for Zope 2.8.
+
+try:
+    from ThreadedAsync import LoopCallback
+
+except ImportError:
+    pass # nothing to do for recent Zope
+
+else:
+    # Switch Zope 2.8 to async I/O for ZEO client storages
+
+    import Lifetime
+    Lifetime_lifetime_loop = Lifetime.lifetime_loop
+
+    def lifetime_loop():
+        from asyncore import socket_map as map
+        LoopCallback._loop_lock.acquire()
+        try:
+            LoopCallback._looping = map
+            while LoopCallback._loop_callbacks:
+                cb, args, kw = LoopCallback._loop_callbacks.pop()
+                cb(map, *args, **(kw or {}))
+        finally:
+            LoopCallback._loop_lock.release()
+        return Lifetime_lifetime_loop()
+
+    Lifetime.lifetime_loop = lifetime_loop
+
+    # Prevent invalidations from being processed out of order
+
+    from ZEO.ClientStorage import ClientStorage
+
+    def tpc_finish(self, txn, f=None):
+        """Storage API: finish a transaction."""
+        if txn is not self._transaction:
+            return
+        self._load_lock.acquire()
+        try:
+            if self._midtxn_disconnect:
+                raise ClientDisconnected(
+                       'Calling tpc_finish() on a disconnected transaction')
+
+            # The calls to tpc_finish() and _update_cache() should
+            # never run currently with another thread, because the
+            # tpc_cond condition variable prevents more than one
+            # thread from calling tpc_finish() at a time.
+            # <patch/>
+            self._lock.acquire()  # for atomic processing of invalidations
+            try:
+                tid = self._server.tpc_finish(id(txn)) # <patch/>
+                self._update_cache(tid)
+                if f is not None:
+                    f(tid)
+            finally:
+                self._lock.release()
+
+            r = self._check_serials()
+            assert r is None or len(r) == 0, "unhandled serialnos: %s" % r
+        finally:
+            self._load_lock.release()
+            self.end_transaction()
+
+    ClientStorage.tpc_finish = tpc_finish
+
+    from ZODB.Connection import Connection
+
+    def invalidate(self, tid, oids):
+        """Notify the Connection that transaction 'tid' invalidated oids."""
+        self._inv_lock.acquire()
+        try:
+            if self._txn_time is None:
+                self._txn_time = tid
+            # <patch>
+            elif tid < self._txn_time:
+                raise AssertionError("invalidations out of order, %r < %r"
+                                     % (tid, self._txn_time))
+            # </patch>
+            self._invalidated.update(oids)
+        finally:
+            self._inv_lock.release()
+
+    Connection.invalidate = invalidate




More information about the Erp5-report mailing list