[Checkins] SVN: ZODB/branches/shane-poll-invalidations/src/ZODB/ Renamed PollableMappingStorage to MVCCMappingStorage,

Shane Hathaway shane at hathawaymix.org
Sat Apr 25 19:45:06 EDT 2009


Log message for revision 99499:
  Renamed PollableMappingStorage to MVCCMappingStorage,
  made it implement IMVCCStorage, and moved it to the
  tests directory.
  

Changed:
  D   ZODB/branches/shane-poll-invalidations/src/ZODB/PollableMappingStorage.py
  A   ZODB/branches/shane-poll-invalidations/src/ZODB/tests/MVCCMappingStorage.py
  A   ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testMVCCMappingStorage.py
  D   ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testPollableMappingStorage.py

-=-
Deleted: ZODB/branches/shane-poll-invalidations/src/ZODB/PollableMappingStorage.py
===================================================================
--- ZODB/branches/shane-poll-invalidations/src/ZODB/PollableMappingStorage.py	2009-04-25 23:27:13 UTC (rev 99498)
+++ ZODB/branches/shane-poll-invalidations/src/ZODB/PollableMappingStorage.py	2009-04-25 23:45:05 UTC (rev 99499)
@@ -1,93 +0,0 @@
-##############################################################################
-#
-# Copyright (c) Zope Corporation and Contributors.
-# 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
-#
-##############################################################################
-"""An extension of MappingStorage that depends on polling.
-
-Each Connection has its own view of the database.  Polling updates each
-connection's view.
-"""
-
-import time
-
-import BTrees
-from ZODB.interfaces import IStoragePollable
-from ZODB.MappingStorage import MappingStorage
-from ZODB.TimeStamp import TimeStamp
-from zope.interface import implements
-
-
-class PollableMappingStorage(MappingStorage):
-    implements(IStoragePollable)
-
-    propagate_invalidations = False
-
-    def __init__(self, name="Pollable Mapping Storage"):
-        MappingStorage.__init__(self, name=name)
-        # _polled_tid contains the transaction ID at the last poll.
-        self._polled_tid = ''
-
-    def bind_connection(self, connection):
-        """Returns a storage instance to be used by the given Connection.
-        """
-        return BoundStorage(self)
-
-    def connection_closing(self):
-        """Notifies the storage that a connection is closing.
-        """
-        pass
-
-    def poll_invalidations(self):
-        """Poll the storage for changes by other connections.
-        """
-        new_tid = self._transactions.maxKey()
-
-        if self._polled_tid:
-            if not self._transactions.has_key(self._polled_tid):
-                # This connection is so old that we can no longer enumerate
-                # all the changes.
-                self._polled_tid = new_tid
-                return None
-
-        changed_oids = set()
-        for tid, txn in self._transactions.items(
-                self._polled_tid, new_tid, excludemin=True, excludemax=False):
-            if txn.status == 'p':
-                # This transaction has been packed, so it is no longer
-                # possible to enumerate all changed oids.
-                self._polled_tid = new_tid
-                return None
-            if tid == self._ltid:
-                # ignore the transaction committed by this connection
-                continue
-
-            changes = txn.data
-            # pull in changes from the transaction log
-            for oid, value in changes.iteritems():
-                tid_data = self._data.get(oid)
-                if tid_data is None:
-                    tid_data = BTrees.OOBTree.OOBucket()
-                    self._data[oid] = tid_data
-                tid_data[tid] = changes[oid]
-            changed_oids.update(changes.keys())
-
-        self._polled_tid = new_tid
-        return list(changed_oids)
-
-
-class BoundStorage(PollableMappingStorage):
-    """A PollableMappingStorage used for a specific Connection."""
-
-    def __init__(self, common):
-        PollableMappingStorage.__init__(self, name=common.__name__)
-        # bound storages use the same transaction log as the common storage.
-        self._transactions = common._transactions

