Ejemplo n.º 1
0
static void
Per_dealloc(cPersistentObject *self)
{
    if (self->state >= 0)
    {
        /* If the cache has been cleared, then a non-ghost object
            isn't in the ring any longer.
        */
        if (self->ring.r_next != NULL)
        {
            /* if we're ghostifying an object, we better have some non-ghosts */
            assert(self->cache->non_ghost_count > 0);
            self->cache->non_ghost_count--;
            self->cache->total_estimated_size -=
                _estimated_size_in_bytes(self->estimated_size);
            ring_del(&self->ring);
        }
    }

    if (self->cache)
        cPersistenceCAPI->percachedel(self->cache, self->oid);
    Py_XDECREF(self->cache);
    Py_XDECREF(self->jar);
    Py_XDECREF(self->oid);
    Py_TYPE(self)->tp_free(self);
}
Ejemplo n.º 2
0
static void
ghostify(cPersistentObject *self)
{
    PyObject **dictptr;

    /* are we already a ghost? */
    if (self->state == cPersistent_GHOST_STATE)
        return;

    /* Is it ever possible to not have a cache? */
    if (self->cache == NULL)
    {
        self->state = cPersistent_GHOST_STATE;
        return;
    }

    if (self->ring.r_next == NULL)
    {
        /* There's no way to raise an error in this routine. */
#ifdef Py_DEBUG
        fatal_1350(self, "ghostify", "claims to be in a cache but isn't");
#else
        return;
#endif
    }

    /* If we're ghostifying an object, we better have some non-ghosts. */
    assert(self->cache->non_ghost_count > 0);
    self->cache->non_ghost_count--;
    self->cache->total_estimated_size -=
        _estimated_size_in_bytes(self->estimated_size);
    ring_del(&self->ring);
    self->state = cPersistent_GHOST_STATE;
    dictptr = _PyObject_GetDictPtr((PyObject *)self);
    if (dictptr && *dictptr)
    {
        Py_DECREF(*dictptr);
        *dictptr = NULL;
    }

    /* We remove the reference to the just ghosted object that the ring
    * holds.  Note that the dictionary of oids->objects has an uncounted
    * reference, so if the ring's reference was the only one, this frees
    * the ghost object.  Note further that the object's dealloc knows to
    * inform the dictionary that it is going away.
    */
    Py_DECREF(self);
}
Ejemplo n.º 3
0
/* Load the state of the object, unghostifying it.  Upon success, return 1.
 * If an error occurred, re-ghostify the object and return -1.
 */
