[Zope] Generating unique keys

gtk gtk@well.com
Sat, 30 Oct 1999 06:12:09 +1000


Excuse the massive quote, but I need all the context:

> But What happens when two ID's are generated at exactly the same time
through
> different threads?
>
> I found a gem that I thinks answers my queries at:
>     http://www.zope.org/Documentation/Developer/Models/ZODB/ZODB_Doc.html
>
> "When a transaction is to be committed, all of the objects modified by
>  the transaction are checked to see if they have been invalidated. If
>  any objects modified by the transaction have been invalidated, then the
>  transaction is aborted and a ZODB3.ConflictError exception is raised.
>  An application (e.g. the Python Object Publisher) should catch the
>  ZODB3.Conflict exception and attempt to re-execute the transaction."
>
> So an object can simply have an integer counter that is incremented
> as necessary, and if two threads try to modify the counter at about the
same
> time, the one that tries to commit last will rollback and be reexecuted.
> If this is true, its so trivial a counter class and locking is totally
> unnecessary :-) And it should work with ZEO as well from what I understand
> of its architecture.

Okay, so a method which tries to maintain sub-objects with incrementing ids
could do something like this:

    def xmlrpc_manage_addNi(self, title=''):
        """Anyone ever noticed that without a doc string, Zope complains
LOTS?"""
        try:
            while 1:
                self.lastNi = self.lastNi + 1
                id = str(self.lastNi)
                if hasattr(self, id): # there's someone else in the system!
                    continue
                v = self._checkId(id) # if someone slips in here, it'll
still break :/
                break

            object = Ni(id, title)
            if v is not None: id = v
            try:    t = object.meta_type
            except: t = None
            self._objects = self._objects + ({ 'id': id, 'meta_type':t},)
            self._setOb(id,object)
            object = self._getOb(id)
            object.manage_afterAdd(object, self)

I haven't tried using multi-threading to force the race condition yet, but I
suspect that it's still possible for two calls to concurrently march through
the method and still try and commit the same id. How the hell do you catch
the ZODB3.ConflictError if this happens?

I guess I'm not sold on the whole "the one that tries to commit last will
rollback and be reexecuted" thing.

Regards,
Garth.

--
<gtk@well.com>
>