Commit 09125899 authored by Jeremy Hylton's avatar Jeremy Hylton

Some first cosmetic changes to the new cache implementation.

Define the contents of ccobject_head_struct via CACHE_HEAD macro.
Don't rely on two different files to define a struct with the same
layout by convention.

Remove many levels of parentheses from the HOME and NON_GHOST_COUNT
macros.

Replace KEEP_THIS_ONE_AROUND_FOR_A_WHILE() macro with a call to the
accessed() function.  (Who comes up with these names :-).

Remove include of string.h in cPersistence.c.

Expand cPersistent_HEAD macro so that it has one line for each
attribute!

Use typedef to define PerCache as "struct ccobject_head_struct" and
use this for the entry cache slot in cPersistent_HEAD instead of
PyObject *.

In cPickleCache.c, reflow a bunch of long lines, add some whitespace,
and an XXX comment explaining that I don't understand a different
comment.
parent 86cc6f96
......@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n"
"\n"
"$Id: cPersistence.c,v 1.51 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPersistence.c,v 1.52 2002/04/01 23:36:33 jeremy Exp $\n";
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
CACHE_HEAD
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) \
(((O)->cache == NULL) ? NULL : &(O)->cache->non_ghost_count)
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(self)
/****************************************************************************/
......@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void
accessed(cPersistentObject *self)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
if (HOME(self) && self->state >= 0) {
self->ring.prev->next = self->ring.next;
self->ring.next->prev = self->ring.prev;
self->ring.next = HOME(self);
self->ring.prev = HOME(self)->prev;
HOME(self)->prev->next = &self->ring;
HOME(self)->prev = &self->ring;
}
}
static void
......@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void
deallocated(cPersistentObject *self)
{
if(self->state>=0) ghostify(self);
if(self->cache)
{
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid);
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(v);
if (self->state >= 0)
ghostify(self);
if (self->cache) {
PyObject *v;
v = PyObject_CallMethod((PyObject *)self->cache,
"_oid_unreferenced", "O", self->oid);
/* XXX What does the comment below mean? */
if (v == NULL)
PyErr_Clear(); /* and explode later */
else
Py_DECREF(v);
}
Py_XDECREF(self->jar);
Py_XDECREF(self->oid);
......@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' &&
......@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
}
return getattrf((PyObject *)self, oname);
......@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar)
......
......@@ -18,15 +18,30 @@
#include "ExtensionClass.h"
#include <time.h>
#define CACHE_HEAD \
PyObject_HEAD \
CPersistentRing ring_home; \
int non_ghost_count;
struct ccobject_head_struct;
typedef struct ccobject_head_struct PerCache;
#define cPersistent_HEAD \
PyObject_HEAD; \
PyObject *jar; \
PyObject *oid; \
PerCache *cache; \
CPersistentRing ring; \
char serial[8]; \
signed char state; \
unsigned char reserved[3];
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct
{
struct CPersistentRing_struct *prev;
......@@ -34,7 +49,7 @@ typedef struct CPersistentRing_struct
} CPersistentRing;
typedef struct {
cPersistent_HEAD
cPersistent_HEAD
} cPersistentObject;
typedef int (*persetattr)(PyObject *, PyObject*, PyObject *, setattrofunc);
......
......@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.42 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPickleCache.c,v 1.43 2002/04/01 23:36:34 jeremy Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -45,16 +45,14 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed;
/* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
CACHE_HEAD
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
} ccobject;
staticforward PyTypeObject Cctype;
......@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v;
}
static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,const char *context)
static cPersistentObject *
object_from_ring(ccobject *self, CPersistentRing *here, const char *context)
{
/* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is
......@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging
version will double-check this. */
PyObject *object = (PyObject *)(((char *)here)-offsetof(cPersistentObject,ring));
PyObject *object;
object = (PyObject *)(((char *)here) - offsetof(cPersistentObject, ring));
#ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context);
if (!PyExtensionInstance_Check(object)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL;
}
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context);
if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-persistent object in %s", context);
return NULL;
}
if(((cPersistentObject*)object)->jar!=self->jar)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context);
if (((cPersistentObject*)object)->jar != self->jar) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered object from a different jar in %s",
context);
return NULL;
}
if(((cPersistentObject*)object)->cache!=(PyObject *)self)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context);
if (((cPersistentObject *)object)->cache != (PerCache *)self) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered broken ring in %s", context);
return NULL;
}
#endif
......@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
}
else
{
if(((cPersistentObject*)v)->cache)
{
if(((cPersistentObject*)v)->cache==(PyObject *)self)
{
/* This object is already one of ours, which is ok.
It would be very strange if someone was trying to register the
same object under a different key */
}
else
{
if(((cPersistentObject*)v)->cache) {
if(((cPersistentObject*)v)->cache != (PerCache *)self) {
/* This object is already in a different cache. */
PyErr_SetString(PyExc_ValueError, "Cache values may only be in one cache.");
PyErr_SetString(PyExc_ValueError,
"Cache values may only be in one cache.");
return -1;
}
}
/* else:
This object is already one of ours, which
is ok. It would be very strange if someone
was trying to register the same object under a
different key.
*/
}
if(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self;
((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0)
{
/* insert this non-ghost object into the ring just behind the home position */
......@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v);
}
Py_DECREF(((cPersistentObject*)v)->cache);
Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL;
}
......
......@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n"
"\n"
"$Id: cPersistence.c,v 1.51 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPersistence.c,v 1.52 2002/04/01 23:36:33 jeremy Exp $\n";
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
CACHE_HEAD
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) \
(((O)->cache == NULL) ? NULL : &(O)->cache->non_ghost_count)
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(self)
/****************************************************************************/
......@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void
accessed(cPersistentObject *self)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
if (HOME(self) && self->state >= 0) {
self->ring.prev->next = self->ring.next;
self->ring.next->prev = self->ring.prev;
self->ring.next = HOME(self);
self->ring.prev = HOME(self)->prev;
HOME(self)->prev->next = &self->ring;
HOME(self)->prev = &self->ring;
}
}
static void
......@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void
deallocated(cPersistentObject *self)
{
if(self->state>=0) ghostify(self);
if(self->cache)
{
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid);
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(v);
if (self->state >= 0)
ghostify(self);
if (self->cache) {
PyObject *v;
v = PyObject_CallMethod((PyObject *)self->cache,
"_oid_unreferenced", "O", self->oid);
/* XXX What does the comment below mean? */
if (v == NULL)
PyErr_Clear(); /* and explode later */
else
Py_DECREF(v);
}
Py_XDECREF(self->jar);
Py_XDECREF(self->oid);
......@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' &&
......@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
}
return getattrf((PyObject *)self, oname);
......@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar)
......
......@@ -18,15 +18,30 @@
#include "ExtensionClass.h"
#include <time.h>
#define CACHE_HEAD \
PyObject_HEAD \
CPersistentRing ring_home; \
int non_ghost_count;
struct ccobject_head_struct;
typedef struct ccobject_head_struct PerCache;
#define cPersistent_HEAD \
PyObject_HEAD; \
PyObject *jar; \
PyObject *oid; \
PerCache *cache; \
CPersistentRing ring; \
char serial[8]; \
signed char state; \
unsigned char reserved[3];
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct
{
struct CPersistentRing_struct *prev;
......@@ -34,7 +49,7 @@ typedef struct CPersistentRing_struct
} CPersistentRing;
typedef struct {
cPersistent_HEAD
cPersistent_HEAD
} cPersistentObject;
typedef int (*persetattr)(PyObject *, PyObject*, PyObject *, setattrofunc);
......
......@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.42 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPickleCache.c,v 1.43 2002/04/01 23:36:34 jeremy Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -45,16 +45,14 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed;
/* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
CACHE_HEAD
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
} ccobject;
staticforward PyTypeObject Cctype;
......@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v;
}
static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,const char *context)
static cPersistentObject *
object_from_ring(ccobject *self, CPersistentRing *here, const char *context)
{
/* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is
......@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging
version will double-check this. */
PyObject *object = (PyObject *)(((char *)here)-offsetof(cPersistentObject,ring));
PyObject *object;
object = (PyObject *)(((char *)here) - offsetof(cPersistentObject, ring));
#ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context);
if (!PyExtensionInstance_Check(object)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL;
}
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context);
if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-persistent object in %s", context);
return NULL;
}
if(((cPersistentObject*)object)->jar!=self->jar)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context);
if (((cPersistentObject*)object)->jar != self->jar) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered object from a different jar in %s",
context);
return NULL;
}
if(((cPersistentObject*)object)->cache!=(PyObject *)self)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context);
if (((cPersistentObject *)object)->cache != (PerCache *)self) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered broken ring in %s", context);
return NULL;
}
#endif
......@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
}
else
{
if(((cPersistentObject*)v)->cache)
{
if(((cPersistentObject*)v)->cache==(PyObject *)self)
{
/* This object is already one of ours, which is ok.
It would be very strange if someone was trying to register the
same object under a different key */
}
else
{
if(((cPersistentObject*)v)->cache) {
if(((cPersistentObject*)v)->cache != (PerCache *)self) {
/* This object is already in a different cache. */
PyErr_SetString(PyExc_ValueError, "Cache values may only be in one cache.");
PyErr_SetString(PyExc_ValueError,
"Cache values may only be in one cache.");
return -1;
}
}
/* else:
This object is already one of ours, which
is ok. It would be very strange if someone
was trying to register the same object under a
different key.
*/
}
if(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self;
((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0)
{
/* insert this non-ghost object into the ring just behind the home position */
......@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v);
}
Py_DECREF(((cPersistentObject*)v)->cache);
Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL;
}
......
......@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n"
"\n"
"$Id: cPersistence.c,v 1.51 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPersistence.c,v 1.52 2002/04/01 23:36:33 jeremy Exp $\n";
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
CACHE_HEAD
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) \
(((O)->cache == NULL) ? NULL : &(O)->cache->non_ghost_count)
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(self)
/****************************************************************************/
......@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void
accessed(cPersistentObject *self)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
if (HOME(self) && self->state >= 0) {
self->ring.prev->next = self->ring.next;
self->ring.next->prev = self->ring.prev;
self->ring.next = HOME(self);
self->ring.prev = HOME(self)->prev;
HOME(self)->prev->next = &self->ring;
HOME(self)->prev = &self->ring;
}
}
static void
......@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void
deallocated(cPersistentObject *self)
{
if(self->state>=0) ghostify(self);
if(self->cache)
{
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid);
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(v);
if (self->state >= 0)
ghostify(self);
if (self->cache) {
PyObject *v;
v = PyObject_CallMethod((PyObject *)self->cache,
"_oid_unreferenced", "O", self->oid);
/* XXX What does the comment below mean? */
if (v == NULL)
PyErr_Clear(); /* and explode later */
else
Py_DECREF(v);
}
Py_XDECREF(self->jar);
Py_XDECREF(self->oid);
......@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' &&
......@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
}
return getattrf((PyObject *)self, oname);
......@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self);
accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar)
......
......@@ -18,15 +18,30 @@
#include "ExtensionClass.h"
#include <time.h>
#define CACHE_HEAD \
PyObject_HEAD \
CPersistentRing ring_home; \
int non_ghost_count;
struct ccobject_head_struct;
typedef struct ccobject_head_struct PerCache;
#define cPersistent_HEAD \
PyObject_HEAD; \
PyObject *jar; \
PyObject *oid; \
PerCache *cache; \
CPersistentRing ring; \
char serial[8]; \
signed char state; \
unsigned char reserved[3];
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct
{
struct CPersistentRing_struct *prev;
......@@ -34,7 +49,7 @@ typedef struct CPersistentRing_struct
} CPersistentRing;
typedef struct {
cPersistent_HEAD
cPersistent_HEAD
} cPersistentObject;
typedef int (*persetattr)(PyObject *, PyObject*, PyObject *, setattrofunc);
......
......@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.42 2002/03/27 10:14:04 htrd Exp $\n";
"$Id: cPickleCache.c,v 1.43 2002/04/01 23:36:34 jeremy Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -45,16 +45,14 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed;
/* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct {
PyObject_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
CACHE_HEAD
int klass_count;
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int cache_size;
int ring_lock;
int cache_drain_resistance;
} ccobject;
staticforward PyTypeObject Cctype;
......@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v;
}
static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,const char *context)
static cPersistentObject *
object_from_ring(ccobject *self, CPersistentRing *here, const char *context)
{
/* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is
......@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging
version will double-check this. */
PyObject *object = (PyObject *)(((char *)here)-offsetof(cPersistentObject,ring));
PyObject *object;
object = (PyObject *)(((char *)here) - offsetof(cPersistentObject, ring));
#ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context);
if (!PyExtensionInstance_Check(object)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL;
}
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG))
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context);
if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered non-persistent object in %s", context);
return NULL;
}
if(((cPersistentObject*)object)->jar!=self->jar)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context);
if (((cPersistentObject*)object)->jar != self->jar) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered object from a different jar in %s",
context);
return NULL;
}
if(((cPersistentObject*)object)->cache!=(PyObject *)self)
{
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context);
if (((cPersistentObject *)object)->cache != (PerCache *)self) {
PyErr_Format(PyExc_RuntimeError,
"Unexpectedly encountered broken ring in %s", context);
return NULL;
}
#endif
......@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
}
else
{
if(((cPersistentObject*)v)->cache)
{
if(((cPersistentObject*)v)->cache==(PyObject *)self)
{
/* This object is already one of ours, which is ok.
It would be very strange if someone was trying to register the
same object under a different key */
}
else
{
if(((cPersistentObject*)v)->cache) {
if(((cPersistentObject*)v)->cache != (PerCache *)self) {
/* This object is already in a different cache. */
PyErr_SetString(PyExc_ValueError, "Cache values may only be in one cache.");
PyErr_SetString(PyExc_ValueError,
"Cache values may only be in one cache.");
return -1;
}
}
/* else:
This object is already one of ours, which
is ok. It would be very strange if someone
was trying to register the same object under a
different key.
*/
}
if(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self;
((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0)
{
/* insert this non-ghost object into the ring just behind the home position */
......@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v);
}
Py_DECREF(((cPersistentObject*)v)->cache);
Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment