Commit 5c0bad8d authored by Jeremy Hylton's avatar Jeremy Hylton

Major reformatting of code along with a few sundry changes.

Summary of changes:

- Add function gc_all_items() to call gc_item() on everything in
  dict.  This factors out common code in all the gc methods.

- Add check_size() function that factors out code to check cache size
  before starting a gc.

- Simplify argument processing in cc_invalidate(), avoiding a second
  call to PyArg_ParseTuple() when argument is a sequence instead of a
  dictionary.

- Chance code to reflect belief that NULL return from PyDict_GetItem()
  does not set exception, except in cases that don't apply for the
  pickle cache like comparing a string with high-order bit set to a
  Unicode object.

- Use if (!expr) instead of UNLESS().

- Remove all statements from conditionals.

- Reformat to 4 spaces and Python-style brace placement.

- Put whitespace around operators and after commas.
parent d6750225
......@@ -13,12 +13,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.38 2002/01/25 14:51:55 gvanrossum Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O)
"$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy Exp $\n";
/* Compute the current time in the units and range used for peristent
objects. */
......@@ -33,23 +28,23 @@ static char cPickleCache_doc_string[] =
static PyObject *py_reload, *py__p_jar, *py__p_changed;
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
} ccobject;
#define WEIGHTING_PERIOD 600
......@@ -74,102 +69,116 @@ staticforward PyTypeObject Cctype;
static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{
if (v && key)
{
self->n++;
if(v->ob_refcnt <= 1)
{
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);
}
if (!(v && key))
return 0;
self->n++;
/* If there is at most one reference to this object, then the
cache has the only reference. It can be removed. */
if (v->ob_refcnt <= 1) {
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);
}
if (dt >= 0 &&
(! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
)
{
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt)
{
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
if (dt >= 0 &&
(!PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE) {
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt) {
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear();
}
}
}
return 0;
return 0;
}
static void
update_stats(ccobject *self, time_t now)
{
double d, deal, deac;
d=now-self->last_check;
if(d < 1) return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/
(self->dfa+self->na))*3;
self->sum_age=0;
deac=self->sum_deac/d;
self->sum_deac=0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/
(self->dfa+self->na));
self->sum_deac=0;
self->dfa += self->na;
self->na=0;
double d, deal, deac;
d = now - self->last_check;
if(d < 1)
return;
self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa + self->na)) * 3;
self->sum_age = 0;
deac = self->sum_deac / d;
self->sum_deac = 0;
self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa + self->na));
self->sum_deac = 0;
self->dfa += self->na;
self->na = 0;
deal=self->sum_deal/d;
self->sum_deal = 0;
self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n));
self->sum_deal = 0;
self->df += self->n;
self->n = 0;
self->last_check = now;
}
deal=self->sum_deal/d;
self->sum_deal=0;
self->mean_deal=((self->mean_deal*self->df +deal)/
(self->df +self->n));
self->sum_deal=0;
static int
check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
self->df += self->n;
self->n=0;
static int
gc_all_items(ccobject *self, int now, int dt)
{
PyObject *key, *v;
int i;
self->last_check=now;
for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0;
}
static int
fullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i;
long now;
long now;
if (self->cache_size < 1)
return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
if (check_size(self) <= 0)
return 0;
now = PER_TIME();
if (dt > 0)
dt /= 3;
now = PER_TIME();
dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
if (gc_all_items(self, 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);
return 0;
}
......@@ -177,139 +186,135 @@ fullgc(ccobject *self, int dt)
static int
reallyfullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i, l, last;
time_t now;
if (self->cache_size < 1)
return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
int l, last;
time_t now;
now = PER_TIME();
if (dt > 0)
dt /= 3;
last = check_size(self);
if (last <= 0)
return 0;
/* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
now = PER_TIME();
/* Units are 3 seconds */
dt /= 3;
l = PyDict_Size(self->data);
/* First time through should get refcounts to 1 */
if (gc_all_items(self, now, dt) < 0)
return -1;
if (l < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
while (l < last)
{
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
/* Now continue to collect until the size of the cache stops
decreasing. */
while (l < last) {
if (gc_all_items(self, now, dt) < 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);
self->position=0;
return 0;
if (now - self->last_check > 1)
update_stats(self, now);
self->position = 0;
return 0;
}
static int
maybegc(ccobject *self, PyObject *thisv)
{
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0;
s=PyDict_Size(self->data);
if (s < 1) return s;
now = PER_TIME();
size=self->cache_size;
self->cache_size=0;
/* Decide how many objects to look at */
n=(s-size)/10;
if (n < 3) n=3;
/* Decide how much time to give them before deactivating them */
s=8*size/s;
if (s > 100) s=100;
dt=(long)(self->cache_age*(0.2+0.1*s));
/* Units are 3 seconds */
dt /= 3;
if (dt < 1) dt=1;
while (--n >= 0)
{
if (PyDict_Next(self->data, &(self->position), &key, &v))
{
if (v != thisv && gc_item(self,key,v,now,dt) < 0)
{
self->cache_size=size;
return -1;
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
s = check_size(self);
if (s <= 0)
return 0;
now = PER_TIME();
size = self->cache_size;
self->cache_size = 0;
/* Decide how many objects to look at */
n = (s - size) / 10;
if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */
s = 8 * size / s;
if (s > 100)
s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */
dt /= 3;
while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
if (v != thisv && gc_item(self, key, v, now, dt) < 0) {
self->cache_size=size;
return -1;
}
}
else
self->position=0;
else
self->position = 0;
}
self->cache_size=size;
if (now-self->last_check > 1) update_stats(self, now);
self->cache_size = size;
if (now - self->last_check > 1)
update_stats(self, now);
return 0;
return 0;
}
static PyObject *
cc_full_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:full_sweep", &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);
return Py_None;
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:minimize", &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);
return Py_None;
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_incrgc(ccobject *self, PyObject *args)
{
int n=1;
int n = 1;
UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
if (!PyArg_ParseTuple(args, "|i:incrgr", &n))
return NULL;
for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL;
if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -317,114 +322,108 @@ cc_incrgc(ccobject *self, PyObject *args)
static void
_invalidate(ccobject *self, PyObject *key)
{
PyObject *v;
PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key)))
{
if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1)
{
if (!v)
return;
if (PyExtensionClass_Check(v))
if (v->ob_refcnt <= 1) {
self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear();
}
else
{
PyErr_Clear();
} else {
PyObject *t = PyTuple_New(1);
if (t)
{
if (t) {
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t);
/* Set tuple element to NULL so that deallocating the
tuple does not decref t.
*/
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
} else
v = t;
}
if (v) Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else
{
if (PyErr_Occurred())
if (v)
Py_DECREF(v);
else
PyErr_Clear();
}
else if (PyObject_DelAttr(v, py__p_changed) < 0)
PyErr_Clear();
}
}
static void
_invalidate_all(ccobject *self)
{
PyObject *key, *v;
int i;
for (i = 0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
}
static PyObject *
cc_invalidate(ccobject *self, PyObject *args)
{
PyObject *inv, *key, *v;
int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) {
for (i=0; PyDict_Next(inv, &i, &key, &v); )
if (key==Py_None)
{ /* Eek some nitwit invalidated everything! */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
}
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv==Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
PyObject *inv, *key, *v;
int i;
if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
return NULL;
if (PyDict_Check(inv)) {
for (i = 0; PyDict_Next(inv, &i, &key, &v); )
if (key == Py_None) {
/* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
} else if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv == Py_None) /* All */
_invalidate_all(self);
else {
int l;
PyErr_Clear();
if ((l=PyObject_Length(inv)) < 0) return NULL;
for(i=l; --i >= 0; )
{
UNLESS (key=PySequence_GetItem(inv, i)) return NULL;
_invalidate(self, key);
Py_DECREF(key);
int l = PyObject_Length(inv);
if (l < 0)
return NULL;
for (i = l; --i >= 0; ) {
key = PySequence_GetItem(inv, i);
if (!key)
return NULL;
_invalidate(self, key);
Py_DECREF(key);
}
PySequence_DelSlice(inv, 0, l);
PySequence_DelSlice(inv, 0, l);
}
}
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_get(ccobject *self, PyObject *args)
{
PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
PyObject *r, *key, *d = NULL;
UNLESS (r=PyDict_GetItem(self->data, key))
{
if (d)
{
if (PyErr_Occurred())
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
if (d)
r = d;
else {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
}
Py_INCREF(r);
return r;
Py_INCREF(r);
return r;
}
......@@ -454,107 +453,115 @@ static struct PyMethodDef cc_methods[] = {
static ccobject *
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
self->setklassstate=self->jar=NULL;
if((self->data=PyDict_New()))
{
self->jar=jar;
Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate"))
self = PyObject_NEW(ccobject, &Cctype);
if (!self)
return NULL;
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
self->sum_deal=0;
self->sum_deac=0;
self->sum_age=0;
self->mean_deal=0;
self->mean_deac=0;
self->mean_age=0;
self->df=1;
self->dfa=1;
self->n=0;
self->na=0;
self->last_check=time(NULL);
return self;
self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar;
Py_INCREF(jar);
self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
if (!self->setklassstate) {
Py_DECREF(jar);
Py_DECREF(self->data);
goto error;
}
self->position = 0;
self->cache_size = cache_size;
self->cache_age = cache_age < 1 ? 1 : cache_age;
self->sum_deal = 0;
self->sum_deac = 0;
self->sum_age = 0;
self->mean_deal = 0;
self->mean_deac = 0;
self->mean_age = 0;
self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self;
}
Py_DECREF(self);
return NULL;
error:
Py_DECREF(self);
return NULL;
}
static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
}
static PyObject *
cc_getattr(ccobject *self, char *name)
{
PyObject *r;
if(*name=='c')
{
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0)
return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0)
{
Py_INCREF(self->data);
return self->data;
PyObject *r;
if (*name == 'c') {
if(strcmp(name, "cache_age") == 0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df);
if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name, "cache_data") == 0) {
Py_INCREF(self->data);
return self->data;
}
}
if((*name=='h' && strcmp(name, "has_key")==0) ||
(*name=='i' && strcmp(name, "items")==0) ||
(*name=='k' && strcmp(name, "keys")==0)
)
return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name)))
if ((strcmp(name, "has_key") == 0)
|| (strcmp(name, "items") == 0)
|| (strcmp(name, "keys") == 0))
return PyObject_GetAttrString(self->data, name);
r = Py_FindMethod(cc_methods, (PyObject *)self, name);
if (!r) {
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
return r;
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
static int
cc_setattr(ccobject *self, char *name, PyObject *value)
{
if(value)
{
if (value) {
int v;
if(strcmp(name,"cache_age")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
if(v > 0)self->cache_age=v;
if (strcmp(name, "cache_age") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
if (v > 0)
self->cache_age = v;
return 0;
}
}
if(strcmp(name,"cache_size")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
self->cache_size=v;
if (strcmp(name, "cache_size") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
self->cache_size = v;
return 0;
}
}
}
}
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
......@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int
cc_length(ccobject *self)
{
return PyObject_Length(self->data);
return PyDict_Size(self->data);
}
static PyObject *
......@@ -570,10 +577,10 @@ cc_subscript(ccobject *self, PyObject *key)
{
PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key))
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
Py_INCREF(r);
......@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{
if(v)
{
if (v) {
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
......@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
};
static PyObject *
......@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000;
PyObject *jar;
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
if (!PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
return (PyObject *)newccobject(jar, cache_size, cache_age);
}
static struct PyMethodDef cCM_methods[] = {
......@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void
initcPickleCache(void)
{
PyObject *m, *d;
PyObject *m;
Cctype.ob_type=&PyType_Type;
Cctype.ob_type = &PyType_Type;
UNLESS(ExtensionClassImported) return;
if (!ExtensionClassImported)
return;
m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m);
py_reload=PyString_FromString("reload");
py__p_jar=PyString_FromString("_p_jar");
py__p_changed=PyString_FromString("_p_changed");
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module cPickleCache");
py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py__p_changed = PyString_InternFromString("_p_changed");
}
......@@ -13,12 +13,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.38 2002/01/25 14:51:55 gvanrossum Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O)
"$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy Exp $\n";
/* Compute the current time in the units and range used for peristent
objects. */
......@@ -33,23 +28,23 @@ static char cPickleCache_doc_string[] =
static PyObject *py_reload, *py__p_jar, *py__p_changed;
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
} ccobject;
#define WEIGHTING_PERIOD 600
......@@ -74,102 +69,116 @@ staticforward PyTypeObject Cctype;
static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{
if (v && key)
{
self->n++;
if(v->ob_refcnt <= 1)
{
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);
}
if (!(v && key))
return 0;
self->n++;
/* If there is at most one reference to this object, then the
cache has the only reference. It can be removed. */
if (v->ob_refcnt <= 1) {
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);
}
if (dt >= 0 &&
(! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
)
{
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt)
{
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
if (dt >= 0 &&
(!PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE) {
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt) {
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear();
}
}
}
return 0;
return 0;
}
static void
update_stats(ccobject *self, time_t now)
{
double d, deal, deac;
d=now-self->last_check;
if(d < 1) return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/
(self->dfa+self->na))*3;
self->sum_age=0;
deac=self->sum_deac/d;
self->sum_deac=0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/
(self->dfa+self->na));
self->sum_deac=0;
self->dfa += self->na;
self->na=0;
double d, deal, deac;
d = now - self->last_check;
if(d < 1)
return;
self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa + self->na)) * 3;
self->sum_age = 0;
deac = self->sum_deac / d;
self->sum_deac = 0;
self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa + self->na));
self->sum_deac = 0;
self->dfa += self->na;
self->na = 0;
deal=self->sum_deal/d;
self->sum_deal = 0;
self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n));
self->sum_deal = 0;
self->df += self->n;
self->n = 0;
self->last_check = now;
}
deal=self->sum_deal/d;
self->sum_deal=0;
self->mean_deal=((self->mean_deal*self->df +deal)/
(self->df +self->n));
self->sum_deal=0;
static int
check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
self->df += self->n;
self->n=0;
static int
gc_all_items(ccobject *self, int now, int dt)
{
PyObject *key, *v;
int i;
self->last_check=now;
for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0;
}
static int
fullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i;
long now;
long now;
if (self->cache_size < 1)
return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
if (check_size(self) <= 0)
return 0;
now = PER_TIME();
if (dt > 0)
dt /= 3;
now = PER_TIME();
dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
if (gc_all_items(self, 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);
return 0;
}
......@@ -177,139 +186,135 @@ fullgc(ccobject *self, int dt)
static int
reallyfullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i, l, last;
time_t now;
if (self->cache_size < 1)
return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
int l, last;
time_t now;
now = PER_TIME();
if (dt > 0)
dt /= 3;
last = check_size(self);
if (last <= 0)
return 0;
/* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
now = PER_TIME();
/* Units are 3 seconds */
dt /= 3;
l = PyDict_Size(self->data);
/* First time through should get refcounts to 1 */
if (gc_all_items(self, now, dt) < 0)
return -1;
if (l < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
while (l < last)
{
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
/* Now continue to collect until the size of the cache stops
decreasing. */
while (l < last) {
if (gc_all_items(self, now, dt) < 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);
self->position=0;
return 0;
if (now - self->last_check > 1)
update_stats(self, now);
self->position = 0;
return 0;
}
static int
maybegc(ccobject *self, PyObject *thisv)
{
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0;
s=PyDict_Size(self->data);
if (s < 1) return s;
now = PER_TIME();
size=self->cache_size;
self->cache_size=0;
/* Decide how many objects to look at */
n=(s-size)/10;
if (n < 3) n=3;
/* Decide how much time to give them before deactivating them */
s=8*size/s;
if (s > 100) s=100;
dt=(long)(self->cache_age*(0.2+0.1*s));
/* Units are 3 seconds */
dt /= 3;
if (dt < 1) dt=1;
while (--n >= 0)
{
if (PyDict_Next(self->data, &(self->position), &key, &v))
{
if (v != thisv && gc_item(self,key,v,now,dt) < 0)
{
self->cache_size=size;
return -1;
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
s = check_size(self);
if (s <= 0)
return 0;
now = PER_TIME();
size = self->cache_size;
self->cache_size = 0;
/* Decide how many objects to look at */
n = (s - size) / 10;
if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */
s = 8 * size / s;
if (s > 100)
s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */
dt /= 3;
while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
if (v != thisv && gc_item(self, key, v, now, dt) < 0) {
self->cache_size=size;
return -1;
}
}
else
self->position=0;
else
self->position = 0;
}
self->cache_size=size;
if (now-self->last_check > 1) update_stats(self, now);
self->cache_size = size;
if (now - self->last_check > 1)
update_stats(self, now);
return 0;
return 0;
}
static PyObject *
cc_full_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:full_sweep", &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);
return Py_None;
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:minimize", &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);
return Py_None;
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_incrgc(ccobject *self, PyObject *args)
{
int n=1;
int n = 1;
UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
if (!PyArg_ParseTuple(args, "|i:incrgr", &n))
return NULL;
for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL;
if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -317,114 +322,108 @@ cc_incrgc(ccobject *self, PyObject *args)
static void
_invalidate(ccobject *self, PyObject *key)
{
PyObject *v;
PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key)))
{
if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1)
{
if (!v)
return;
if (PyExtensionClass_Check(v))
if (v->ob_refcnt <= 1) {
self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear();
}
else
{
PyErr_Clear();
} else {
PyObject *t = PyTuple_New(1);
if (t)
{
if (t) {
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t);
/* Set tuple element to NULL so that deallocating the
tuple does not decref t.
*/
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
} else
v = t;
}
if (v) Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else
{
if (PyErr_Occurred())
if (v)
Py_DECREF(v);
else
PyErr_Clear();
}
else if (PyObject_DelAttr(v, py__p_changed) < 0)
PyErr_Clear();
}
}
static void
_invalidate_all(ccobject *self)
{
PyObject *key, *v;
int i;
for (i = 0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
}
static PyObject *
cc_invalidate(ccobject *self, PyObject *args)
{
PyObject *inv, *key, *v;
int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) {
for (i=0; PyDict_Next(inv, &i, &key, &v); )
if (key==Py_None)
{ /* Eek some nitwit invalidated everything! */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
}
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv==Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
PyObject *inv, *key, *v;
int i;
if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
return NULL;
if (PyDict_Check(inv)) {
for (i = 0; PyDict_Next(inv, &i, &key, &v); )
if (key == Py_None) {
/* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
} else if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv == Py_None) /* All */
_invalidate_all(self);
else {
int l;
PyErr_Clear();
if ((l=PyObject_Length(inv)) < 0) return NULL;
for(i=l; --i >= 0; )
{
UNLESS (key=PySequence_GetItem(inv, i)) return NULL;
_invalidate(self, key);
Py_DECREF(key);
int l = PyObject_Length(inv);
if (l < 0)
return NULL;
for (i = l; --i >= 0; ) {
key = PySequence_GetItem(inv, i);
if (!key)
return NULL;
_invalidate(self, key);
Py_DECREF(key);
}
PySequence_DelSlice(inv, 0, l);
PySequence_DelSlice(inv, 0, l);
}
}
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_get(ccobject *self, PyObject *args)
{
PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
PyObject *r, *key, *d = NULL;
UNLESS (r=PyDict_GetItem(self->data, key))
{
if (d)
{
if (PyErr_Occurred())
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
if (d)
r = d;
else {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
}
Py_INCREF(r);
return r;
Py_INCREF(r);
return r;
}
......@@ -454,107 +453,115 @@ static struct PyMethodDef cc_methods[] = {
static ccobject *
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
self->setklassstate=self->jar=NULL;
if((self->data=PyDict_New()))
{
self->jar=jar;
Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate"))
self = PyObject_NEW(ccobject, &Cctype);
if (!self)
return NULL;
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
self->sum_deal=0;
self->sum_deac=0;
self->sum_age=0;
self->mean_deal=0;
self->mean_deac=0;
self->mean_age=0;
self->df=1;
self->dfa=1;
self->n=0;
self->na=0;
self->last_check=time(NULL);
return self;
self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar;
Py_INCREF(jar);
self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
if (!self->setklassstate) {
Py_DECREF(jar);
Py_DECREF(self->data);
goto error;
}
self->position = 0;
self->cache_size = cache_size;
self->cache_age = cache_age < 1 ? 1 : cache_age;
self->sum_deal = 0;
self->sum_deac = 0;
self->sum_age = 0;
self->mean_deal = 0;
self->mean_deac = 0;
self->mean_age = 0;
self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self;
}
Py_DECREF(self);
return NULL;
error:
Py_DECREF(self);
return NULL;
}
static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
}
static PyObject *
cc_getattr(ccobject *self, char *name)
{
PyObject *r;
if(*name=='c')
{
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0)
return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0)
{
Py_INCREF(self->data);
return self->data;
PyObject *r;
if (*name == 'c') {
if(strcmp(name, "cache_age") == 0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df);
if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name, "cache_data") == 0) {
Py_INCREF(self->data);
return self->data;
}
}
if((*name=='h' && strcmp(name, "has_key")==0) ||
(*name=='i' && strcmp(name, "items")==0) ||
(*name=='k' && strcmp(name, "keys")==0)
)
return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name)))
if ((strcmp(name, "has_key") == 0)
|| (strcmp(name, "items") == 0)
|| (strcmp(name, "keys") == 0))
return PyObject_GetAttrString(self->data, name);
r = Py_FindMethod(cc_methods, (PyObject *)self, name);
if (!r) {
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
return r;
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
static int
cc_setattr(ccobject *self, char *name, PyObject *value)
{
if(value)
{
if (value) {
int v;
if(strcmp(name,"cache_age")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
if(v > 0)self->cache_age=v;
if (strcmp(name, "cache_age") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
if (v > 0)
self->cache_age = v;
return 0;
}
}
if(strcmp(name,"cache_size")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
self->cache_size=v;
if (strcmp(name, "cache_size") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
self->cache_size = v;
return 0;
}
}
}
}
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
......@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int
cc_length(ccobject *self)
{
return PyObject_Length(self->data);
return PyDict_Size(self->data);
}
static PyObject *
......@@ -570,10 +577,10 @@ cc_subscript(ccobject *self, PyObject *key)
{
PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key))
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
Py_INCREF(r);
......@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{
if(v)
{
if (v) {
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
......@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
};
static PyObject *
......@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000;
PyObject *jar;
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
if (!PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
return (PyObject *)newccobject(jar, cache_size, cache_age);
}
static struct PyMethodDef cCM_methods[] = {
......@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void
initcPickleCache(void)
{
PyObject *m, *d;
PyObject *m;
Cctype.ob_type=&PyType_Type;
Cctype.ob_type = &PyType_Type;
UNLESS(ExtensionClassImported) return;
if (!ExtensionClassImported)
return;
m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m);
py_reload=PyString_FromString("reload");
py__p_jar=PyString_FromString("_p_jar");
py__p_changed=PyString_FromString("_p_changed");
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module cPickleCache");
py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py__p_changed = PyString_InternFromString("_p_changed");
}
......@@ -13,12 +13,7 @@
static char cPickleCache_doc_string[] =
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
"$Id: cPickleCache.c,v 1.38 2002/01/25 14:51:55 gvanrossum Exp $\n";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(O) ((PyObject*)O)
"$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy Exp $\n";
/* Compute the current time in the units and range used for peristent
objects. */
......@@ -33,23 +28,23 @@ static char cPickleCache_doc_string[] =
static PyObject *py_reload, *py__p_jar, *py__p_changed;
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
PyObject_HEAD
PyObject *data;
PyObject *jar;
PyObject *setklassstate;
int position;
int cache_size;
int cache_age;
/* Cache statistics */
int sum_deal;
int sum_deac;
double sum_age;
int n, na;
time_t last_check; /* Time of last gc */
double mean_age;
double mean_deal;
double mean_deac;
double df, dfa; /* Degees of freedom for above stats */
} ccobject;
#define WEIGHTING_PERIOD 600
......@@ -74,102 +69,116 @@ staticforward PyTypeObject Cctype;
static int
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
{
if (v && key)
{
self->n++;
if(v->ob_refcnt <= 1)
{
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);
}
if (!(v && key))
return 0;
self->n++;
/* If there is at most one reference to this object, then the
cache has the only reference. It can be removed. */
if (v->ob_refcnt <= 1) {
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);
}
if (dt >= 0 &&
(! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE
)
{
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt)
{
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
if (dt >= 0 &&
(!PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar == self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state == cPersistent_UPTODATE_STATE) {
now -= ((cPersistentObject*)v)->atime;
if (now < 0)
now += 65536;
self->na++;
self->sum_age += now;
if (now > dt) {
/* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's
state.
*/
self->sum_deac++;
if (PyObject_SetAttr(v, py__p_changed, Py_None) < 0)
PyErr_Clear();
}
}
}
return 0;
return 0;
}
static void
update_stats(ccobject *self, time_t now)
{
double d, deal, deac;
d=now-self->last_check;
if(d < 1) return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/
(self->dfa+self->na))*3;
self->sum_age=0;
deac=self->sum_deac/d;
self->sum_deac=0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/
(self->dfa+self->na));
self->sum_deac=0;
self->dfa += self->na;
self->na=0;
double d, deal, deac;
d = now - self->last_check;
if(d < 1)
return;
self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa + self->na)) * 3;
self->sum_age = 0;
deac = self->sum_deac / d;
self->sum_deac = 0;
self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa + self->na));
self->sum_deac = 0;
self->dfa += self->na;
self->na = 0;
deal=self->sum_deal/d;
self->sum_deal = 0;
self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n));
self->sum_deal = 0;
self->df += self->n;
self->n = 0;
self->last_check = now;
}
deal=self->sum_deal/d;
self->sum_deal=0;
self->mean_deal=((self->mean_deal*self->df +deal)/
(self->df +self->n));
self->sum_deal=0;
static int
check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
self->df += self->n;
self->n=0;
static int
gc_all_items(ccobject *self, int now, int dt)
{
PyObject *key, *v;
int i;
self->last_check=now;
for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0;
}
static int
fullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i;
long now;
long now;
if (self->cache_size < 1)
return 0;
if ((i=PyDict_Size(self->data)) < 1)
return 0;
if (check_size(self) <= 0)
return 0;
now = PER_TIME();
if (dt > 0)
dt /= 3;
now = PER_TIME();
dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
if (gc_all_items(self, 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);
return 0;
}
......@@ -177,139 +186,135 @@ fullgc(ccobject *self, int dt)
static int
reallyfullgc(ccobject *self, int dt)
{
PyObject *key, *v;
int i, l, last;
time_t now;
if (self->cache_size < 1)
return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
int l, last;
time_t now;
now = PER_TIME();
if (dt > 0)
dt /= 3;
last = check_size(self);
if (last <= 0)
return 0;
/* First time through should get refcounts to 1 */
for(i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
now = PER_TIME();
/* Units are 3 seconds */
dt /= 3;
l = PyDict_Size(self->data);
/* First time through should get refcounts to 1 */
if (gc_all_items(self, now, dt) < 0)
return -1;
if (l < 0)
return -1;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
while (l < last)
{
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
last = l;
l = PyDict_Size(self->data);
if (l < 0)
return -1;
/* Now continue to collect until the size of the cache stops
decreasing. */
while (l < last) {
if (gc_all_items(self, now, dt) < 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);
self->position=0;
return 0;
if (now - self->last_check > 1)
update_stats(self, now);
self->position = 0;
return 0;
}
static int
maybegc(ccobject *self, PyObject *thisv)
{
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0;
s=PyDict_Size(self->data);
if (s < 1) return s;
now = PER_TIME();
size=self->cache_size;
self->cache_size=0;
/* Decide how many objects to look at */
n=(s-size)/10;
if (n < 3) n=3;
/* Decide how much time to give them before deactivating them */
s=8*size/s;
if (s > 100) s=100;
dt=(long)(self->cache_age*(0.2+0.1*s));
/* Units are 3 seconds */
dt /= 3;
if (dt < 1) dt=1;
while (--n >= 0)
{
if (PyDict_Next(self->data, &(self->position), &key, &v))
{
if (v != thisv && gc_item(self,key,v,now,dt) < 0)
{
self->cache_size=size;
return -1;
int n, s, size, dt;
long now;
PyObject *key=0, *v=0;
s = check_size(self);
if (s <= 0)
return 0;
now = PER_TIME();
size = self->cache_size;
self->cache_size = 0;
/* Decide how many objects to look at */
n = (s - size) / 10;
if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */
s = 8 * size / s;
if (s > 100)
s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */
dt /= 3;
while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
if (v != thisv && gc_item(self, key, v, now, dt) < 0) {
self->cache_size=size;
return -1;
}
}
else
self->position=0;
else
self->position = 0;
}
self->cache_size=size;
if (now-self->last_check > 1) update_stats(self, now);
self->cache_size = size;
if (now - self->last_check > 1)
update_stats(self, now);
return 0;
return 0;
}
static PyObject *
cc_full_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:full_sweep", &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);
return Py_None;
if (fullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args)
{
int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL;
if (dt < -1)
{
PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL;
int dt = self->cache_age;
if (!PyArg_ParseTuple(args, "|i:minimize", &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);
return Py_None;
if (reallyfullgc(self, dt) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_incrgc(ccobject *self, PyObject *args)
{
int n=1;
int n = 1;
UNLESS (PyArg_ParseTuple(args, "|i:incrgr",&n)) return NULL;
if (!PyArg_ParseTuple(args, "|i:incrgr", &n))
return NULL;
for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL;
if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -317,114 +322,108 @@ cc_incrgc(ccobject *self, PyObject *args)
static void
_invalidate(ccobject *self, PyObject *key)
{
PyObject *v;
PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key)))
{
if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1)
{
if (!v)
return;
if (PyExtensionClass_Check(v))
if (v->ob_refcnt <= 1) {
self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear();
}
else
{
PyErr_Clear();
} else {
PyObject *t = PyTuple_New(1);
if (t)
{
if (t) {
PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t);
/* Set tuple element to NULL so that deallocating the
tuple does not decref t.
*/
PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t);
}
else
{
} else
v = t;
}
if (v) Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else
{
if (PyErr_Occurred())
if (v)
Py_DECREF(v);
else
PyErr_Clear();
}
else if (PyObject_DelAttr(v, py__p_changed) < 0)
PyErr_Clear();
}
}
static void
_invalidate_all(ccobject *self)
{
PyObject *key, *v;
int i;
for (i = 0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
}
static PyObject *
cc_invalidate(ccobject *self, PyObject *args)
{
PyObject *inv, *key, *v;
int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) {
for (i=0; PyDict_Next(inv, &i, &key, &v); )
if (key==Py_None)
{ /* Eek some nitwit invalidated everything! */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
}
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv==Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); )
_invalidate(self, key);
PyObject *inv, *key, *v;
int i;
if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
return NULL;
if (PyDict_Check(inv)) {
for (i = 0; PyDict_Next(inv, &i, &key, &v); )
if (key == Py_None) {
/* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break;
}
else
_invalidate(self, key);
PyDict_Clear(inv);
} else if (PyString_Check(inv))
_invalidate(self, inv);
else if (inv == Py_None) /* All */
_invalidate_all(self);
else {
int l;
PyErr_Clear();
if ((l=PyObject_Length(inv)) < 0) return NULL;
for(i=l; --i >= 0; )
{
UNLESS (key=PySequence_GetItem(inv, i)) return NULL;
_invalidate(self, key);
Py_DECREF(key);
int l = PyObject_Length(inv);
if (l < 0)
return NULL;
for (i = l; --i >= 0; ) {
key = PySequence_GetItem(inv, i);
if (!key)
return NULL;
_invalidate(self, key);
Py_DECREF(key);
}
PySequence_DelSlice(inv, 0, l);
PySequence_DelSlice(inv, 0, l);
}
}
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cc_get(ccobject *self, PyObject *args)
{
PyObject *r, *key, *d=0;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL;
PyObject *r, *key, *d = NULL;
UNLESS (r=PyDict_GetItem(self->data, key))
{
if (d)
{
if (PyErr_Occurred())
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
if (d)
r = d;
else {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
}
Py_INCREF(r);
return r;
Py_INCREF(r);
return r;
}
......@@ -454,107 +453,115 @@ static struct PyMethodDef cc_methods[] = {
static ccobject *
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
self->setklassstate=self->jar=NULL;
if((self->data=PyDict_New()))
{
self->jar=jar;
Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate"))
self = PyObject_NEW(ccobject, &Cctype);
if (!self)
return NULL;
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
self->sum_deal=0;
self->sum_deac=0;
self->sum_age=0;
self->mean_deal=0;
self->mean_deac=0;
self->mean_age=0;
self->df=1;
self->dfa=1;
self->n=0;
self->na=0;
self->last_check=time(NULL);
return self;
self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar;
Py_INCREF(jar);
self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
if (!self->setklassstate) {
Py_DECREF(jar);
Py_DECREF(self->data);
goto error;
}
self->position = 0;
self->cache_size = cache_size;
self->cache_age = cache_age < 1 ? 1 : cache_age;
self->sum_deal = 0;
self->sum_deac = 0;
self->sum_age = 0;
self->mean_deal = 0;
self->mean_deac = 0;
self->mean_age = 0;
self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self;
}
Py_DECREF(self);
return NULL;
error:
Py_DECREF(self);
return NULL;
}
static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
Py_XDECREF(self->setklassstate);
PyMem_DEL(self);
}
static PyObject *
cc_getattr(ccobject *self, char *name)
{
PyObject *r;
if(*name=='c')
{
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0)
return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0)
{
Py_INCREF(self->data);
return self->data;
PyObject *r;
if (*name == 'c') {
if(strcmp(name, "cache_age") == 0)
return PyInt_FromLong(self->cache_age);
if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size);
if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age);
if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df);
if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa);
if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check);
if(strcmp(name, "cache_data") == 0) {
Py_INCREF(self->data);
return self->data;
}
}
if((*name=='h' && strcmp(name, "has_key")==0) ||
(*name=='i' && strcmp(name, "items")==0) ||
(*name=='k' && strcmp(name, "keys")==0)
)
return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name)))
if ((strcmp(name, "has_key") == 0)
|| (strcmp(name, "items") == 0)
|| (strcmp(name, "keys") == 0))
return PyObject_GetAttrString(self->data, name);
r = Py_FindMethod(cc_methods, (PyObject *)self, name);
if (!r) {
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
return r;
PyErr_Clear();
return PyObject_GetAttrString(self->data, name);
}
static int
cc_setattr(ccobject *self, char *name, PyObject *value)
{
if(value)
{
if (value) {
int v;
if(strcmp(name,"cache_age")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
if(v > 0)self->cache_age=v;
if (strcmp(name, "cache_age") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
if (v > 0)
self->cache_age = v;
return 0;
}
}
if(strcmp(name,"cache_size")==0)
{
UNLESS(PyArg_Parse(value,"i",&v)) return -1;
self->cache_size=v;
if (strcmp(name, "cache_size") == 0) {
v = PyInt_AsLong(value);
if (v == -1 && PyErr_Occurred())
return -1;
self->cache_size = v;
return 0;
}
}
}
}
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
......@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int
cc_length(ccobject *self)
{
return PyObject_Length(self->data);
return PyDict_Size(self->data);
}
static PyObject *
......@@ -570,10 +577,10 @@ cc_subscript(ccobject *self, PyObject *key)
{
PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key))
{
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
r = PyDict_GetItem(self->data, key);
if (!r) {
PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
Py_INCREF(r);
......@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{
if(v)
{
if (v) {
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
......@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
};
static PyObject *
......@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000;
PyObject *jar;
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
if (!PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
return (PyObject *)newccobject(jar, cache_size, cache_age);
}
static struct PyMethodDef cCM_methods[] = {
......@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void
initcPickleCache(void)
{
PyObject *m, *d;
PyObject *m;
Cctype.ob_type=&PyType_Type;
Cctype.ob_type = &PyType_Type;
UNLESS(ExtensionClassImported) return;
if (!ExtensionClassImported)
return;
m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m);
py_reload=PyString_FromString("reload");
py__p_jar=PyString_FromString("_p_jar");
py__p_changed=PyString_FromString("_p_changed");
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module cPickleCache");
py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py__p_changed = PyString_InternFromString("_p_changed");
}
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