[Zodb-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 Zodb-checkins
mailing list