[Zodb-checkins] SVN: ZODB/trunk/src/ZODB/ Added a lastInvalidations that a ZEO server can use to populate its

Jim Fulton jim at zope.com
Mon Mar 26 18:04:47 EDT 2007


Log message for revision 73654:
  Added a lastInvalidations that a ZEO server can use to populate its
  invalidation queue.
  

Changed:
  U   ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
  U   ZODB/trunk/src/ZODB/tests/testFileStorage.py

-=-
Modified: ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2007-03-26 22:04:44 UTC (rev 73653)
+++ ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2007-03-26 22:04:46 UTC (rev 73654)
@@ -1390,6 +1390,25 @@
         """Return transaction id for last committed transaction"""
         return self._ltid
 
+    def lastInvalidations(self, count):
+        file = self._file
+        seek = file.seek
+        read = file.read
+        self._lock_acquire()
+        try:
+            pos = self._pos
+            while count > 0 and pos > 4:
+                count -= 1
+                seek(pos-8)
+                pos = pos - 8 - u64(read(8))
+
+            seek(0)
+            return [(trans.tid, [(r.oid, r.version) for r in trans])
+                    for trans in FileIterator(self._file, pos=pos)]
+        finally:
+            self._lock_release()
+        
+
     def lastTid(self, oid):
         """Return last serialno committed for object oid.
 
@@ -1822,7 +1841,7 @@
     _ltid = z64
     _file = None
 
-    def __init__(self, file, start=None, stop=None):
+    def __init__(self, file, start=None, stop=None, pos=4L):
         if isinstance(file, str):
             file = open(file, 'rb')
         self._file = file
@@ -1830,7 +1849,7 @@
             raise FileStorageFormatError(file.name)
         file.seek(0,2)
         self._file_size = file.tell()
-        self._pos = 4L
+        self._pos = pos
         assert start is None or isinstance(start, str)
         assert stop is None or isinstance(stop, str)
         if start:

Modified: ZODB/trunk/src/ZODB/tests/testFileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testFileStorage.py	2007-03-26 22:04:44 UTC (rev 73653)
+++ ZODB/trunk/src/ZODB/tests/testFileStorage.py	2007-03-26 22:04:46 UTC (rev 73654)
@@ -14,7 +14,9 @@
 import os, unittest
 import transaction
 import ZODB.FileStorage
+import ZODB.tests.util
 from ZODB import POSException
+from ZODB import DB
 
 from ZODB.tests import StorageTestBase, BasicStorage, \
      TransactionalUndoStorage, VersionStorage, \
@@ -192,7 +194,6 @@
         # Now the cached 'oid' value is ignored:  verify that this is so.
         import cPickle as pickle
         from ZODB.utils import z64
-        from ZODB.DB import DB
 
         # Create some data.
         db = DB(self._storage)
@@ -281,7 +282,6 @@
         # global.
         import time
 
-        from ZODB.DB import DB
         from ZODB.utils import U64, p64
         from ZODB.FileStorage.format import CorruptedError
 
@@ -324,7 +324,6 @@
             self.fail("expected CorruptedError")
 
     def check_record_iternext(self):
-        from ZODB.DB import DB
 
         db = DB(self._storage)
         conn = db.open()
@@ -351,7 +350,6 @@
             else:
                 self.assertNotEqual(next_oid, None)
 
-
 class FileStorageRecoveryTest(
     StorageTestBase.StorageTestBase,
     RecoveryStorage.RecoveryStorage,
@@ -409,8 +407,6 @@
 def testTimeTravelOnOpen():
     """
     >>> from ZODB.FileStorage import FileStorage
-    >>> from ZODB.DB import DB
-    >>> import transaction
     >>> from zope.testing.loggingsupport import InstalledHandler
 
     Arrange to capture log messages -- they're an important part of
@@ -484,6 +480,55 @@
     >>> handler.uninstall()
     """
 
+def lastInvalidations():
+    """
+
+The last invalidations method is used by a storage server to pupulate
+it's data structure of recent invalidations.  The lastInvalidations
+method is passed a count and must return up to count number of the
+most recent transactions.
+
+We'll create a FileStorage and populate it with some data, keeping
+track of the transactions along the way:
+
+    >>> fs = ZODB.FileStorage.FileStorage('t.fs', create=True)
+    >>> db = DB(fs)
+    >>> conn = db.open()
+    >>> from persistent.dict import PersistentDict
+    >>> last = []
+    >>> for i in range(100):
+    ...     conn.root()[i] = PersistentDict()
+    ...     transaction.commit()
+    ...     last.append(fs.lastTransaction())
+
+Now, we can call lastInvalidations on it:
+
+    >>> invalidations = fs.lastInvalidations(10)
+    >>> [t for (t, oids) in invalidations] == last[-10:]
+    True
+
+    >>> from ZODB.utils import u64
+    >>> [[u64(oid) for (oid, version) in oids]
+    ...  for (i, oids) in invalidations]
+    ... # doctest: +NORMALIZE_WHITESPACE
+    [[0L, 91L], [0L, 92L], [0L, 93L], [0L, 94L], [0L, 95L],
+     [0L, 96L], [0L, 97L], [0L, 98L], [0L, 99L], [0L, 100L]]
+
+If we ask for more transactions than there are, we'll get as many as
+there are:
+
+    >>> len(fs.lastInvalidations(1000))
+    101
+
+Of course, calling lastInvalidations on an empty storage refturns no data:
+
+    >>> fs.close()
+    >>> fs = ZODB.FileStorage.FileStorage('t.fs', create=True)
+    >>> list(fs.lastInvalidations(10))
+    []
+
+    """
+
 def test_suite():
     from zope.testing import doctest
 
@@ -491,7 +536,8 @@
     for klass in [FileStorageTests, Corruption.FileStorageCorruptTests,
                   FileStorageRecoveryTest, SlowFileStorageTest]:
         suite.addTest(unittest.makeSuite(klass, "check"))
-    suite.addTest(doctest.DocTestSuite())
+    suite.addTest(doctest.DocTestSuite(setUp=ZODB.tests.util.setUp,
+                                       tearDown=ZODB.tests.util.tearDown))
     return suite
 
 if __name__=='__main__':



More information about the Zodb-checkins mailing list