[Zodb-checkins] SVN: ZODB/branches/3.6/src/ZODB/ merged jim's fix
(r76408) for the caching problem showing up in the zclasses tests:
Andreas Zeidler
az at zitc.de
Thu Jun 28 09:19:37 EDT 2007
Log message for revision 77178:
merged jim's fix (r76408) for the caching problem showing up in the zclasses tests:
Non-ghostifiable (persistent classes) objects load their state right
away -- even before they are placed in the cache. This causes a
problem if the object's state has a (direct or indirect) reference to
it. Added a pre-cache that allows the connection to return objects
already being loaded when necessary.
Changed:
U ZODB/branches/3.6/src/ZODB/Connection.py
U ZODB/branches/3.6/src/ZODB/tests/testpersistentclass.py
-=-
Modified: ZODB/branches/3.6/src/ZODB/Connection.py
===================================================================
--- ZODB/branches/3.6/src/ZODB/Connection.py 2007-06-28 12:35:43 UTC (rev 77177)
+++ ZODB/branches/3.6/src/ZODB/Connection.py 2007-06-28 13:19:37 UTC (rev 77178)
@@ -88,6 +88,12 @@
self._version = version
self._cache = cache = PickleCache(self, cache_size)
+
+ # The pre-cache is used by get to avoid infinite loops when
+ # objects immediately load their state whern they get their
+ # persistent data set.
+ self._pre_cache = {}
+
if version:
# Caches for versions end up empty if the version
# is not used for a while. Non-version caches
@@ -191,6 +197,9 @@
if self._opened is None:
raise ConnectionStateError("The database connection is closed")
+ obj = self._pre_cache.get(oid, None)
+ if obj is not None:
+ return obj
obj = self._cache.get(oid, None)
if obj is not None:
return obj
@@ -201,11 +210,14 @@
p, serial = self._storage.load(oid, self._version)
obj = self._reader.getGhost(p)
+ # Avoid infiniate loop if obj tries to load its state before
+ # it is added to the cache and it's state refers to it.
+ self._pre_cache[oid] = obj
obj._p_oid = oid
obj._p_jar = self
obj._p_changed = None
obj._p_serial = serial
-
+ self._pre_cache.pop(oid)
self._cache[oid] = obj
return obj
Modified: ZODB/branches/3.6/src/ZODB/tests/testpersistentclass.py
===================================================================
--- ZODB/branches/3.6/src/ZODB/tests/testpersistentclass.py 2007-06-28 12:35:43 UTC (rev 77177)
+++ ZODB/branches/3.6/src/ZODB/tests/testpersistentclass.py 2007-06-28 13:19:37 UTC (rev 77178)
@@ -21,8 +21,29 @@
import ZODB.tests.util
import transaction
from zope.testing import doctest
+import ZODB.persistentclass
+def class_with_circular_ref_to_self():
+ """
+It should be possible for a class to reger to itself.
+ >>> class C:
+ ... __metaclass__ = ZODB.persistentclass.PersistentMetaClass
+
+ >>> C.me = C
+ >>> db = ZODB.tests.util.DB()
+ >>> conn = db.open()
+ >>> conn.root()['C'] = C
+ >>> transaction.commit()
+
+ >>> conn2 = db.open()
+ >>> C2 = conn2.root()['C']
+ >>> c = C2()
+ >>> c.__class__.__name__
+ 'C'
+
+"""
+
# XXX need to update files to get newer testing package
class FakeModule:
def __init__(self, name, dict):
@@ -44,6 +65,7 @@
return unittest.TestSuite((
doctest.DocFileSuite("../persistentclass.txt",
setUp=setUp, tearDown=tearDown),
+ doctest.DocTestSuite(setUp=setUp, tearDown=tearDown),
))
if __name__ == '__main__':
More information about the Zodb-checkins
mailing list