Copied: ZODB/branches/shane-poll-invalidations/src/ZODB/tests/MVCCMappingStorage.py (from rev 99492, ZODB/branches/shane-poll-invalidations/src/ZODB/PollableMappingStorage.py)
===================================================================
--- ZODB/branches/shane-poll-invalidations/src/ZODB/tests/MVCCMappingStorage.py	                        (rev 0)
+++ ZODB/branches/shane-poll-invalidations/src/ZODB/tests/MVCCMappingStorage.py	2009-04-25 23:45:05 UTC (rev 99499)
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# Copyright (c) Zope Corporation and Contributors.
+# 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
+#
+##############################################################################
+"""An extension of MappingStorage that depends on polling.
+
+Each Connection has its own view of the database.  Polling updates each
+connection's view.
+"""
+
+import time
+
+import BTrees
+from ZODB.interfaces import IMVCCStorage
+from ZODB.MappingStorage import MappingStorage
+from ZODB.TimeStamp import TimeStamp
+from zope.interface import implements
+
+
+class MVCCMappingStorage(MappingStorage):
+    implements(IMVCCStorage)
+
+    def __init__(self, name="MVCC Mapping Storage"):
+        MappingStorage.__init__(self, name=name)
+        # _polled_tid contains the transaction ID at the last poll.
+        self._polled_tid = ''
+
+    def new_instance(self):
+        """Returns a storage instance that is a view of the same data.
+        """
+        res = MVCCMappingStorage(name=self.__name__)
+        res._transactions = self._transactions
+        return res
+
+    def sync(self, force=False):
+        pass
+
+    def release(self):
+        pass
+
+    def poll_invalidations(self):
+        """Poll the storage for changes by other connections.
+        """
+        new_tid = self._transactions.maxKey()
+
+        if self._polled_tid:
+            if not self._transactions.has_key(self._polled_tid):
+                # This connection is so old that we can no longer enumerate
+                # all the changes.
+                self._polled_tid = new_tid
+                return None
+
+        changed_oids = set()
+        for tid, txn in self._transactions.items(
+                self._polled_tid, new_tid, excludemin=True, excludemax=False):
+            if txn.status == 'p':
+                # This transaction has been packed, so it is no longer
+                # possible to enumerate all changed oids.
+                self._polled_tid = new_tid
+                return None
+            if tid == self._ltid:
+                # ignore the transaction committed by this connection
+                continue
+
+            changes = txn.data
+            # pull in changes from the transaction log
+            for oid, value in changes.iteritems():
+                tid_data = self._data.get(oid)
+                if tid_data is None:
+                    tid_data = BTrees.OOBTree.OOBucket()
+                    self._data[oid] = tid_data
+                tid_data[tid] = changes[oid]
+            changed_oids.update(changes.keys())
+
+        self._polled_tid = new_tid
+        return list(changed_oids)


Property changes on: ZODB/branches/shane-poll-invalidations/src/ZODB/tests/MVCCMappingStorage.py
___________________________________________________________________
Added: svn:mergeinfo
   + 

