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 @@ ...@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] = static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n" "Defines Persistent mixin class for persistent objects.\n"
"\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" #include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct { struct ccobject_head_struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
}; };
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) ) #define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) ) #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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \ ...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \ Py_DECREF(r); \
} }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \ #define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(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; }
/****************************************************************************/ /****************************************************************************/
...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype; ...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void static void
accessed(cPersistentObject *self) 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 static void
...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self) ...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void static void
deallocated(cPersistentObject *self) deallocated(cPersistentObject *self)
{ {
if(self->state>=0) ghostify(self); if (self->state >= 0)
if(self->cache) ghostify(self);
{ if (self->cache) {
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid); PyObject *v;
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(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->jar);
Py_XDECREF(self->oid); Py_XDECREF(self->oid);
...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); 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' && if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' && self->serial[5]=='\0' && self->serial[4]=='\0' &&
...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
UPDATE_STATE_IF_NECESSARY(self, -1); UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_')) if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar) && (self->state != cPersistent_CHANGED_STATE && self->jar)
......
...@@ -18,15 +18,30 @@ ...@@ -18,15 +18,30 @@
#include "ExtensionClass.h" #include "ExtensionClass.h"
#include <time.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_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1 #define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2 #define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct typedef struct CPersistentRing_struct
{ {
struct CPersistentRing_struct *prev; struct CPersistentRing_struct *prev;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] = static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n" "Defines the PickleCache used by ZODB Connection objects.\n"
"\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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -45,9 +45,7 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed; ...@@ -45,9 +45,7 @@ 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 */ /* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct { typedef struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count; int klass_count;
PyObject *data; PyObject *data;
PyObject *jar; PyObject *jar;
...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key) ...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v; 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 /* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is 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, ...@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging correspond to a persistent object, although the debugging
version will double-check this. */ 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 #ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object)) if (!PyExtensionInstance_Check(object)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context); "Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL; return NULL;
} }
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context); "Unexpectedly encountered non-persistent object in %s", context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->jar!=self->jar) if (((cPersistentObject*)object)->jar != self->jar) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context); "Unexpectedly encountered object from a different jar in %s",
context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->cache!=(PyObject *)self) if (((cPersistentObject *)object)->cache != (PerCache *)self) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context); "Unexpectedly encountered broken ring in %s", context);
return NULL; return NULL;
} }
#endif #endif
...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) ...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
} }
else else
{ {
if(((cPersistentObject*)v)->cache) if(((cPersistentObject*)v)->cache) {
{ if(((cPersistentObject*)v)->cache != (PerCache *)self) {
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
{
/* This object is already in a different cache. */ /* 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; 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(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1; if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self); Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self; ((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0) if(((cPersistentObject*)v)->state>=0)
{ {
/* insert this non-ghost object into the ring just behind the home position */ /* 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) ...@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v); Py_INCREF(v);
} }
Py_DECREF(((cPersistentObject*)v)->cache); Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL; ((cPersistentObject*)v)->cache = NULL;
} }
......
...@@ -14,20 +14,17 @@ ...@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] = static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n" "Defines Persistent mixin class for persistent objects.\n"
"\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" #include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct { struct ccobject_head_struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
}; };
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) ) #define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) ) #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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \ ...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \ Py_DECREF(r); \
} }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \ #define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(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; }
/****************************************************************************/ /****************************************************************************/
...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype; ...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void static void
accessed(cPersistentObject *self) 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 static void
...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self) ...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void static void
deallocated(cPersistentObject *self) deallocated(cPersistentObject *self)
{ {
if(self->state>=0) ghostify(self); if (self->state >= 0)
if(self->cache) ghostify(self);
{ if (self->cache) {
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid); PyObject *v;
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(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->jar);
Py_XDECREF(self->oid); Py_XDECREF(self->oid);
...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); 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' && if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' && self->serial[5]=='\0' && self->serial[4]=='\0' &&
...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
UPDATE_STATE_IF_NECESSARY(self, -1); UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_')) if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar) && (self->state != cPersistent_CHANGED_STATE && self->jar)
......
...@@ -18,15 +18,30 @@ ...@@ -18,15 +18,30 @@
#include "ExtensionClass.h" #include "ExtensionClass.h"
#include <time.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_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1 #define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2 #define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct typedef struct CPersistentRing_struct
{ {
struct CPersistentRing_struct *prev; struct CPersistentRing_struct *prev;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] = static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n" "Defines the PickleCache used by ZODB Connection objects.\n"
"\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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -45,9 +45,7 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed; ...@@ -45,9 +45,7 @@ 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 */ /* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct { typedef struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count; int klass_count;
PyObject *data; PyObject *data;
PyObject *jar; PyObject *jar;
...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key) ...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v; 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 /* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is 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, ...@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging correspond to a persistent object, although the debugging
version will double-check this. */ 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 #ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object)) if (!PyExtensionInstance_Check(object)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context); "Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL; return NULL;
} }
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context); "Unexpectedly encountered non-persistent object in %s", context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->jar!=self->jar) if (((cPersistentObject*)object)->jar != self->jar) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context); "Unexpectedly encountered object from a different jar in %s",
context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->cache!=(PyObject *)self) if (((cPersistentObject *)object)->cache != (PerCache *)self) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context); "Unexpectedly encountered broken ring in %s", context);
return NULL; return NULL;
} }
#endif #endif
...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) ...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
} }
else else
{ {
if(((cPersistentObject*)v)->cache) if(((cPersistentObject*)v)->cache) {
{ if(((cPersistentObject*)v)->cache != (PerCache *)self) {
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
{
/* This object is already in a different cache. */ /* 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; 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(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1; if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self); Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self; ((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0) if(((cPersistentObject*)v)->state>=0)
{ {
/* insert this non-ghost object into the ring just behind the home position */ /* 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) ...@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v); Py_INCREF(v);
} }
Py_DECREF(((cPersistentObject*)v)->cache); Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL; ((cPersistentObject*)v)->cache = NULL;
} }
......
...@@ -14,20 +14,17 @@ ...@@ -14,20 +14,17 @@
static char cPersistence_doc_string[] = static char cPersistence_doc_string[] =
"Defines Persistent mixin class for persistent objects.\n" "Defines Persistent mixin class for persistent objects.\n"
"\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" #include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct ccobject_head_struct { struct ccobject_head_struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
}; };
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) ) #define HOME(O) (((O)->cache == NULL) ? NULL : &(O)->cache->ring_home)
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) ) #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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \ ...@@ -142,16 +139,7 @@ if(self->state < 0 && self->jar) \
Py_DECREF(r); \ Py_DECREF(r); \
} }
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \ #define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(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; }
/****************************************************************************/ /****************************************************************************/
...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype; ...@@ -160,7 +148,14 @@ staticforward PyExtensionClass Pertype;
static void static void
accessed(cPersistentObject *self) 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 static void
...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self) ...@@ -187,12 +182,18 @@ ghostify(cPersistentObject *self)
static void static void
deallocated(cPersistentObject *self) deallocated(cPersistentObject *self)
{ {
if(self->state>=0) ghostify(self); if (self->state >= 0)
if(self->cache) ghostify(self);
{ if (self->cache) {
PyObject *v=PyObject_CallMethod(self->cache,"_oid_unreferenced","O",self->oid); PyObject *v;
if(!v) PyErr_Clear(); /* and explode later */
Py_XDECREF(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->jar);
Py_XDECREF(self->oid); Py_XDECREF(self->oid);
...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -467,7 +468,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); 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' && if (self->serial[7]=='\0' && self->serial[6]=='\0' &&
self->serial[5]=='\0' && self->serial[4]=='\0' && self->serial[5]=='\0' && self->serial[4]=='\0' &&
...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -499,7 +500,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{ {
UPDATE_STATE_IF_NECESSARY(self, NULL); UPDATE_STATE_IF_NECESSARY(self, NULL);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -615,7 +616,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
UPDATE_STATE_IF_NECESSARY(self, -1); UPDATE_STATE_IF_NECESSARY(self, -1);
KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self); accessed(self);
if((! (*name=='_' && name[1]=='v' && name[2]=='_')) if((! (*name=='_' && name[1]=='v' && name[2]=='_'))
&& (self->state != cPersistent_CHANGED_STATE && self->jar) && (self->state != cPersistent_CHANGED_STATE && self->jar)
......
...@@ -18,15 +18,30 @@ ...@@ -18,15 +18,30 @@
#include "ExtensionClass.h" #include "ExtensionClass.h"
#include <time.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_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1 #define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2 #define cPersistent_STICKY_STATE 2
struct ccobject_head_struct;
typedef struct CPersistentRing_struct typedef struct CPersistentRing_struct
{ {
struct CPersistentRing_struct *prev; struct CPersistentRing_struct *prev;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
static char cPickleCache_doc_string[] = static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n" "Defines the PickleCache used by ZODB Connection objects.\n"
"\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 ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -45,9 +45,7 @@ static PyObject *py__p_oid, *py_reload, *py__p_jar, *py__p_changed; ...@@ -45,9 +45,7 @@ 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 */ /* the layout of this struct is the same as the start of ccobject_head in cPersistence.c */
typedef struct { typedef struct {
PyObject_HEAD CACHE_HEAD
CPersistentRing ring_home;
int non_ghost_count;
int klass_count; int klass_count;
PyObject *data; PyObject *data;
PyObject *jar; PyObject *jar;
...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key) ...@@ -78,7 +76,8 @@ static PyObject *object_from_oid(ccobject *self,PyObject *key)
return v; 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 /* Given a position in the LRU ring, return a borrowed
reference to the object at that point in the ring. The caller is 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, ...@@ -86,27 +85,31 @@ static cPersistentObject *object_from_ring(ccobject *self,CPersistentRing *here,
correspond to a persistent object, although the debugging correspond to a persistent object, although the debugging
version will double-check this. */ 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 #ifdef MUCH_RING_CHECKING
if(!PyExtensionInstance_Check(object)) if (!PyExtensionInstance_Check(object)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-ExtensionClass object in %s",context); "Unexpectedly encountered non-ExtensionClass object in %s",
context);
return NULL; return NULL;
} }
if(!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) if (!(((PyExtensionClass*)(object->ob_type))->class_flags & PERSISTENT_TYPE_FLAG)) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered non-persistent object in %s",context); "Unexpectedly encountered non-persistent object in %s", context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->jar!=self->jar) if (((cPersistentObject*)object)->jar != self->jar) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered object from a different jar in %s",context); "Unexpectedly encountered object from a different jar in %s",
context);
return NULL; return NULL;
} }
if(((cPersistentObject*)object)->cache!=(PyObject *)self) if (((cPersistentObject *)object)->cache != (PerCache *)self) {
{ PyErr_Format(PyExc_RuntimeError,
PyErr_Format(PyExc_RuntimeError,"Unexpectedly encountered broken ring in %s",context); "Unexpectedly encountered broken ring in %s", context);
return NULL; return NULL;
} }
#endif #endif
...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) ...@@ -714,27 +717,27 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
} }
else else
{ {
if(((cPersistentObject*)v)->cache) if(((cPersistentObject*)v)->cache) {
{ if(((cPersistentObject*)v)->cache != (PerCache *)self) {
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
{
/* This object is already in a different cache. */ /* 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; 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(check_ring(self,"pre-setitem")) return -1;
if(PyDict_SetItem(self->data, key, v)) return -1; if(PyDict_SetItem(self->data, key, v)) return -1;
Py_INCREF(self); Py_INCREF(self);
((cPersistentObject*)v)->cache = (PyObject *)self; ((cPersistentObject*)v)->cache = (PerCache *)self;
if(((cPersistentObject*)v)->state>=0) if(((cPersistentObject*)v)->state>=0)
{ {
/* insert this non-ghost object into the ring just behind the home position */ /* 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) ...@@ -791,7 +794,7 @@ cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Py_INCREF(v); Py_INCREF(v);
} }
Py_DECREF(((cPersistentObject*)v)->cache); Py_DECREF((PyObject *)((cPersistentObject*)v)->cache);
((cPersistentObject*)v)->cache = NULL; ((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