[TransWarp] storage: order of actions on commit
Phillip J. Eby
pje at telecommunity.com
Tue Feb 18 17:29:31 EST 2003
At 12:24 PM 2/18/03 +0100, Ulrich Eck wrote:
>creating/retrieving folders works nice and i use the way you described for
>creating oid's:
>
> def _new(self, ob):
> if ob.parent is None:
> folder = ob.name
> else:
> folder = '%s.%s' % (self.oidFor(ob.parent)[0], ob.name)
> folder = naming.CompositeName.parse(folder, imapFolderPath)
If you're doing what I think you're doing there, then:
folder = imapFolderPath(folder)
would suffice. The only reason to use CompositeName.parse is if you expect
there to be another '/'-separated namespace in the name, and that won't be
the case unless the object's name contains a '/' (presumably an invalid
character).
I would also note, by the way, that there's little point to parsing the
name and then making it also a tuple to serve as an oid. Simply taking the
unparsed folder name string as an oid would probably suffice, unless you
have needs I don't know about. I don't recommend mixing folders and
message retrieval in the same DM, because it's just going to clutter a lot
of your methods with conditional code.
> ob._p_oid = (folder, )
>
> print '_new', folder
> conn = self.connection
> status, body = conn.create(str(folder))
Notice here that you're now unparsing the previously parsed folder
name... Keeping it a string in the first place would of course be easier...
> if not status == 'OK':
> raise Exception, 'Cannot create Folder: %s' % folder
>
> return ob._p_oid
>
>
>
>so the next questions are:
>
>- How should deleting objects be implemented ??
> i haven't found anything in the code/interfaces that says something about
> how to implement it. probably the Element is responsible to delete itself
> .. but are there any methods that should be implemented in the dm to
> support that ?
Deletion needs to be handled by a DM method, not an Element
method. Elements don't know how they're stored, so they can't delete
themselves. If you have a composite relationship where an object can't
exist once it's removed from its container, then the _save() method should
treat that as a deletion, and remove the deleted object from the DM's
cache. For other types of deletion, it's an application-level operation,
and so is directed to the DM.
Perhaps I should add a 'delItem()' method to EntityDM, but of course it
wouldn't do anything, because that's what you would need to fill in. So
I'm sort of +0 on it for now.
>- Is there any way to determine which values of an element have been
>changed ??
> or is it intended to just save the complete state of an object on _save() ?
You can always call the DM's _load() method to reload its original state
and compare, or you can stuff a memento of your choosing into the state at
_load() time. A simple way to do that is to stick the uninterpreted
database rows or whatever into a special attribute.
But I think that in most cases, doing that kind of tracking is more work
than it's worth; certainly I'd consider it a premature optimization if you
aren't sure you need it.
I can think of one place where I might do it, though... LDAP group
membership. Large LDAP groups are slow to load over-the-wire, so I'd use
QueryLink objects for their membership fields, and a LazyLoader (see
peak.storage.lazy_loader) on the LDAP user objects corresponding field for
what groups they belong to. The LazyLoader would actually load a list by
querying for all the groups that the user was a member of, and it would
also hide a memento of the groups' DNs in the user object. Then, the
_save() operation for the user object would actually be the thing that
added or removed the user from a particular group, rather than a _save()
operation on the group. This would mean I'd never have to load a group's
entire membership just to add or remove a user; I could just send
modifications to the LDAP server.
The way you use a LazyLoader is to subclass it and add the behavior you
want, then put an instance of it into the object's state at _load()
time. If the attribute is accessed via a Feature, the LazyLoader's
'_load()' method will be called, and it will have the opportunity to
replace itself in the object's state.
Your _save() method will need to check before saving such an attribute, to
ensure that it's not the LazyLoader itself. If it is a LazyLoader
instance, then you will know the value has not been changed or even accessed.
More information about the PEAK
mailing list