Copied: ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testMVCCMappingStorage.py (from rev 99492, ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testPollableMappingStorage.py)
===================================================================
--- ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testMVCCMappingStorage.py	                        (rev 0)
+++ ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testMVCCMappingStorage.py	2009-04-25 23:45:05 UTC (rev 99499)
@@ -0,0 +1,164 @@
+##############################################################################
+#
+# Copyright (c) Zope Corporation and Contributors.
+# 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.
+#
+##############################################################################
+
+import unittest
+
+from persistent.mapping import PersistentMapping
+import transaction
+from ZODB.DB import DB
+from ZODB.tests.MVCCMappingStorage import MVCCMappingStorage
+
+
+from ZODB.tests import (
+    BasicStorage,
+    HistoryStorage,
+    IteratorStorage,
+    MTStorage,
+    PackableStorage,
+    RevisionStorage,
+    StorageTestBase,
+    Synchronization,
+    )
+
+class MVCCTests:
+
+    def checkCrossConnectionInvalidation(self):
+        # Verify connections see updated state at txn boundaries.
+        # This will fail if the Connection doesn't poll for changes.
+        db = DB(self._storage)
+        try:
+            c1 = db.open()
+            r1 = c1.root()
+            r1['myobj'] = 'yes'
+            c2 = db.open()
+            r2 = c2.root()
+            self.assert_('myobj' not in r2)
+
+            storage = c1._storage
+            t = transaction.Transaction()
+            t.description = 'invalidation test'
+            storage.tpc_begin(t)
+            c1.commit(t)
+            storage.tpc_vote(t)
+            storage.tpc_finish(t)
+
+            self.assert_('myobj' not in r2)
+            c2.sync()
+            self.assert_('myobj' in r2)
+            self.assert_(r2['myobj'] == 'yes')
+        finally:
+            db.close()
+
+    def checkCrossConnectionIsolation(self):
+        # Verify MVCC isolates connections.
+        # This will fail if Connection doesn't poll for changes.
+        db = DB(self._storage)
+        try:
+            c1 = db.open()
+            r1 = c1.root()
+            r1['alpha'] = PersistentMapping()
+            r1['gamma'] = PersistentMapping()
+            transaction.commit()
+
+            # Open a second connection but don't load root['alpha'] yet
+            c2 = db.open()
+            r2 = c2.root()
+
+            r1['alpha']['beta'] = 'yes'
+
+            storage = c1._storage
+            t = transaction.Transaction()
+            t.description = 'isolation test 1'
+            storage.tpc_begin(t)
+            c1.commit(t)
+            storage.tpc_vote(t)
+            storage.tpc_finish(t)
+
+            # The second connection will now load root['alpha'], but due to
+            # MVCC, it should continue to see the old state.
+            self.assert_(r2['alpha']._p_changed is None)  # A ghost
+            self.assert_(not r2['alpha'])
+            self.assert_(r2['alpha']._p_changed == 0)
+
+            # make root['alpha'] visible to the second connection
+            c2.sync()
+
+            # Now it should be in sync
+            self.assert_(r2['alpha']._p_changed is None)  # A ghost
+            self.assert_(r2['alpha'])
+            self.assert_(r2['alpha']._p_changed == 0)
+            self.assert_(r2['alpha']['beta'] == 'yes')
+
+            # Repeat the test with root['gamma']
+            r1['gamma']['delta'] = 'yes'
+
+            storage = c1._storage
+            t = transaction.Transaction()
+            t.description = 'isolation test 2'
+            storage.tpc_begin(t)
+            c1.commit(t)
+            storage.tpc_vote(t)
+            storage.tpc_finish(t)
+
+            # The second connection will now load root[3], but due to MVCC,
+            # it should continue to see the old state.
+            self.assert_(r2['gamma']._p_changed is None)  # A ghost
+            self.assert_(not r2['gamma'])
+            self.assert_(r2['gamma']._p_changed == 0)
+
+            # make root[3] visible to the second connection
+            c2.sync()
+
+            # Now it should be in sync
+            self.assert_(r2['gamma']._p_changed is None)  # A ghost
+            self.assert_(r2['gamma'])
+            self.assert_(r2['gamma']._p_changed == 0)
+            self.assert_(r2['gamma']['delta'] == 'yes')
+        finally:
+            db.close()
+    
+
+class MVCCMappingStorageTests(
+    StorageTestBase.StorageTestBase,
+    BasicStorage.BasicStorage,
+
+    HistoryStorage.HistoryStorage,
+    IteratorStorage.ExtendedIteratorStorage,
+    IteratorStorage.IteratorStorage,
+    MTStorage.MTStorage,
+    PackableStorage.PackableStorageWithOptionalGC,
+    RevisionStorage.RevisionStorage,
+    Synchronization.SynchronizedStorage,
+    MVCCTests
+    ):
+
+    def setUp(self):
+        self._storage = MVCCMappingStorage()
+
+    def tearDown(self):
+        self._storage.close()
+
+    def checkLoadBeforeUndo(self):
+        pass # we don't support undo yet
+    checkUndoZombie = checkLoadBeforeUndo
+
+
+def test_suite():
+    suite = unittest.makeSuite(MVCCMappingStorageTests, 'check')
+    return suite
+
+if __name__ == "__main__":
+    loader = unittest.TestLoader()
+    loader.testMethodPrefix = "check"
+    unittest.main(testLoader=loader)


Property changes on: ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testMVCCMappingStorage.py
___________________________________________________________________
Added: svn:mergeinfo
   + 

