[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);