static int
unghostify(cPersistentObject *self)
{
    if (self->state < 0 && self->jar)
    {
        PyObject *r;

        /* Is it ever possible to not have a cache? */
        if (self->cache)
        {
            /* Create a node in the ring for this unghostified object. */
            self->cache->non_ghost_count++;
            self->cache->total_estimated_size += 
                _estimated_size_in_bytes(self->estimated_size);
            ring_add(&self->cache->ring_home, &self->ring);
            Py_INCREF(self);
        }
        /* set state to CHANGED while setstate() call is in progress
            to prevent a recursive call to _PyPersist_Load().
        */
        self->state = cPersistent_CHANGED_STATE;
        /* Call the object's __setstate__() */
        r = PyObject_CallMethod(self->jar, "setstate", "O", (PyObject *)self);
        if (r == NULL)
        {
            ghostify(self);
            return -1;
        }
        self->state = cPersistent_UPTODATE_STATE;
        Py_DECREF(r);
        if (self->cache && self->ring.r_next == NULL)
        {
#ifdef Py_DEBUG
            fatal_1350(self, "unghostify",
                     "is not in the cache despite that we just "
                     "unghostified it");
#else
            PyErr_Format(PyExc_SystemError, "object at %p with type "
                       "%.200s not in the cache despite that we just "
                       "unghostified it", self, Py_TYPE(self)->tp_name);
            return -1;
#endif
        }
    }
    return 1;
}
Ejemplo n.º 4
0
static void
ghostify(cPersistentObject *self)
{
    PyObject **dictptr, *slotnames;

    /* are we already a ghost? */
    if (self->state == cPersistent_GHOST_STATE)
        return;

    /* Is it ever possible to not have a cache? */
    if (self->cache == NULL) 
    {
        self->state = cPersistent_GHOST_STATE;
        return;
    }

    if (self->ring.r_next == NULL)
    {
        /* There's no way to raise an error in this routine. */
#ifdef Py_DEBUG
        fatal_1350(self, "ghostify", "claims to be in a cache but isn't");
#else
        return;
#endif
    }

    /* If we're ghostifying an object, we better have some non-ghosts. */
    assert(self->cache->non_ghost_count > 0);
    self->cache->non_ghost_count--;
    self->cache->total_estimated_size -= 
        _estimated_size_in_bytes(self->estimated_size);
    ring_del(&self->ring);
    self->state = cPersistent_GHOST_STATE;

    /* clear __dict__ */
    dictptr = _PyObject_GetDictPtr((PyObject *)self);
    if (dictptr && *dictptr)
    {
        Py_DECREF(*dictptr);
        *dictptr = NULL;
    }

    /* clear all slots besides _p_*
     * ( for backward-compatibility reason we do this only if class does not
     *   override __new__ ) */
    if (Py_TYPE(self)->tp_new == Pertype.tp_new)
    {
        slotnames = pickle_slotnames(Py_TYPE(self));
        if (slotnames && slotnames != Py_None)
        {
            int i;

            for (i = 0; i < PyList_GET_SIZE(slotnames); i++)
            {
                PyObject *name;
                char *cname;
                int is_special;

                name = PyList_GET_ITEM(slotnames, i);
#ifdef PY3K
                if (PyUnicode_Check(name))
                {
                    PyObject *converted = convert_name(name);
                    cname = PyBytes_AS_STRING(converted);
#else
                if (PyBytes_Check(name))
                {
                    cname = PyBytes_AS_STRING(name);
#endif
                    is_special = !strncmp(cname, "_p_", 3);
#ifdef PY3K
                    Py_DECREF(converted);
#endif
                    if (is_special) /* skip persistent */
                    {
                        continue;
                    }
                }

                /* NOTE: this skips our delattr hook */
                if (PyObject_GenericSetAttr((PyObject *)self, name, NULL) < 0)
                    /* delattr of non-set slot will raise AttributeError - we
                     * simply ignore. */
                    PyErr_Clear();
            }
        }
        Py_XDECREF(slotnames);
    }

    /* We remove the reference to the just ghosted object that the ring
    * holds.  Note that the dictionary of oids->objects has an uncounted
    * reference, so if the ring's reference was the only one, this frees
    * the ghost object.  Note further that the object's dealloc knows to
    * inform the dictionary that it is going away.
    */
    Py_DECREF(self);
}

static int
changed(cPersistentObject *self)
{
    if ((self->state == cPersistent_UPTODATE_STATE ||
        self->state == cPersistent_STICKY_STATE)
        && self->jar)
    {
        PyObject *meth, *arg, *result;
        static PyObject *s_register;

        if (s_register == NULL)
            s_register = INTERN("register");
        meth = PyObject_GetAttr((PyObject *)self->jar, s_register);
        if (meth == NULL)
            return -1;
        arg = PyTuple_New(1);
        if (arg == NULL) 
        {
            Py_DECREF(meth);
            return -1;
        }
        Py_INCREF(self);
        PyTuple_SET_ITEM(arg, 0, (PyObject *)self);
        result = PyEval_CallObject(meth, arg);
        Py_DECREF(arg);
        Py_DECREF(meth);
        if (result == NULL)
            return -1;
        Py_DECREF(result);

        self->state = cPersistent_CHANGED_STATE;
    }

    return 0;
}

static int
readCurrent(cPersistentObject *self)
{
    if ((self->state == cPersistent_UPTODATE_STATE ||
        self->state == cPersistent_STICKY_STATE)
        && self->jar && self->oid)
    {
        static PyObject *s_readCurrent=NULL;
        PyObject *r;

        if (s_readCurrent == NULL)
            s_readCurrent = INTERN("readCurrent");

        r = PyObject_CallMethodObjArgs(self->jar, s_readCurrent, self, NULL);
        if (r == NULL)
            return -1;

        Py_DECREF(r);
    }

    return 0;
}

static PyObject *
Per__p_deactivate(cPersistentObject *self)
{
    if (self->state == cPersistent_UPTODATE_STATE && self->jar)
    {
        PyObject **dictptr = _PyObject_GetDictPtr((PyObject *)self);
        if (dictptr && *dictptr)
        {
            Py_DECREF(*dictptr);
            *dictptr = NULL;
        }
        /* Note that we need to set to ghost state unless we are
            called directly. Methods that override this need to
            do the same! */
        ghostify(self);
        if (PyErr_Occurred())
            return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject *
Per__p_activate(cPersistentObject *self)
{
    if (unghostify(self) < 0)
        return NULL;

    Py_INCREF(Py_None);
    return Py_None;
}

static int Per_set_changed(cPersistentObject *self, PyObject *v);

static PyObject *
Per__p_invalidate(cPersistentObject *self)
{
    signed char old_state = self->state;

    if (old_state != cPersistent_GHOST_STATE)
    {
        if (Per_set_changed(self, NULL) < 0)
            return NULL;
        ghostify(self);
        if (PyErr_Occurred())
            return NULL;
    }
    Py_INCREF(Py_None);
    return Py_None;
}
Ejemplo n.º 5
0
static PyObject *
Per_get_estimated_size(cPersistentObject *self)
{
    return INT_FROM_LONG(_estimated_size_in_bytes(self->estimated_size));
}