[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