[Zodb-checkins] CVS: StandaloneZODB/ZODB - cPersistence.c:1.55
Barry Warsaw
barry@wooz.org
Tue, 2 Apr 2002 17:17:25 -0500
Update of /cvs-repository/StandaloneZODB/ZODB
In directory cvs.zope.org:/tmp/cvs-serv20347
Modified Files:
cPersistence.c
Log Message:
Code cleanup, and a bunch of XXX comments. Specifically,
UPDATE_STATE_IF_NECESSARY: Un-macroize this. Renamed to function
unghostify() and changed (slightly) the return semantics.
ghostify(): Don't use the NON_GHOST_COUNT macro. Add some comments.
Per_setstate(), Per__getstate__(), Per_getattr(), _setattro(): Use
unghostify() instead of UPDATE_STATE_IF_NECESSARY.
=== StandaloneZODB/ZODB/cPersistence.c 1.54 => 1.55 ===
#include "cPersistence.h"
+/* XXX What is this structure used for? */
struct ccobject_head_struct {
CACHE_HEAD
};
@@ -114,31 +115,42 @@
return self;
}
-#define UPDATE_STATE_IF_NECESSARY(self, ER) \
-if(self->state < 0 && self->jar) \
-{ \
- PyObject *r; \
- \
- int *count = NON_GHOST_COUNT(self); \
- if(count) \
- { \
- (*count)++; \
- self->ring.next = HOME(self); \
- self->ring.prev = HOME(self)->prev; \
- HOME(self)->prev->next = &self->ring; \
- HOME(self)->prev = &self->ring; \
- Py_INCREF(self); \
- } \
- self->state=cPersistent_CHANGED_STATE; \
- UNLESS(r=callmethod1(self->jar,py_setstate,(PyObject*)self)) \
- { \
- ghostify(self); \
- return ER; \
- } \
- self->state=cPersistent_UPTODATE_STATE; \
- Py_DECREF(r); \
+
+static void ghostify(cPersistentObject*);
+
+/* Load the state of the object, unghostifying it. Upon success, return 1.
+ * If an error occurred, re-ghostify the object and return 0.
+ */
+static int
+unghostify(cPersistentObject *self)
+{
+ if (self->state < 0 && self->jar) {
+ PyObject *r;
+
+ /* XXX Is it ever possibly to not have a cache? */
+ if (self->cache) {
+ /* Create a node in the ring for this unghostified object. */
+ self->cache->non_ghost_count++;
+ self->ring.next = &self->cache->ring_home;
+ self->ring.prev = (&(self)->cache->ring_home)->prev;
+ HOME(self)->prev->next = &self->ring;
+ HOME(self)->prev = &self->ring;
+ Py_INCREF(self);
+ }
+ self->state = cPersistent_CHANGED_STATE;
+ /* Call the object's __setstate__() */
+ r = callmethod1(self->jar, py_setstate, (PyObject*)self);
+ if (r == NULL) {
+ ghostify(self);
+ return 0;
+ }
+ self->state = cPersistent_UPTODATE_STATE;
+ Py_DECREF(r);
+ }
+ return 1;
}
+
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) accessed(self)
/****************************************************************************/
@@ -161,22 +173,31 @@
static void
ghostify(cPersistentObject *self)
{
- int *count;
- count = NON_GHOST_COUNT(self);
- if(count && (self->state>=0))
- {
- (*count)--;
- self->ring.next->prev = self->ring.prev;
- self->ring.prev->next = self->ring.next;
- self->ring.prev = NULL;
- self->ring.next = NULL;
- self->state = cPersistent_GHOST_STATE;
- Py_DECREF(self);
- }
- else
- {
+ /* are we already a ghost? */
+ if (self->state == cPersistent_GHOST_STATE)
+ return;
+ /* XXX is it ever possible to not have a cache? */
+ if (self->cache == NULL) {
self->state = cPersistent_GHOST_STATE;
+ return;
}
+ /* 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->ring.next->prev = self->ring.prev;
+ self->ring.prev->next = self->ring.next;
+ self->ring.prev = NULL;
+ self->ring.next = NULL;
+ self->state = cPersistent_GHOST_STATE;
+
+ /* 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 void
@@ -293,53 +314,59 @@
static int
Per_setstate(cPersistentObject *self)
{
- UPDATE_STATE_IF_NECESSARY(self, -1);
- self->state=cPersistent_STICKY_STATE;
- return 0;
+ if (!unghostify(self))
+ return -1;
+ self->state = cPersistent_STICKY_STATE;
+ return 0;
}
static PyObject *
Per__getstate__(cPersistentObject *self, PyObject *args)
{
- PyObject *__dict__, *d=0;
+ PyObject *__dict__, *d=0;
- if (!checknoargs(args)) return NULL;
+ if (!checknoargs(args))
+ return NULL;
#ifdef DEBUG_LOG
- if(idebug_log < 0) call_debug("get",self);
+ if (idebug_log < 0)
+ call_debug("get",self);
#endif
- UPDATE_STATE_IF_NECESSARY(self, NULL);
+ if (!unghostify(self))
+ return NULL;
- if(HasInstDict(self) && (__dict__=INSTANCE_DICT(self)))
- {
- PyObject *k, *v;
- int pos;
- char *ck;
+ if (HasInstDict(self) && (__dict__=INSTANCE_DICT(self))) {
+ PyObject *k, *v;
+ int pos;
+ char *ck;
- for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
- {
- if(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
- (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
+ for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) {
+ if(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
+ (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
{
- UNLESS(d=PyDict_New()) goto err;
- for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
- UNLESS(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
- (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
- if(PyDict_SetItem(d,k,v) < 0) goto err;
- return d;
+ if ((d=PyDict_New()) == NULL)
+ goto err;
+
+ for (pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
+ UNLESS(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
+ (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
+ {
+ if (PyDict_SetItem(d,k,v) < 0)
+ goto err;
+ }
+ return d;
}
}
}
- else
- __dict__=Py_None;
-
- Py_INCREF(__dict__);
- return __dict__;
+ else
+ __dict__ = Py_None;
-err:
- Py_XDECREF(d);
- return NULL;
+ Py_INCREF(__dict__);
+ return __dict__;
+ err:
+ Py_XDECREF(d);
+ return NULL;
}
static PyObject *
@@ -466,7 +493,8 @@
case 'm':
if(strcmp(n,"time")==0)
{
- UPDATE_STATE_IF_NECESSARY(self, NULL);
+ if (!unghostify(self))
+ return NULL;
accessed(self);
@@ -498,7 +526,8 @@
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0)))
{
- UPDATE_STATE_IF_NECESSARY(self, NULL);
+ if (!unghostify(self))
+ return NULL;
accessed(self);
}
@@ -614,7 +643,8 @@
}
else
{
- UPDATE_STATE_IF_NECESSARY(self, -1);
+ if (!unghostify(self))
+ return -1;
accessed(self);