durusmail: durus-users: Mutating __class__ of persistent classes
Mutating __class__ of persistent classes
2006-02-08
2006-02-08
2006-02-08
2006-02-09
Mutating __class__ of persistent classes
David Binger
2006-02-09
When you change the class of a persistent instance X,
it is natural to think that you need to call X._p_note_change()
and commit the change to the database.  This saves
a new version of the object in the storage, along with
the new state.

This does not, however, complete the job.  You must also
call Y._p_note_change() on every persistent instance that
contains a reference to X, and you must also commit those
changes.

The reason for this second step is not obvious, so I'll take
this opportunity to offer an explanation.

When you pickle an object, the pickle includes everything that
the object references.  For a big, tangled, object graph, this would
normally include just about every object, so the pickle would be
huge.  This would be bad for a system like Durus.
The trick in Durus, and ZODB, is that the pickler is modified
to stop the "crawl" of the object graph whenever it finds a reference
to an instance of Persistent.  Instead of recursively crawling through
the reference,  it just stops and (essentially) puts the pair
(, )
in place of the actual reference.

When the referring object's state is loaded, the specially modified
unpickler does something special when it hits this (class, oid) pair.
Instead of just creating the tuple, it creates a ghost instance of the
named class with the given oid.  Thus it creates a quick ghost for the
instance without having to go back to the storage again to
find out what the class is that is actually saved for the object with
that oid.

So, if Y refers to X, the pickle of Y contains a tuple that records
the class of X, and it is this reference may be used to create an
initial ghost version of X.    That's why changing the class of X
requires you to save new pickles of both X and Y.






reply