[Zodb-checkins] SVN: ZODB/trunk/src/ZODB/ Non-ghostifiable
(persistent classes) objects load their state right
Jim Fulton
jim at zope.com
Wed Jun 6 09:14:48 EDT 2007
Log message for revision 76408:
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
alreadey being loaded when necessary.
Changed:
U ZODB/trunk/src/ZODB/Connection.py
U ZODB/trunk/src/ZODB/tests/testpersistentclass.py
-=-
Modified: ZODB/trunk/src/ZODB/Connection.py
===================================================================
--- ZODB/trunk/src/ZODB/Connection.py 2007-06-06 13:14:40 UTC (rev 76407)
+++ ZODB/trunk/src/ZODB/Connection.py 2007-06-06 13:14:47 UTC (rev 76408)
@@ -105,6 +105,12 @@
# recently used. Its API is roughly that of a dict, with
# additional gc-related and invalidation-related methods.
self._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
@@ -225,6 +231,9 @@
return obj
obj = self._added.get(oid, None)
if obj is not None:
+ return obj
+ obj = self._pre_cache.get(oid, None)
+ if obj is not None:
return obj
# This appears to be an MVCC violation because we are loading
@@ -233,11 +242,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/trunk/src/ZODB/tests/testpersistentclass.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testpersistentclass.py 2007-06-06 13:14:40 UTC (rev 76407)
+++ ZODB/trunk/src/ZODB/tests/testpersistentclass.py 2007-06-06 13:14:47 UTC (rev 76408)
@@ -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