[ZODB-Dev] historicalRevision for subobjects

Tim Peters tim at zope.com
Mon May 2 13:37:35 EDT 2005


[Christian Heimes]
> ...
> Christian Theune and me have implemented a diffed history feature for
> Archetypes based content types. It's part of ATContentTypes and is meant
> to help reviewers to see the differences between different revisions of
> an object. The code is using the method OFS.History.historicalRevision +
> db().oldstate() to iterate over the ZODB revisions of the object.
>
> The code was working very well because we were using AttributeStorage. AS
> stores the data of Archetype fields as a simple attribute on the object.
> For security and performance reasons I have implemented annotation
> storage that is using Zope3 style attribute annotations to store the data
> in an OOBTree attached to the object. With AnnotationStorage the history
> isn't working any more because historicalRevision() returns only an older
> version of the object but *not* older versions of its subobjects like the
> btree. Even trying to get the different revisions of the oobtree didn't
> help. The symptoms were the same. I assume I have to get the revisions of
> the btree bucket or choose a different path.

Yes, under the covers "a BTree" is an arbitrarily large graph (rooted DAG --
directed and acyclic) of BTree and Bucket objects.  Each such object in a
BTree graph has its own history (each is a distinct "first-class" persistent
object in its own right).  The object most app code thinks of as being "the
BTree" is just the root of this arbitrarily large object graph, and the
other objects in the graph generally aren't directly visible to application
code.

It's common as mud, e.g., that adding a new key to a BTree doesn't change
its root object; then fetching an older revision of the root will still
point to the current revision of the bucket to which that key was added.
Indeed, BTrees are designed to make this so:  if every key addition mutated
the root object, any two transactions adding to a single BTree concurrently
would suffer a write conflict (as does indeed happen if using, e.g., a
PersistentMapping or PersistentList instead).

> I had the idea of getting a snapshot of the entire ZODB for a given
> transaction serial number but I don't know how to get it. Is this
> possible?

Sorry, don't know.  I don't expect a reasonable way exists in ZODB 3.2.  It
may be possible to trick ZODB 3.3/3.4's MVCC machinery into delivering a
consistent past view (provided it hasn't been packed away!), but if so it's
not an exposed mechanism.  You might want to stare at the code involving
Connection._txn_time.



More information about the ZODB-Dev mailing list