Deleted: ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testPollableMappingStorage.py
===================================================================
--- ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testPollableMappingStorage.py	2009-04-25 23:27:13 UTC (rev 99498)
+++ ZODB/branches/shane-poll-invalidations/src/ZODB/tests/testPollableMappingStorage.py	2009-04-25 23:45:05 UTC (rev 99499)
@@ -1,164 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# 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.
-#
-##############################################################################
-
-import unittest
-
-from persistent.mapping import PersistentMapping
-import transaction
-import ZODB.PollableMappingStorage
-from ZODB.DB import DB
-
-
-from ZODB.tests import (
-    BasicStorage,
-    HistoryStorage,
-    IteratorStorage,
-    MTStorage,
-    PackableStorage,
-    RevisionStorage,
-    StorageTestBase,
-    Synchronization,
-    )
-
-class PollableTests:
-
-    def checkCrossConnectionInvalidation(self):
-        # Verify connections see updated state at txn boundaries.
-        # This will fail if Connection doesn't poll for changes.
-        db = DB(self._storage)
-        try:
-            c1 = db.open()
-            r1 = c1.root()
-            r1['myobj'] = 'yes'
-            c2 = db.open()
-            r2 = c2.root()
-            self.assert_('myobj' not in r2)
-
-            storage = c1._storage
-            t = transaction.Transaction()
-            t.description = 'invalidation test'
-            storage.tpc_begin(t)
-            c1.commit(t)
-            storage.tpc_vote(t)
-            storage.tpc_finish(t)
-
-            self.assert_('myobj' not in r2)
-            c2.sync()
-            self.assert_('myobj' in r2)
-            self.assert_(r2['myobj'] == 'yes')
-        finally:
-            db.close()
-
-    def checkCrossConnectionIsolation(self):
-        # Verify MVCC isolates connections.
-        # This will fail if Connection doesn't poll for changes.
-        db = DB(self._storage)
-        try:
-            c1 = db.open()
-            r1 = c1.root()
-            r1['alpha'] = PersistentMapping()
-            r1['gamma'] = PersistentMapping()
-            transaction.commit()
-
-            # Open a second connection but don't load root['alpha'] yet
-            c2 = db.open()
-            r2 = c2.root()
-
-            r1['alpha']['beta'] = 'yes'
-
-            storage = c1._storage
-            t = transaction.Transaction()
-            t.description = 'isolation test 1'
-            storage.tpc_begin(t)
-            c1.commit(t)
-            storage.tpc_vote(t)
-            storage.tpc_finish(t)
-
-            # The second connection will now load root['alpha'], but due to
-            # MVCC, it should continue to see the old state.
-            self.assert_(r2['alpha']._p_changed is None)  # A ghost
-            self.assert_(not r2['alpha'])
-            self.assert_(r2['alpha']._p_changed == 0)
-
-            # make root['alpha'] visible to the second connection
-            c2.sync()
-
-            # Now it should be in sync
-            self.assert_(r2['alpha']._p_changed is None)  # A ghost
-            self.assert_(r2['alpha'])
-            self.assert_(r2['alpha']._p_changed == 0)
-            self.assert_(r2['alpha']['beta'] == 'yes')
-
-            # Repeat the test with root['gamma']
-            r1['gamma']['delta'] = 'yes'
-
-            storage = c1._storage
-            t = transaction.Transaction()
-            t.description = 'isolation test 2'
-            storage.tpc_begin(t)
-            c1.commit(t)
-            storage.tpc_vote(t)
-            storage.tpc_finish(t)
-
-            # The second connection will now load root[3], but due to MVCC,
-            # it should continue to see the old state.
-            self.assert_(r2['gamma']._p_changed is None)  # A ghost
-            self.assert_(not r2['gamma'])
-            self.assert_(r2['gamma']._p_changed == 0)
-
-            # make root[3] visible to the second connection
-            c2.sync()
-
-            # Now it should be in sync
-            self.assert_(r2['gamma']._p_changed is None)  # A ghost
-            self.assert_(r2['gamma'])
-            self.assert_(r2['gamma']._p_changed == 0)
-            self.assert_(r2['gamma']['delta'] == 'yes')
-        finally:
-            db.close()
-    
-
-class PollableMappingStorageTests(
-    StorageTestBase.StorageTestBase,
-    BasicStorage.BasicStorage,
-
-    HistoryStorage.HistoryStorage,
-    IteratorStorage.ExtendedIteratorStorage,
-    IteratorStorage.IteratorStorage,
-    MTStorage.MTStorage,
-    PackableStorage.PackableStorageWithOptionalGC,
-    RevisionStorage.RevisionStorage,
-    Synchronization.SynchronizedStorage,
-    PollableTests
-    ):
-
-    def setUp(self):
-        self._storage = ZODB.PollableMappingStorage.PollableMappingStorage()
-
-    def tearDown(self):
-        self._storage.close()
-
-    def checkLoadBeforeUndo(self):
-        pass # we don't support undo yet
-    checkUndoZombie = checkLoadBeforeUndo
-
-
-def test_suite():
-    suite = unittest.makeSuite(PollableMappingStorageTests, 'check')
-    return suite
-
-if __name__ == "__main__":
-    loader = unittest.TestLoader()
-    loader.testMethodPrefix = "check"
-    unittest.main(testLoader=loader)



More information about the Checkins mailing list