[Zodb-checkins] SVN: ZODB/trunk/src/ Bug Fixed:

Jim Fulton jim at zope.com
Wed Jun 10 14:42:29 EDT 2009


Log message for revision 100808:
  Bug Fixed:
    Saving indexes for large file storages failed (with the error:
    RuntimeError: maximum recursion depth exceeded).  This can cause a
    FileStorage to fail to start because it gets an error trying to save
    its index.
  

Changed:
  U   ZODB/trunk/src/CHANGES.txt
  U   ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
  U   ZODB/trunk/src/ZODB/FileStorage/tests.py

-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt	2009-06-10 18:14:53 UTC (rev 100807)
+++ ZODB/trunk/src/CHANGES.txt	2009-06-10 18:42:24 UTC (rev 100808)
@@ -8,6 +8,11 @@
 Bugs Fixed
 ----------
 
+- Saving indexes for large file storages failed (with the error:
+  RuntimeError: maximum recursion depth exceeded).  This can cause a
+  FileStorage to fail to start because it gets an error trying to save
+  its index.
+
 - Sizes of new objects weren't added to the object cache size
   estimation, causing the object-cache size limiting feature to let
   the cache grow too large when many objects were added.

Modified: ZODB/trunk/src/ZODB/FileStorage/FileStorage.py
===================================================================
--- ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2009-06-10 18:14:53 UTC (rev 100807)
+++ ZODB/trunk/src/ZODB/FileStorage/FileStorage.py	2009-06-10 18:42:24 UTC (rev 100808)
@@ -33,6 +33,7 @@
 from ZODB.utils import p64, u64, z64
 
 import base64
+import BTrees.OOBTree
 import errno
 import logging
 import os
@@ -248,8 +249,17 @@
         f=open(tmp_name,'wb')
         p=Pickler(f,1)
 
-        info={'index': self._index, 'pos': self._pos}
+        # Pickle the index buckets first to avoid deep recursion:
+        buckets = []
+        bucket = self._index._data._firstbucket
+        while bucket is not None:
+            buckets.append(bucket)
+            bucket = bucket._next
+        buckets.reverse()
 
+        info=BTrees.OOBTree.Bucket(dict(
+            _buckets=buckets, index=self._index, pos=self._pos))
+
         p.dump(info)
         f.flush()
         f.close()

Modified: ZODB/trunk/src/ZODB/FileStorage/tests.py
===================================================================
--- ZODB/trunk/src/ZODB/FileStorage/tests.py	2009-06-10 18:14:53 UTC (rev 100807)
+++ ZODB/trunk/src/ZODB/FileStorage/tests.py	2009-06-10 18:42:24 UTC (rev 100808)
@@ -125,6 +125,49 @@
     >>> db.close()
     """
 
+def _save_index():
+    """
+
+_save_index can fail for large indexes.
+
+    >>> import ZODB.utils
+    >>> fs = ZODB.FileStorage.FileStorage('data.fs')
+
+    >>> t = transaction.begin()
+    >>> fs.tpc_begin(t)
+    >>> oid = 0
+    >>> for i in range(5000):
+    ...     oid += (1<<16)
+    ...     _ = fs.store(ZODB.utils.p64(oid), ZODB.utils.z64, 'x', '', t)
+    >>> fs.tpc_vote(t)
+    >>> fs.tpc_finish(t)
+
+    >>> import sys
+    >>> old_limit = sys.getrecursionlimit()
+    >>> sys.setrecursionlimit(50)
+    >>> fs._save_index()
+
+Make sure we can restore:
+
+    >>> import logging
+    >>> handler = logging.StreamHandler(sys.stdout)
+    >>> logger = logging.getLogger('ZODB.FileStorage')
+    >>> logger.setLevel(logging.DEBUG)
+    >>> logger.addHandler(handler)
+    >>> index, pos, tid = fs._restore_index()
+    >>> index.items() == fs._index.items()
+    True
+    >>> pos, tid = fs._pos, fs._tid
+
+cleanup
+
+    >>> logger.setLevel(logging.NOTSET)
+    >>> logger.removeHandler(handler)
+    >>> sys.setrecursionlimit(old_limit)
+
+    """
+
+
 def test_suite():
     return unittest.TestSuite((
         doctest.DocFileSuite(



More information about the Zodb-checkins mailing list