Commit c88dc766 authored by Jeremy Hylton's avatar Jeremy Hylton

Merge a bunch of changes accidentally committed on the jeremy-Standby-branch.

DB.py: typo in comment
cPickleCache.c: fix cache sweep logic
cPersistence.c: small performance changes
parent 20fc000a
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
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.43 2001/03/28 14:04:15 jim Exp $\n"; "$Id: cPersistence.c,v 1.44 2001/11/06 17:52:38 jeremy Exp $\n";
#include <string.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
...@@ -137,6 +137,20 @@ init_strings(void) ...@@ -137,6 +137,20 @@ init_strings(void)
return 0; return 0;
} }
static int
checknoargs(PyObject *args)
{
if (!PyTuple_Check(args))
return 0;
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(PyExc_TypeError,
"function takes exactly 0 arguments (%d given)",
PyTuple_GET_SIZE(args));
return 0;
}
return 1;
}
static PyObject * static PyObject *
callmethod(PyObject *self, PyObject *name) callmethod(PyObject *self, PyObject *name)
{ {
...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args) ...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if (idebug_log < 0) call_debug("reinit",self); if (idebug_log < 0) call_debug("reinit",self);
#endif #endif
if (args && ! PyArg_ParseTuple(args,"")) return NULL; if (args && !checknoargs(args))
return NULL;
if (self->state==cPersistent_UPTODATE_STATE && self->jar && if (self->state==cPersistent_UPTODATE_STATE && self->jar &&
HasInstDict(self) && (dict=INSTANCE_DICT(self))) HasInstDict(self) && (dict=INSTANCE_DICT(self)))
...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
{ {
PyObject *__dict__, *d=0; PyObject *__dict__, *d=0;
UNLESS(PyArg_ParseTuple(args, "")) return NULL; if (!checknoargs(args)) return NULL;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
if(idebug_log < 0) call_debug("get",self); if(idebug_log < 0) call_debug("get",self);
...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
{ {
if(PyString_Check(k) && (ck=PyString_AsString(k)) && if(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
{ {
UNLESS(d=PyDict_New()) goto err; UNLESS(d=PyDict_New()) goto err;
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
UNLESS(PyString_Check(k) && (ck=PyString_AsString(k)) && UNLESS(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
if(PyDict_SetItem(d,k,v) < 0) goto err; if(PyDict_SetItem(d,k,v) < 0) goto err;
return d; return d;
...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args) ...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args)
if(PyDict_Check(v)) if(PyDict_Check(v))
{ {
for(i=0; PyDict_Next(v,&i,&key,&e);) for(i=0; PyDict_Next(v, &i, &key, &e);)
if(PyObject_SetItem(__dict__,key,e) < 0) if(PyDict_SetItem(__dict__, key, e) < 0)
return NULL; return NULL;
} }
else else
...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
PyObject *r; PyObject *r;
if (PyString_Check(name)) if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL; UNLESS(s=PyString_AS_STRING(name)) return NULL;
r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro); r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
if (! r && self->state != cPersistent_GHOST_STATE && if (! r && self->state != cPersistent_GHOST_STATE &&
...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
) )
{ {
PyErr_Clear(); PyErr_Clear();
r=PyObject_GetAttr(OBJECT(self), py___getattr__); r=PyObject_GetAttr(OBJECT(self), py___getattr__);
if (r) if (r)
{ {
...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
char *name=""; char *name="";
UNLESS(oname) return -1; UNLESS(oname) return -1;
if(PyString_Check(oname)) UNLESS(name=PyString_AsString(oname)) return -1; if(PyString_Check(oname)) UNLESS(name=PyString_AS_STRING(oname)) return -1;
if(*name=='_' && name[1]=='p' && name[2]=='_') if(*name=='_' && name[1]=='p' && name[2]=='_')
{ {
...@@ -739,7 +755,7 @@ void ...@@ -739,7 +755,7 @@ void
initcPersistence(void) initcPersistence(void)
{ {
PyObject *m, *d, *s; PyObject *m, *d, *s;
char *rev="$Revision: 1.43 $"; char *rev="$Revision: 1.44 $";
s = PyString_FromString("TimeStamp"); s = PyString_FromString("TimeStamp");
if (s == NULL) if (s == NULL)
......
...@@ -85,13 +85,17 @@ ...@@ -85,13 +85,17 @@
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.33 2001/03/28 14:36:30 jim Exp $\n"; "$Id: cPickleCache.c,v 1.34 2001/11/06 17:52:38 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))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O) #define OBJECT(O) ((PyObject*)O)
/* Compute the current time in the units and range used for peristent
objects. */
#define PER_TIME() ((long)(time(NULL) / 3)) % 65536
#define DONT_USE_CPERSISTENCECAPI #define DONT_USE_CPERSISTENCECAPI
#include "cPersistence.h" #include "cPersistence.h"
#include <time.h> #include <time.h>
...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype; ...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype;
static int static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{ {
if (v && key) if (v && key)
{ {
self->n++; self->n++;
if(v->ob_refcnt <= 1) if(v->ob_refcnt <= 1)
{ {
self->sum_deal++; self->sum_deal++;
/* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the
current Python dictionary implementation. */
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && if (dt >= 0 &&
(! PyExtensionClass_Check(v)) && (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ && ((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE ((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
) )
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0)
now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt)
...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
state. state.
*/ */
self->sum_deac++; self->sum_deac++;
if (PyObject_SetAttr(v,py__p_changed,Py_None) < 0) if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear(); PyErr_Clear();
} }
} }
...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt) ...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt)
int i; int i;
long now; long now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if ((i=PyDict_Size(self->data)) < 1) return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
self->position=0; self->position=0;
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt) ...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt)
int i, l, last; int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if((last=PyDict_Size(self->data)) < 0) return -1; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
/* First time through should get refcounts to 1 */ /* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; while (l < last)
while(l < last)
{ {
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
last=l; return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv)
s=PyDict_Size(self->data); s=PyDict_Size(self->data);
if (s < 1) return s; if (s < 1) return s;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
size=self->cache_size; size=self->cache_size;
self->cache_size=0; self->cache_size=0;
...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv)
static PyObject * static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
UNLESS(-1 != fullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args) ...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
UNLESS(-1 != reallyfullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args)
{ {
int n=1; int n=1;
UNLESS (PyArg_ParseTuple(args, "|i",&n)) return NULL; UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
for (; --n >= 0;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if(maybegc(self,NULL) < 0) return NULL;
...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key) ...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key)
} }
else else
{ {
v=PyObject_CallFunction(self->setklassstate, PyObject *t = PyTuple_New(1);
"O", v); if (t)
{
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_Call(self->setklassstate, t, NULL);
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
v = t;
}
if (v) Py_DECREF(v); if (v) Py_DECREF(v);
else PyErr_Clear(); else PyErr_Clear();
} }
else if (PyObject_DelAttr(v,py__p_changed) < 0) else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear(); PyErr_Clear();
} }
else PyErr_Clear(); else
{
if (PyErr_Occurred())
PyErr_Clear();
}
} }
static PyObject * static PyObject *
...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args)
} }
else { else {
PyErr_Clear(); PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O", &inv)) return NULL; UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv)) if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv==Py_None) /* All */
...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args) ...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args,"O|O", &key, &d)) return NULL; UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) UNLESS (r=PyDict_GetItem(self->data, key))
{ {
if (d) if (d)
{ {
if (PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
r=d; r=d;
} }
...@@ -679,7 +727,7 @@ void ...@@ -679,7 +727,7 @@ void
initcPickleCache(void) initcPickleCache(void)
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.33 $"; char *rev="$Revision: 1.34 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
......
...@@ -84,8 +84,8 @@ ...@@ -84,8 +84,8 @@
############################################################################## ##############################################################################
"""Database objects """Database objects
$Id: DB.py,v 1.33 2001/08/27 19:25:19 shane Exp $""" $Id: DB.py,v 1.34 2001/11/06 17:52:38 jeremy Exp $"""
__version__='$Revision: 1.33 $'[11:-2] __version__='$Revision: 1.34 $'[11:-2]
import cPickle, cStringIO, sys, POSException, UndoLogCompatible import cPickle, cStringIO, sys, POSException, UndoLogCompatible
from Connection import Connection from Connection import Connection
...@@ -442,7 +442,7 @@ class DB(UndoLogCompatible.UndoLogCompatible): ...@@ -442,7 +442,7 @@ class DB(UndoLogCompatible.UndoLogCompatible):
# Pool locks are tricky. Basically, the lock needs to be # Pool locks are tricky. Basically, the lock needs to be
# set whenever the pool becomes empty so that threads are # set whenever the pool becomes empty so that threads are
# forced to wait until the pool gets a connection it it. # forced to wait until the pool gets a connection in it.
# The lock is acquired when the (empty) pool is # The lock is acquired when the (empty) pool is
# created. The The lock is acquired just prior to removing # created. The The lock is acquired just prior to removing
# the last connection from the pool and just after adding # the last connection from the pool and just after adding
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
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.43 2001/03/28 14:04:15 jim Exp $\n"; "$Id: cPersistence.c,v 1.44 2001/11/06 17:52:38 jeremy Exp $\n";
#include <string.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
...@@ -137,6 +137,20 @@ init_strings(void) ...@@ -137,6 +137,20 @@ init_strings(void)
return 0; return 0;
} }
static int
checknoargs(PyObject *args)
{
if (!PyTuple_Check(args))
return 0;
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(PyExc_TypeError,
"function takes exactly 0 arguments (%d given)",
PyTuple_GET_SIZE(args));
return 0;
}
return 1;
}
static PyObject * static PyObject *
callmethod(PyObject *self, PyObject *name) callmethod(PyObject *self, PyObject *name)
{ {
...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args) ...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if (idebug_log < 0) call_debug("reinit",self); if (idebug_log < 0) call_debug("reinit",self);
#endif #endif
if (args && ! PyArg_ParseTuple(args,"")) return NULL; if (args && !checknoargs(args))
return NULL;
if (self->state==cPersistent_UPTODATE_STATE && self->jar && if (self->state==cPersistent_UPTODATE_STATE && self->jar &&
HasInstDict(self) && (dict=INSTANCE_DICT(self))) HasInstDict(self) && (dict=INSTANCE_DICT(self)))
...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
{ {
PyObject *__dict__, *d=0; PyObject *__dict__, *d=0;
UNLESS(PyArg_ParseTuple(args, "")) return NULL; if (!checknoargs(args)) return NULL;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
if(idebug_log < 0) call_debug("get",self); if(idebug_log < 0) call_debug("get",self);
...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
{ {
if(PyString_Check(k) && (ck=PyString_AsString(k)) && if(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
{ {
UNLESS(d=PyDict_New()) goto err; UNLESS(d=PyDict_New()) goto err;
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
UNLESS(PyString_Check(k) && (ck=PyString_AsString(k)) && UNLESS(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
if(PyDict_SetItem(d,k,v) < 0) goto err; if(PyDict_SetItem(d,k,v) < 0) goto err;
return d; return d;
...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args) ...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args)
if(PyDict_Check(v)) if(PyDict_Check(v))
{ {
for(i=0; PyDict_Next(v,&i,&key,&e);) for(i=0; PyDict_Next(v, &i, &key, &e);)
if(PyObject_SetItem(__dict__,key,e) < 0) if(PyDict_SetItem(__dict__, key, e) < 0)
return NULL; return NULL;
} }
else else
...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
PyObject *r; PyObject *r;
if (PyString_Check(name)) if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL; UNLESS(s=PyString_AS_STRING(name)) return NULL;
r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro); r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
if (! r && self->state != cPersistent_GHOST_STATE && if (! r && self->state != cPersistent_GHOST_STATE &&
...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
) )
{ {
PyErr_Clear(); PyErr_Clear();
r=PyObject_GetAttr(OBJECT(self), py___getattr__); r=PyObject_GetAttr(OBJECT(self), py___getattr__);
if (r) if (r)
{ {
...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
char *name=""; char *name="";
UNLESS(oname) return -1; UNLESS(oname) return -1;
if(PyString_Check(oname)) UNLESS(name=PyString_AsString(oname)) return -1; if(PyString_Check(oname)) UNLESS(name=PyString_AS_STRING(oname)) return -1;
if(*name=='_' && name[1]=='p' && name[2]=='_') if(*name=='_' && name[1]=='p' && name[2]=='_')
{ {
...@@ -739,7 +755,7 @@ void ...@@ -739,7 +755,7 @@ void
initcPersistence(void) initcPersistence(void)
{ {
PyObject *m, *d, *s; PyObject *m, *d, *s;
char *rev="$Revision: 1.43 $"; char *rev="$Revision: 1.44 $";
s = PyString_FromString("TimeStamp"); s = PyString_FromString("TimeStamp");
if (s == NULL) if (s == NULL)
......
...@@ -85,13 +85,17 @@ ...@@ -85,13 +85,17 @@
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.33 2001/03/28 14:36:30 jim Exp $\n"; "$Id: cPickleCache.c,v 1.34 2001/11/06 17:52:38 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))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O) #define OBJECT(O) ((PyObject*)O)
/* Compute the current time in the units and range used for peristent
objects. */
#define PER_TIME() ((long)(time(NULL) / 3)) % 65536
#define DONT_USE_CPERSISTENCECAPI #define DONT_USE_CPERSISTENCECAPI
#include "cPersistence.h" #include "cPersistence.h"
#include <time.h> #include <time.h>
...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype; ...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype;
static int static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{ {
if (v && key) if (v && key)
{ {
self->n++; self->n++;
if(v->ob_refcnt <= 1) if(v->ob_refcnt <= 1)
{ {
self->sum_deal++; self->sum_deal++;
/* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the
current Python dictionary implementation. */
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && if (dt >= 0 &&
(! PyExtensionClass_Check(v)) && (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ && ((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE ((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
) )
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0)
now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt)
...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
state. state.
*/ */
self->sum_deac++; self->sum_deac++;
if (PyObject_SetAttr(v,py__p_changed,Py_None) < 0) if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear(); PyErr_Clear();
} }
} }
...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt) ...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt)
int i; int i;
long now; long now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if ((i=PyDict_Size(self->data)) < 1) return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
self->position=0; self->position=0;
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt) ...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt)
int i, l, last; int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if((last=PyDict_Size(self->data)) < 0) return -1; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
/* First time through should get refcounts to 1 */ /* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; while (l < last)
while(l < last)
{ {
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
last=l; return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv)
s=PyDict_Size(self->data); s=PyDict_Size(self->data);
if (s < 1) return s; if (s < 1) return s;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
size=self->cache_size; size=self->cache_size;
self->cache_size=0; self->cache_size=0;
...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv)
static PyObject * static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
UNLESS(-1 != fullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args) ...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
UNLESS(-1 != reallyfullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args)
{ {
int n=1; int n=1;
UNLESS (PyArg_ParseTuple(args, "|i",&n)) return NULL; UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
for (; --n >= 0;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if(maybegc(self,NULL) < 0) return NULL;
...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key) ...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key)
} }
else else
{ {
v=PyObject_CallFunction(self->setklassstate, PyObject *t = PyTuple_New(1);
"O", v); if (t)
{
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_Call(self->setklassstate, t, NULL);
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
v = t;
}
if (v) Py_DECREF(v); if (v) Py_DECREF(v);
else PyErr_Clear(); else PyErr_Clear();
} }
else if (PyObject_DelAttr(v,py__p_changed) < 0) else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear(); PyErr_Clear();
} }
else PyErr_Clear(); else
{
if (PyErr_Occurred())
PyErr_Clear();
}
} }
static PyObject * static PyObject *
...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args)
} }
else { else {
PyErr_Clear(); PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O", &inv)) return NULL; UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv)) if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv==Py_None) /* All */
...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args) ...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args,"O|O", &key, &d)) return NULL; UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) UNLESS (r=PyDict_GetItem(self->data, key))
{ {
if (d) if (d)
{ {
if (PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
r=d; r=d;
} }
...@@ -679,7 +727,7 @@ void ...@@ -679,7 +727,7 @@ void
initcPickleCache(void) initcPickleCache(void)
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.33 $"; char *rev="$Revision: 1.34 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
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.43 2001/03/28 14:04:15 jim Exp $\n"; "$Id: cPersistence.c,v 1.44 2001/11/06 17:52:38 jeremy Exp $\n";
#include <string.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
...@@ -137,6 +137,20 @@ init_strings(void) ...@@ -137,6 +137,20 @@ init_strings(void)
return 0; return 0;
} }
static int
checknoargs(PyObject *args)
{
if (!PyTuple_Check(args))
return 0;
if (PyTuple_GET_SIZE(args) != 0) {
PyErr_Format(PyExc_TypeError,
"function takes exactly 0 arguments (%d given)",
PyTuple_GET_SIZE(args));
return 0;
}
return 1;
}
static PyObject * static PyObject *
callmethod(PyObject *self, PyObject *name) callmethod(PyObject *self, PyObject *name)
{ {
...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args) ...@@ -243,7 +257,8 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if (idebug_log < 0) call_debug("reinit",self); if (idebug_log < 0) call_debug("reinit",self);
#endif #endif
if (args && ! PyArg_ParseTuple(args,"")) return NULL; if (args && !checknoargs(args))
return NULL;
if (self->state==cPersistent_UPTODATE_STATE && self->jar && if (self->state==cPersistent_UPTODATE_STATE && self->jar &&
HasInstDict(self) && (dict=INSTANCE_DICT(self))) HasInstDict(self) && (dict=INSTANCE_DICT(self)))
...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -273,7 +288,7 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
{ {
PyObject *__dict__, *d=0; PyObject *__dict__, *d=0;
UNLESS(PyArg_ParseTuple(args, "")) return NULL; if (!checknoargs(args)) return NULL;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
if(idebug_log < 0) call_debug("get",self); if(idebug_log < 0) call_debug("get",self);
...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args) ...@@ -289,12 +304,12 @@ Per__getstate__(cPersistentObject *self, PyObject *args)
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
{ {
if(PyString_Check(k) && (ck=PyString_AsString(k)) && if(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
{ {
UNLESS(d=PyDict_New()) goto err; UNLESS(d=PyDict_New()) goto err;
for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); ) for(pos=0; PyDict_Next(__dict__, &pos, &k, &v); )
UNLESS(PyString_Check(k) && (ck=PyString_AsString(k)) && UNLESS(PyString_Check(k) && (ck=PyString_AS_STRING(k)) &&
(*ck=='_' && ck[1]=='v' && ck[2]=='_')) (*ck=='_' && ck[1]=='v' && ck[2]=='_'))
if(PyDict_SetItem(d,k,v) < 0) goto err; if(PyDict_SetItem(d,k,v) < 0) goto err;
return d; return d;
...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args) ...@@ -331,8 +346,8 @@ Per__setstate__(cPersistentObject *self, PyObject *args)
if(PyDict_Check(v)) if(PyDict_Check(v))
{ {
for(i=0; PyDict_Next(v,&i,&key,&e);) for(i=0; PyDict_Next(v, &i, &key, &e);)
if(PyObject_SetItem(__dict__,key,e) < 0) if(PyDict_SetItem(__dict__, key, e) < 0)
return NULL; return NULL;
} }
else else
...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -483,7 +498,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
PyObject *r; PyObject *r;
if (PyString_Check(name)) if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL; UNLESS(s=PyString_AS_STRING(name)) return NULL;
r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro); r = Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
if (! r && self->state != cPersistent_GHOST_STATE && if (! r && self->state != cPersistent_GHOST_STATE &&
...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name) ...@@ -492,6 +507,7 @@ Per_getattro(cPersistentObject *self, PyObject *name)
) )
{ {
PyErr_Clear(); PyErr_Clear();
r=PyObject_GetAttr(OBJECT(self), py___getattr__); r=PyObject_GetAttr(OBJECT(self), py___getattr__);
if (r) if (r)
{ {
...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -510,7 +526,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
char *name=""; char *name="";
UNLESS(oname) return -1; UNLESS(oname) return -1;
if(PyString_Check(oname)) UNLESS(name=PyString_AsString(oname)) return -1; if(PyString_Check(oname)) UNLESS(name=PyString_AS_STRING(oname)) return -1;
if(*name=='_' && name[1]=='p' && name[2]=='_') if(*name=='_' && name[1]=='p' && name[2]=='_')
{ {
...@@ -739,7 +755,7 @@ void ...@@ -739,7 +755,7 @@ void
initcPersistence(void) initcPersistence(void)
{ {
PyObject *m, *d, *s; PyObject *m, *d, *s;
char *rev="$Revision: 1.43 $"; char *rev="$Revision: 1.44 $";
s = PyString_FromString("TimeStamp"); s = PyString_FromString("TimeStamp");
if (s == NULL) if (s == NULL)
......
...@@ -85,13 +85,17 @@ ...@@ -85,13 +85,17 @@
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.33 2001/03/28 14:36:30 jim Exp $\n"; "$Id: cPickleCache.c,v 1.34 2001/11/06 17:52:38 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))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O) #define OBJECT(O) ((PyObject*)O)
/* Compute the current time in the units and range used for peristent
objects. */
#define PER_TIME() ((long)(time(NULL) / 3)) % 65536
#define DONT_USE_CPERSISTENCECAPI #define DONT_USE_CPERSISTENCECAPI
#include "cPersistence.h" #include "cPersistence.h"
#include <time.h> #include <time.h>
...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype; ...@@ -142,24 +146,27 @@ staticforward PyTypeObject Cctype;
static int static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{ {
if (v && key) if (v && key)
{ {
self->n++; self->n++;
if(v->ob_refcnt <= 1) if(v->ob_refcnt <= 1)
{ {
self->sum_deal++; self->sum_deal++;
/* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the
current Python dictionary implementation. */
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && if (dt >= 0 &&
(! PyExtensionClass_Check(v)) && (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ && ((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE ((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
) )
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0)
now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt)
...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -169,7 +176,7 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
state. state.
*/ */
self->sum_deac++; self->sum_deac++;
if (PyObject_SetAttr(v,py__p_changed,Py_None) < 0) if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear(); PyErr_Clear();
} }
} }
...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt) ...@@ -220,15 +227,18 @@ fullgc(ccobject *self, int dt)
int i; int i;
long now; long now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if ((i=PyDict_Size(self->data)) < 1) return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
self->position=0; self->position=0;
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt) ...@@ -243,24 +253,35 @@ reallyfullgc(ccobject *self, int dt)
int i, l, last; int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) return 0; if (self->cache_size < 1)
if((last=PyDict_Size(self->data)) < 0) return -1; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
if (dt < 0) dt=0; if (dt > 0)
else dt /= 3; dt /= 3;
/* First time through should get refcounts to 1 */ /* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; while (l < last)
while(l < last)
{ {
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if(gc_item(self,key,v,now,dt) < 0) return -1; if (gc_item(self, key, v, now, dt) < 0)
last=l; return -1;
if((l=PyDict_Size(self->data)) < 0) return -1; last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if(now-self->last_check > 1) update_stats(self, now);
...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -280,7 +301,7 @@ maybegc(ccobject *self, PyObject *thisv)
s=PyDict_Size(self->data); s=PyDict_Size(self->data);
if (s < 1) return s; if (s < 1) return s;
now=((long)(time(NULL)/3))%65536; now = PER_TIME();
size=self->cache_size; size=self->cache_size;
self->cache_size=0; self->cache_size=0;
...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -322,9 +343,15 @@ maybegc(ccobject *self, PyObject *thisv)
static PyObject * static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
UNLESS(-1 != fullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args) ...@@ -332,9 +359,15 @@ cc_full_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt=0; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i", &dt)) return NULL; UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
UNLESS(-1 != reallyfullgc(self,dt)) return NULL; if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
}
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -344,7 +377,7 @@ cc_incrgc(ccobject *self, PyObject *args)
{ {
int n=1; int n=1;
UNLESS (PyArg_ParseTuple(args, "|i",&n)) return NULL; UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
for (; --n >= 0;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if(maybegc(self,NULL) < 0) return NULL;
...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key) ...@@ -369,15 +402,29 @@ _invalidate(ccobject *self, PyObject *key)
} }
else else
{ {
v=PyObject_CallFunction(self->setklassstate, PyObject *t = PyTuple_New(1);
"O", v); if (t)
{
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_Call(self->setklassstate, t, NULL);
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
v = t;
}
if (v) Py_DECREF(v); if (v) Py_DECREF(v);
else PyErr_Clear(); else PyErr_Clear();
} }
else if (PyObject_DelAttr(v,py__p_changed) < 0) else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear(); PyErr_Clear();
} }
else PyErr_Clear(); else
{
if (PyErr_Occurred())
PyErr_Clear();
}
} }
static PyObject * static PyObject *
...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -400,7 +447,7 @@ cc_invalidate(ccobject *self, PyObject *args)
} }
else { else {
PyErr_Clear(); PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O", &inv)) return NULL; UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv)) if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv==Py_None) /* All */
...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args) ...@@ -431,12 +478,13 @@ cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args,"O|O", &key, &d)) return NULL; UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) UNLESS (r=PyDict_GetItem(self->data, key))
{ {
if (d) if (d)
{ {
if (PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
r=d; r=d;
} }
...@@ -679,7 +727,7 @@ void ...@@ -679,7 +727,7 @@ void
initcPickleCache(void) initcPickleCache(void)
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.33 $"; char *rev="$Revision: 1.34 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
......
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