[PEAK] Recursive __setstate__ call
Radek Kanovsky
rk at dat.cz
Sat Apr 17 10:19:32 EDT 2004
On Fri, Apr 16, 2004 at 09:25:22PM -0400, Phillip J. Eby wrote:
> At 02:58 PM 4/16/04 +0200, Radek Kanovsky wrote:
> >On Thu, Mar 25, 2004 at 11:52:02AM -0500, Phillip J. Eby wrote:
> >
> >> So, it's almost certainly something wrong with the state management logic
> >> in _persistence.c. It might be possible to workaround by having
> >> 'setstate()' force ob._p_changed to a particular state before calling
> >> __setstate__, but I'm not sure.
> >
> >Investigating persistence code I am almost sure that it is not
> >possible to revive ghost object without setstate invocation as
> >undesirable side effect. Any operation on ghost causes immediate
> >_PyPersist_Load() -> setstate() calling.
>
> What would happen if you temporarily set ob._p_jar to an object with a
> 'setstate()' method that set the desired state?
Yes! It is the right trick that doesn't strike me. I have changed
QueryDM.__getitem__ and QueryDM.setstate methods following way:
class _noDM :
def setstate (self, ob) :
pass
_noDM = _noDM()
class QueryDM (TransactionComponent) :
[...]
def __getitem__(self, oid, state=None):
if self.resetStatesAfterTxn:
# must always be used in a txn
self.joinedTxn
ob = self.cache.get(oid,self)
if ob is not self:
if state is not None and ob._p_state == 3 :
# Revive ghost
ob._p_jar = _noDM
ob.__setstate__(state)
ob._p_jar = self
return ob
ob = self._ghost(oid,state)
if isinstance(ob,Persistent):
ob._p_jar = self
ob._p_oid = oid
if state is None:
ob._p_deactivate()
else:
ob.__setstate__(state)
self.cache[oid] = ob
return ob
def setstate(self, ob):
if self.resetStatesAfterTxn:
# must always be used in a txn
self.joinedTxn
oid = ob._p_oid
assert oid is not None
state = self._load(oid,ob)
ob._p_jar = _noDM
ob.__setstate__(state)
ob._p_jar = self
All my unit tests passed without error so I don't expect some other problems.
Thanks for help.
RadekK
More information about the PEAK
mailing list