Commit 4c3e38f4 authored by Jim Fulton's avatar Jim Fulton

Added logic to disable deactivation during methods. This sort of

logic will be needed for any C-based persistent object.
parent ff73dc02
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
static char Trie_module_documentation[] = static char Trie_module_documentation[] =
"" ""
"\n$Id: Trie.c,v 1.8 1997/05/08 21:09:49 jim Exp $" "\n$Id: Trie.c,v 1.9 1997/05/19 17:49:35 jim Exp $"
; ;
...@@ -92,18 +92,37 @@ staticforward PyExtensionClass TrieType; ...@@ -92,18 +92,37 @@ staticforward PyExtensionClass TrieType;
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */
static PyObject *
PER_RETURN(TrieObject *self, PyObject *r)
{
PER_ALLOW_DEACTIVATION(self);
return r;
}
static int
PER_INT_RETURN(TrieObject *self, int r)
{
PER_ALLOW_DEACTIVATION(self);
return r;
}
static PyObject * static PyObject *
Trie___setstate__(TrieObject *self, PyObject *args) Trie___setstate__(TrieObject *self, PyObject *args)
{ {
PyObject *state; PyObject *state;
UNLESS(PyArg_ParseTuple(args, "O", &state)) return NULL; UNLESS(PyArg_ParseTuple(args, "O", &state)) return NULL;
#ifdef PERSISTENT
PER_PREVENT_DEACTIVATION(self);
#endif
if(state != Py_None) if(state != Py_None)
{ {
self->value=NULL; self->value=NULL;
UNLESS(PyArg_ParseTuple(state, "iO|O", &(self->min), &(self->bins), UNLESS(PyArg_ParseTuple(state, "iO|O", &(self->min), &(self->bins),
&(self->value))) &(self->value)))
return NULL; return PER_RETURN(self, NULL);
if(self->min < 0) if(self->min < 0)
{ {
self->value=self->bins; self->value=self->bins;
...@@ -113,28 +132,34 @@ Trie___setstate__(TrieObject *self, PyObject *args) ...@@ -113,28 +132,34 @@ Trie___setstate__(TrieObject *self, PyObject *args)
Py_XINCREF(self->bins); Py_XINCREF(self->bins);
} }
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return PER_RETURN(self, Py_None);
} }
static PyObject * static PyObject *
Trie___getstate__(TrieObject *self, PyObject *args) Trie___getstate__(TrieObject *self, PyObject *args)
{ {
PyObject *r;
UNLESS(PyArg_ParseTuple(args, "")) return NULL; UNLESS(PyArg_ParseTuple(args, "")) return NULL;
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) PER_RETURN(self, NULL);
#endif #endif
if(self->value) if(self->value)
if(self->bins) if(self->bins)
return Py_BuildValue("(iOO)", self->min, self->bins, self->value); return PER_RETURN(self,
Py_BuildValue("(iOO)",
self->min, self->bins, self->value));
else else
return Py_BuildValue("(iO)", -1, self->value); return PER_RETURN(self, Py_BuildValue("(iO)", -1, self->value));
else else
if(self->bins) if(self->bins)
return Py_BuildValue("(iO)", self->min, self->bins); return PER_RETURN(self, Py_BuildValue("(iO)", self->min, self->bins));
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return PER_RETURN(self, Py_None);
} }
#ifdef PERSISTENT #ifdef PERSISTENT
...@@ -170,25 +195,29 @@ getiork(TrieObject *self, PyObject * r, keybuf *buf, int l, int dokeys) ...@@ -170,25 +195,29 @@ getiork(TrieObject *self, PyObject * r, keybuf *buf, int l, int dokeys)
PyObject *item=0; PyObject *item=0;
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return PER_RETURN(self, NULL);
#endif #endif
if(self->value) if(self->value)
{ {
if(dokeys) if(dokeys)
{ {
UNLESS(item=PyString_FromStringAndSize(buf->data,l)) return NULL; UNLESS(item=PyString_FromStringAndSize(buf->data,l))
return PER_RETURN(self, NULL);
} }
else else
UNLESS(item=Py_BuildValue("(s#O)",buf->data,l,self->value)) return NULL; UNLESS(item=Py_BuildValue("(s#O)",buf->data,l,self->value))
return PER_RETURN(self, NULL);
i=PyList_Append(r,item); i=PyList_Append(r,item);
Py_DECREF(item); Py_DECREF(item);
if(i < 0) return NULL; if(i < 0) return PER_RETURN(self, NULL);
} }
if(l==buf->size) if(l==buf->size)
{ {
buf->size *= 2; buf->size *= 2;
UNLESS(buf->data=realloc(buf->data, buf->size)) return PyErr_NoMemory(); UNLESS(buf->data=realloc(buf->data, buf->size))
return PER_RETURN(self, PyErr_NoMemory());
} }
if(self->bins) if(self->bins)
{ {
...@@ -201,24 +230,25 @@ getiork(TrieObject *self, PyObject * r, keybuf *buf, int l, int dokeys) ...@@ -201,24 +230,25 @@ getiork(TrieObject *self, PyObject * r, keybuf *buf, int l, int dokeys)
if(bin->ob_type==self->ob_type) if(bin->ob_type==self->ob_type)
{ {
buf->data[l]=self->min+ibin; buf->data[l]=self->min+ibin;
UNLESS(getiork((TrieObject*)bin,r,buf,l1,dokeys)) return NULL; UNLESS(getiork((TrieObject*)bin,r,buf,l1,dokeys))
return PER_RETURN(self, NULL);
} }
else if(PyTuple_Check(bin)) else if(PyTuple_Check(bin))
{ {
buf->data[l]=self->min+ibin; buf->data[l]=self->min+ibin;
UNLESS(item=PyString_FromStringAndSize(buf->data,l1)) UNLESS(item=PyString_FromStringAndSize(buf->data,l1))
return NULL; return PER_RETURN(self, NULL);
ASSIGN(item,PySequence_Concat(item,PyTuple_GET_ITEM(bin,0))); ASSIGN(item,PySequence_Concat(item,PyTuple_GET_ITEM(bin,0)));
if(! dokeys && item) if(! dokeys && item)
ASSIGN(item, Py_BuildValue("OO",item,PyTuple_GET_ITEM(bin,1))); ASSIGN(item, Py_BuildValue("OO",item,PyTuple_GET_ITEM(bin,1)));
UNLESS(item) return NULL; UNLESS(item) return PER_RETURN(self, NULL);
i=PyList_Append(r,item); i=PyList_Append(r,item);
Py_DECREF(item); Py_DECREF(item);
if(i < 0) return NULL; if(i < 0) return PER_RETURN(self, NULL);
} }
} }
} }
return r; return PER_RETURN(self, r);
} }
static PyObject * static PyObject *
...@@ -251,11 +281,12 @@ static PyObject * ...@@ -251,11 +281,12 @@ static PyObject *
Trie_cvalues(TrieObject *self, PyObject *r) Trie_cvalues(TrieObject *self, PyObject *r)
{ {
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return PER_RETURN(self, NULL);
#endif #endif
if(self->value) if(self->value)
if(PyList_Append(r,self->value) < 0) return NULL; if(PyList_Append(r,self->value) < 0) return PER_RETURN(self, NULL);
if(self->bins) if(self->bins)
{ {
PyObject *bin; PyObject *bin;
...@@ -266,13 +297,15 @@ Trie_cvalues(TrieObject *self, PyObject *r) ...@@ -266,13 +297,15 @@ Trie_cvalues(TrieObject *self, PyObject *r)
bin=PyList_GET_ITEM(LIST(self->bins), i); bin=PyList_GET_ITEM(LIST(self->bins), i);
if(bin->ob_type==self->ob_type) if(bin->ob_type==self->ob_type)
{ {
UNLESS(Trie_cvalues((TrieObject*)bin,r)) return NULL; UNLESS(Trie_cvalues((TrieObject*)bin,r))
return PER_RETURN(self, NULL);
} }
else if(PyTuple_Check(bin)) else if(PyTuple_Check(bin))
if(PyList_Append(r,PyTuple_GET_ITEM(bin,1)) < 0) return NULL; if(PyList_Append(r,PyTuple_GET_ITEM(bin,1)) < 0)
return PER_RETURN(self, NULL);
} }
} }
return r; return PER_RETURN(self, r);
} }
static PyObject * static PyObject *
...@@ -303,7 +336,9 @@ Trie_cclear(TrieObject *self) ...@@ -303,7 +336,9 @@ Trie_cclear(TrieObject *self)
#ifdef PERSISTENT #ifdef PERSISTENT
int changed=0; int changed=0;
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0)
return PER_INT_RETURN(self, -1);
#endif #endif
if(self->value) if(self->value)
...@@ -327,12 +362,14 @@ Trie_cclear(TrieObject *self) ...@@ -327,12 +362,14 @@ Trie_cclear(TrieObject *self)
bin=PyList_GET_ITEM(LIST(self->bins), i); bin=PyList_GET_ITEM(LIST(self->bins), i);
if(bin->ob_type==self->ob_type) if(bin->ob_type==self->ob_type)
{ {
if(Trie_cclear((TrieObject*)bin) < 0) return -1; if(Trie_cclear((TrieObject*)bin) < 0)
return PER_INT_RETURN(self, -1);
} }
else else
{ {
Py_INCREF(Py_None); Py_INCREF(Py_None);
if(PyList_SetItem(self->bins, i, Py_None) < 0) return -1; if(PyList_SetItem(self->bins, i, Py_None) < 0)
return PER_INT_RETURN(self, -1);
#ifdef PERSISTENT #ifdef PERSISTENT
changed=1; changed=1;
...@@ -343,10 +380,11 @@ Trie_cclear(TrieObject *self) ...@@ -343,10 +380,11 @@ Trie_cclear(TrieObject *self)
} }
#ifdef PERSISTENT #ifdef PERSISTENT
if(changed && cPersistenceCAPI->changed(PyOb(self)) < 0) return -1; if(changed && cPersistenceCAPI->changed(PyOb(self)) < 0)
return PER_INT_RETURN(self, -1);
#endif #endif
return 0; return PER_INT_RETURN(self, 0);
} }
static PyObject * static PyObject *
...@@ -381,14 +419,14 @@ static struct PyMethodDef Trie_methods[] = { ...@@ -381,14 +419,14 @@ static struct PyMethodDef Trie_methods[] = {
}; };
static PyObject * static PyObject *
NotFoundError() NotFoundError(PyObject *key)
{ {
PyErr_SetObject(PyExc_KeyError, Py_None); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
static PyObject * static PyObject *
Trie_cget(TrieObject *self, char *word) Trie_cget(TrieObject *self, char *word, PyObject *oword)
{ {
int c; int c;
char *k; char *k;
...@@ -397,42 +435,46 @@ Trie_cget(TrieObject *self, char *word) ...@@ -397,42 +435,46 @@ Trie_cget(TrieObject *self, char *word)
PyObject *key; PyObject *key;
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return PER_RETURN(self, NULL);
#endif #endif
typ=self->ob_type; typ=self->ob_type;
while(c=*word++) while(c=*word++)
{ {
if(! (bins=self->bins) || c < self->min) return NotFoundError(); if(! (bins=self->bins) || c < self->min)
return PER_RETURN(self, NotFoundError(oword));
c-=self->min; c-=self->min;
if(c >= PyList_SIZE(bins)) return NotFoundError(); if(c >= PyList_SIZE(bins)) return PER_RETURN(self, NotFoundError(oword));
self=(TrieObject *)PyList_GET_ITEM(LIST(bins), c); self=(TrieObject *)PyList_GET_ITEM(LIST(bins), c);
if(self->ob_type != typ) if(self->ob_type != typ)
if(PyTuple_Check(PyOb(self)) && if(PyTuple_Check(PyOb(self)) &&
PyString_Check((key=PyTuple_GET_ITEM(PyOb(self),0))) && PyString_Check((key=PyTuple_GET_ITEM(PyOb(self),0))) &&
strcmp(word,PyString_AS_STRING(STRING(key)))==0) strcmp(word,PyString_AS_STRING(STRING(key)))==0)
return PySequence_GetItem(PyOb(self),1); return PER_RETURN(self, PySequence_GetItem(PyOb(self),1));
else else
return NotFoundError(); return PER_RETURN(self, NotFoundError(oword));
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; if(cPersistenceCAPI->setstate(PyOb(self)) < 0)
return PER_RETURN(self, NULL);
#endif #endif
} }
if(! self->value) return NotFoundError(); if(! self->value) return PER_RETURN(self, NotFoundError(oword));
Py_INCREF(self->value); Py_INCREF(self->value);
return self->value; return PER_RETURN(self, self->value);
} }
static int static int
Trie_cset(TrieObject *self, char *word, PyObject *v) Trie_cset(TrieObject *self, char *word, PyObject *v, PyObject *oword)
{ {
PyObject *bin; PyObject *bin=0;
int c, r, max; int c, r, max;
#ifdef PERSISTENT #ifdef PERSISTENT
int ch=0; int ch=0;
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return -1; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) goto err;
#endif #endif
c=*word++; c=*word++;
...@@ -440,13 +482,14 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -440,13 +482,14 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
{ {
if(!v && !self->value) if(!v && !self->value)
{ {
NotFoundError(); NotFoundError(oword);
return -1; goto err;
} }
Py_XINCREF(v); Py_XINCREF(v);
ASSIGN(self->value, v); ASSIGN(self->value, v);
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->changed(PyOb(self)) < 0) return -1; if(cPersistenceCAPI->changed(PyOb(self)) < 0) goto err;
PER_ALLOW_DEACTIVATION(self);
#endif #endif
return 0; return 0;
} }
...@@ -454,12 +497,12 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -454,12 +497,12 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
(!self->bins || c < self->min || c-self->min >= PyList_SIZE(self->bins)) (!self->bins || c < self->min || c-self->min >= PyList_SIZE(self->bins))
) )
{ {
NotFoundError(); NotFoundError(oword);
return -1; goto err;
} }
if(! self->bins) if(! self->bins)
{ {
UNLESS(self->bins=PyList_New(1)) return -1; UNLESS(self->bins=PyList_New(1)) goto err;
self->min=c; self->min=c;
#ifdef PERSISTENT #ifdef PERSISTENT
ch=1; ch=1;
...@@ -468,7 +511,7 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -468,7 +511,7 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
else if(c < self->min) else if(c < self->min)
while(c < self->min) while(c < self->min)
{ {
if(PyList_Insert(self->bins,0,Py_None) < 0) return -1; if(PyList_Insert(self->bins,0,Py_None) < 0) goto err;
self->min--; self->min--;
#ifdef PERSISTENT #ifdef PERSISTENT
ch=1; ch=1;
...@@ -480,7 +523,7 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -480,7 +523,7 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
if(c > max) if(c > max)
while(c > max) while(c > max)
{ {
if(PyList_Append(self->bins,Py_None) < 0) return -1; if(PyList_Append(self->bins,Py_None) < 0) goto err;
max++; max++;
#ifdef PERSISTENT #ifdef PERSISTENT
ch=1; ch=1;
...@@ -504,8 +547,8 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -504,8 +547,8 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
} }
else else
{ {
NotFoundError(); NotFoundError(oword);
return -1; goto err;
} }
else else
{ {
...@@ -517,31 +560,40 @@ Trie_cset(TrieObject *self, char *word, PyObject *v) ...@@ -517,31 +560,40 @@ Trie_cset(TrieObject *self, char *word, PyObject *v)
PyObject *o; PyObject *o;
o=PyTuple_GET_ITEM(bin,1); o=PyTuple_GET_ITEM(bin,1);
UNLESS(bin=PyObject_GetAttr(PyOb(self),py___class__)) return -1; UNLESS(bin=PyObject_GetAttr(PyOb(self),py___class__)) goto err;
UNLESS_ASSIGN(bin,PyObject_CallObject(bin,NULL)) return -1; UNLESS_ASSIGN(bin,PyObject_CallObject(bin,NULL)) goto err;
if(Trie_cset((TrieObject*)bin, if(Trie_cset((TrieObject*)bin,
PyString_AS_STRING(STRING(key)),o) < 0 || PyString_AS_STRING(STRING(key)),o, oword) < 0 ||
Trie_cset((TrieObject*)bin,word,v) < 0 Trie_cset((TrieObject*)bin,word,v,oword) < 0
) goto err; ) goto err;
} }
else else
UNLESS(bin=Py_BuildValue("sO",word,v)) goto err; UNLESS(bin=Py_BuildValue("sO",word,v)) goto err;
} }
r=PyList_SetItem(self->bins, c, bin);
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->changed(PyOb(self)) < 0) goto err; if(cPersistenceCAPI->changed(PyOb(self)) < 0) goto err;
PER_ALLOW_DEACTIVATION(self);
#endif #endif
return PyList_SetItem(self->bins, c, bin); return r;
} }
r=Trie_cset((TrieObject*)bin,word,v,oword);
#ifdef PERSISTENT #ifdef PERSISTENT
if(ch && cPersistenceCAPI->changed(PyOb(self)) < 0) return -1; if(ch && cPersistenceCAPI->changed(PyOb(self)) < 0) goto err;
PER_ALLOW_DEACTIVATION(self);
#endif #endif
return Trie_cset((TrieObject*)bin,word,v); return r;
err: err:
Py_DECREF(bin); Py_XDECREF(bin);
#ifdef PERSISTENT
PER_ALLOW_DEACTIVATION(self);
#endif
return -1; return -1;
} }
...@@ -552,7 +604,9 @@ Trie_length(TrieObject *self) ...@@ -552,7 +604,9 @@ Trie_length(TrieObject *self)
PyObject *bin; PyObject *bin;
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->setstate(PyOb(self)) < 0) return NULL; PER_PREVENT_DEACTIVATION(self);
if(cPersistenceCAPI->setstate(PyOb(self)) < 0)
return PER_INT_RETURN(self, -1);
#endif #endif
if(self->bins) if(self->bins)
...@@ -562,24 +616,26 @@ Trie_length(TrieObject *self) ...@@ -562,24 +616,26 @@ Trie_length(TrieObject *self)
if(bin->ob_type==self->ob_type) if(bin->ob_type==self->ob_type)
{ {
li=Trie_length((TrieObject*)bin); li=Trie_length((TrieObject*)bin);
if(li < 0) return li; if(li < 0) return PER_INT_RETURN(self, li);
if(li) if(li)
l+=li; l+=li;
else else
{ {
#ifdef PERSISTENT #ifdef PERSISTENT
if(cPersistenceCAPI->changed(PyOb(self)) < 0) return -1; if(cPersistenceCAPI->changed(PyOb(self)) < 0)
return PER_INT_RETURN(self, -1);
#endif #endif
/* Database management concerns make us leery of this /* Database management concerns make us leery of this
Py_INCREF(Py_None); Py_INCREF(Py_None);
if(PyList_SetItem(self->bins, i, Py_None) < 1) return -1; if(PyList_SetItem(self->bins, i, Py_None) < 1)
return PER_INT_RETURN(self, -1);
*/ */
} }
} }
else if(PyTuple_Check(bin)) l++; else if(PyTuple_Check(bin)) l++;
} }
if(self->value) l++; if(self->value) l++;
return l; return PER_INT_RETURN(self, l);
} }
static PyObject * static PyObject *
...@@ -589,7 +645,7 @@ Trie_subscript(TrieObject *self, PyObject *key) ...@@ -589,7 +645,7 @@ Trie_subscript(TrieObject *self, PyObject *key)
if(PyString_Check(key)) if(PyString_Check(key))
{ {
UNLESS(word=PyString_AsString(key)) return NULL; UNLESS(word=PyString_AsString(key)) return NULL;
return Trie_cget(self,word); return Trie_cget(self,word,key);
} }
PyErr_SetString(PyExc_TypeError, "Only string keys are allowed for tries."); PyErr_SetString(PyExc_TypeError, "Only string keys are allowed for tries.");
return NULL; return NULL;
...@@ -602,10 +658,10 @@ Trie_ass_sub(TrieObject *self, PyObject *key, PyObject *v) ...@@ -602,10 +658,10 @@ Trie_ass_sub(TrieObject *self, PyObject *key, PyObject *v)
if(PyString_Check(key)) if(PyString_Check(key))
{ {
UNLESS(word=PyString_AsString(key)) return -1; UNLESS(word=PyString_AsString(key)) return -1;
return Trie_cset((TrieObject*)self,word,v); return Trie_cset((TrieObject*)self,word,v,key);
} }
PyErr_SetString(PyExc_TypeError, "Only string keys are allowed for tries."); PyErr_SetString(PyExc_TypeError, "Only string keys are allowed for tries.");
return NULL; return -1;
} }
static PyMappingMethods Trie_as_mapping = { static PyMappingMethods Trie_as_mapping = {
...@@ -707,7 +763,7 @@ void ...@@ -707,7 +763,7 @@ void
initTrie() initTrie()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.8 $"; char *rev="$Revision: 1.9 $";
UNLESS(ExtensionClassImported) return; UNLESS(ExtensionClassImported) return;
...@@ -747,6 +803,10 @@ initTrie() ...@@ -747,6 +803,10 @@ initTrie()
Revision Log: Revision Log:
$Log: Trie.c,v $ $Log: Trie.c,v $
Revision 1.9 1997/05/19 17:49:35 jim
Added logic to disable deactivation during methods. This sort of
logic will be needed for any C-based persistent object.
Revision 1.8 1997/05/08 21:09:49 jim Revision 1.8 1997/05/08 21:09:49 jim
Added clear method. Added clear method.
......
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