[ZODB-Dev] Unexpected behavior of a volatile property

Patrick K. O'Brien pobrien@orbtech.com
Thu, 11 Oct 2001 11:23:40 -0500


I'm seeing some behavior I don't understand. I'm playing around with the
sample application I'm creating. As part of this, I'm generating some test
objects. When I generated 5000 of them, assigning a volatile property
(_v_key), the first 1730 objects "lost" this property -- hasattr(object,
'_v_key') fails -- the remaining objects all have the property. How can this
happen? This is during the session where the objects are created, not in
between sessions (where you would expect the volatile property to be ...
volatile).

Bear with me as I show the different parts of the code so you can understand
what is happening. These are snippets from various modules.

nk = NoteKeeper()
fs = nk.folderSet

# Load sample data. Assumes all containers are empty, since we deleted
files.

f = {}
for n in range(5000):
    name = 'New Folder ' + str(n)
    f[n] = fs.new(name)

commit()


# Supporting classes from other modules:

class Folder(AlphaPersistent):
    """Folder class."""

    def __init__(self, name=''):
        """Create a Folder instance."""
        self.name = name


class FolderSet(SetManager):
    """FolderSet class."""

    def __init__(self):
        """Create a FolderSet instance."""
        SetManager.__init__(self, managedClass=Folder)

    def new(self, name='New Folder'):
        """Return a new Folder instance."""
        return SetManager.new(self, name=name)


class SetManager(AlphaPersistent):
    """SetManager class."""

    def __init__(self, managedClass):
        """Create a SetManager instance.

        managedClass is the class whose instances will be managed."""
        self.container = IOBTree()
        self.managedClass = managedClass
        transaction.commit(1)

    def new(self, *args, **kwds):
        """Return a new managedClass instance."""
        object = self.managedClass(*args, **kwds)
        key = keymanager.new()
        while not self.container.insert(key, object):
            key = keymanager.new()
        object._v_key = key
        transaction.commit(1)
        return object


# keymanager.py module:

import whrandom

# Grab the functions we want, so we can delete the whrandom module
reference.
choice = whrandom.choice
randint = whrandom.randint

# When whrandom is imported, a random number generator is created and seeded
# with values based on the current time. So we delete the module reference
to
# allow other imports of keymanager to get new seeds.
del whrandom


def new():
    """Return a random integer for use as a key value.
    The return value can range from -2147483647 to 2147483647."""
    global choice, randint
    maxint = 2147483647
    # The implementation of randint() increments the second parameter.
    # So we need to decrement it here, otherwise we get an OverflowError.
    return choice((-1, 1)) * randint(1, maxint-1)


Can anyone explain what is going on? I didn't expect a _v_ property to be
volatile within a session, I just expected it to not be made persistent and
to not trigger conflicts. Am I mistaken?

---
Patrick K. O'Brien
Orbtech (http://www.orbtech.com)
"I am, therefore I think."