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 @@ ...@@ -13,12 +13,7 @@
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.38 2002/01/25 14:51:55 gvanrossum Exp $\n"; "$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy 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)
/* Compute the current time in the units and range used for peristent /* Compute the current time in the units and range used for peristent
objects. */ objects. */
...@@ -74,11 +69,13 @@ staticforward PyTypeObject Cctype; ...@@ -74,11 +69,13 @@ 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))
{ return 0;
self->n++; self->n++;
if(v->ob_refcnt <= 1)
{ /* 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++; self->sum_deal++;
/* XXX The fact that this works will iterating over /* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the self->data with PyDict_Next() is an accident of the
...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
} }
if (dt >= 0 && 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) if (now < 0)
now += 65536; now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt) {
{
/* We have a cPersistent object that hasn't been used in /* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's a while. Reinitialize it, hopefully freeing it's
state. state.
...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
PyErr_Clear(); PyErr_Clear();
} }
} }
}
return 0; return 0;
} }
...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now) ...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now)
{ {
double d, deal, deac; double d, deal, deac;
d=now-self->last_check; d = now - self->last_check;
if(d < 1) return; if(d < 1)
return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/ self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa+self->na))*3; (self->dfa + self->na)) * 3;
self->sum_age=0; self->sum_age = 0;
deac=self->sum_deac/d; deac = self->sum_deac / d;
self->sum_deac=0; self->sum_deac = 0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/ self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa+self->na)); (self->dfa + self->na));
self->sum_deac=0; self->sum_deac = 0;
self->dfa += self->na; self->dfa += self->na;
self->na=0; self->na = 0;
deal=self->sum_deal/d; deal=self->sum_deal/d;
self->sum_deal=0; self->sum_deal = 0;
self->mean_deal=((self->mean_deal*self->df +deal)/ self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n)); (self->df +self->n));
self->sum_deal=0; self->sum_deal = 0;
self->df += self->n; self->df += self->n;
self->n=0; self->n = 0;
self->last_check=now; self->last_check = now;
} }
static int static int
fullgc(ccobject *self, int dt) check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
static int
gc_all_items(ccobject *self, int now, int dt)
{ {
PyObject *key, *v; PyObject *key, *v;
int i; int i;
long now;
if (self->cache_size < 1) for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1) }
static int
fullgc(ccobject *self, int dt)
{
long now;
if (check_size(self) <= 0)
return 0; return 0;
now = PER_TIME(); now = PER_TIME();
if (dt > 0)
dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; 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; return 0;
} }
...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt) ...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt)
static int static int
reallyfullgc(ccobject *self, int dt) reallyfullgc(ccobject *self, int dt)
{ {
PyObject *key, *v; int l, last;
int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) last = check_size(self);
if (last <= 0)
return 0; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now = PER_TIME(); now = PER_TIME();
if (dt > 0) /* Units are 3 seconds */
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); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; return -1;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
if (l < 0) if (l < 0)
return -1; return -1;
while (l < last) /* Now continue to collect until the size of the cache stops
{ decreasing. */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) while (l < last) {
if (gc_item(self, key, v, now, dt) < 0) if (gc_all_items(self, now, dt) < 0)
return -1; return -1;
last = l; last = l;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt) ...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt)
return -1; return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
self->position=0; self->position = 0;
return 0; return 0;
} }
...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv)
long now; long now;
PyObject *key=0, *v=0; PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0; s = check_size(self);
s=PyDict_Size(self->data); if (s <= 0)
if (s < 1) return s; return 0;
now = PER_TIME(); now = PER_TIME();
size=self->cache_size; size = self->cache_size;
self->cache_size=0; self->cache_size = 0;
/* Decide how many objects to look at */ /* Decide how many objects to look at */
n=(s-size)/10; n = (s - size) / 10;
if (n < 3) n=3; if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */ /* Decide how much time to give them before deactivating them */
s=8*size/s; s = 8 * size / s;
if (s > 100) s=100; if (s > 100)
dt=(long)(self->cache_age*(0.2+0.1*s)); s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */ /* Units are 3 seconds */
dt /= 3; dt /= 3;
if (dt < 1) dt=1; while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
while (--n >= 0) if (v != thisv && gc_item(self, key, v, now, dt) < 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; self->cache_size=size;
return -1; return -1;
} }
} }
else else
self->position=0; self->position = 0;
} }
self->cache_size=size; self->cache_size = size;
if (now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
return 0; return 0;
} }
...@@ -272,9 +275,9 @@ static PyObject * ...@@ -272,9 +275,9 @@ static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:full_sweep", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -288,9 +291,9 @@ static PyObject * ...@@ -288,9 +291,9 @@ static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:minimize", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args) ...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_incrgc(ccobject *self, PyObject *args) 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;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args)
static void static void
_invalidate(ccobject *self, PyObject *key) _invalidate(ccobject *self, PyObject *key)
{ {
PyObject *v; PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key))) if (!v)
{ return;
if (PyExtensionClass_Check(v)) if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1) if (v->ob_refcnt <= 1) {
{
self->sum_deal++; self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0) if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear(); PyErr_Clear();
} } else {
else
{
PyObject *t = PyTuple_New(1); PyObject *t = PyTuple_New(1);
if (t) if (t) {
{
PyTuple_SET_ITEM(t, 0, v); PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t); 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); PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t); Py_DECREF(t);
} } else
else
{
v = t; v = t;
} if (v)
if (v) Py_DECREF(v); Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else else
{
if (PyErr_Occurred())
PyErr_Clear(); 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 * static PyObject *
...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args)
PyObject *inv, *key, *v; PyObject *inv, *key, *v;
int i; int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) { if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
for (i=0; PyDict_Next(inv, &i, &key, &v); ) return NULL;
if (key==Py_None) if (PyDict_Check(inv)) {
{ /* Eek some nitwit invalidated everything! */ for (i = 0; PyDict_Next(inv, &i, &key, &v); )
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) if (key == Py_None) {
_invalidate(self, key); /* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break; break;
} }
else else
_invalidate(self, key); _invalidate(self, key);
PyDict_Clear(inv); PyDict_Clear(inv);
} } else if (PyString_Check(inv))
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv == Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) _invalidate_all(self);
_invalidate(self, key);
else { else {
int l; int l = PyObject_Length(inv);
PyErr_Clear(); if (l < 0)
if ((l=PyObject_Length(inv)) < 0) return NULL; return NULL;
for(i=l; --i >= 0; ) for (i = l; --i >= 0; ) {
{ key = PySequence_GetItem(inv, i);
UNLESS (key=PySequence_GetItem(inv, i)) return NULL; if (!key)
return NULL;
_invalidate(self, key); _invalidate(self, key);
Py_DECREF(key); Py_DECREF(key);
} }
PySequence_DelSlice(inv, 0, l); PySequence_DelSlice(inv, 0, l);
} }
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_get(ccobject *self, PyObject *args) cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d = NULL;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL; if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
if (d) if (d)
{ r = d;
if (PyErr_Occurred()) else {
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age) ...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; self = PyObject_NEW(ccobject, &Cctype);
self->setklassstate=self->jar=NULL; if (!self)
if((self->data=PyDict_New())) return NULL;
{ self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar; self->jar=jar;
Py_INCREF(jar); Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate")) self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
return NULL; if (!self->setklassstate) {
self->position=0; Py_DECREF(jar);
self->cache_size=cache_size; Py_DECREF(self->data);
self->cache_age=cache_age < 1 ? 1 : cache_age; goto error;
self->sum_deal=0; }
self->sum_deac=0; self->position = 0;
self->sum_age=0; self->cache_size = cache_size;
self->mean_deal=0; self->cache_age = cache_age < 1 ? 1 : cache_age;
self->mean_deac=0; self->sum_deal = 0;
self->mean_age=0; self->sum_deac = 0;
self->df=1; self->sum_age = 0;
self->dfa=1; self->mean_deal = 0;
self->n=0; self->mean_deac = 0;
self->na=0; self->mean_age = 0;
self->last_check=time(NULL); self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self; return self;
} }
error:
Py_DECREF(self); Py_DECREF(self);
return NULL; return NULL;
} }
...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name) ...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name)
{ {
PyObject *r; PyObject *r;
if(*name=='c') if (*name == 'c') {
{ if(strcmp(name, "cache_age") == 0)
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age); return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0) if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size); return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0) if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age); return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0) if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal); return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0) if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac); return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0) if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df); return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0) if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa); return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0) if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check); return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0) if(strcmp(name, "cache_data") == 0) {
{
Py_INCREF(self->data); Py_INCREF(self->data);
return self->data; return self->data;
} }
} }
if((*name=='h' && strcmp(name, "has_key")==0) || if ((strcmp(name, "has_key") == 0)
(*name=='i' && strcmp(name, "items")==0) || || (strcmp(name, "items") == 0)
(*name=='k' && strcmp(name, "keys")==0) || (strcmp(name, "keys") == 0))
)
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name))) r = Py_FindMethod(cc_methods, (PyObject *)self, name);
return r; if (!r) {
PyErr_Clear(); PyErr_Clear();
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
}
return r;
} }
static int static int
cc_setattr(ccobject *self, char *name, PyObject *value) cc_setattr(ccobject *self, char *name, PyObject *value)
{ {
if(value) if (value) {
{
int v; int v;
if(strcmp(name,"cache_age")==0) if (strcmp(name, "cache_age") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
if(v > 0)self->cache_age=v; return -1;
if (v > 0)
self->cache_age = v;
return 0; return 0;
} }
if(strcmp(name,"cache_size")==0) if (strcmp(name, "cache_size") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
self->cache_size=v; return -1;
self->cache_size = v;
return 0; return 0;
} }
} }
...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value) ...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int static int
cc_length(ccobject *self) cc_length(ccobject *self)
{ {
return PyObject_Length(self->data); return PyDict_Size(self->data);
} }
static PyObject * static PyObject *
...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key)
{ {
PyObject *r; PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) if (v) {
{
if (PyExtensionClass_Check(v) if (PyExtensionClass_Check(v)
|| ||
(PyExtensionInstance_Check(v) (PyExtensionInstance_Check(v)
...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = { ...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/ (hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/ (ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/ (reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
}; };
static PyObject * static PyObject *
...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args) ...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
PyObject *jar; 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 NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age); return (PyObject *)newccobject(jar, cache_size, cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = { ...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void void
initcPickleCache(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, m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION); (PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m); py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py_reload=PyString_FromString("reload"); py__p_changed = PyString_InternFromString("_p_changed");
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");
} }
...@@ -13,12 +13,7 @@ ...@@ -13,12 +13,7 @@
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.38 2002/01/25 14:51:55 gvanrossum Exp $\n"; "$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy 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)
/* Compute the current time in the units and range used for peristent /* Compute the current time in the units and range used for peristent
objects. */ objects. */
...@@ -74,11 +69,13 @@ staticforward PyTypeObject Cctype; ...@@ -74,11 +69,13 @@ 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))
{ return 0;
self->n++; self->n++;
if(v->ob_refcnt <= 1)
{ /* 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++; self->sum_deal++;
/* XXX The fact that this works will iterating over /* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the self->data with PyDict_Next() is an accident of the
...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
} }
if (dt >= 0 && 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) if (now < 0)
now += 65536; now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt) {
{
/* We have a cPersistent object that hasn't been used in /* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's a while. Reinitialize it, hopefully freeing it's
state. state.
...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
PyErr_Clear(); PyErr_Clear();
} }
} }
}
return 0; return 0;
} }
...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now) ...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now)
{ {
double d, deal, deac; double d, deal, deac;
d=now-self->last_check; d = now - self->last_check;
if(d < 1) return; if(d < 1)
return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/ self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa+self->na))*3; (self->dfa + self->na)) * 3;
self->sum_age=0; self->sum_age = 0;
deac=self->sum_deac/d; deac = self->sum_deac / d;
self->sum_deac=0; self->sum_deac = 0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/ self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa+self->na)); (self->dfa + self->na));
self->sum_deac=0; self->sum_deac = 0;
self->dfa += self->na; self->dfa += self->na;
self->na=0; self->na = 0;
deal=self->sum_deal/d; deal=self->sum_deal/d;
self->sum_deal=0; self->sum_deal = 0;
self->mean_deal=((self->mean_deal*self->df +deal)/ self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n)); (self->df +self->n));
self->sum_deal=0; self->sum_deal = 0;
self->df += self->n; self->df += self->n;
self->n=0; self->n = 0;
self->last_check=now; self->last_check = now;
} }
static int static int
fullgc(ccobject *self, int dt) check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
static int
gc_all_items(ccobject *self, int now, int dt)
{ {
PyObject *key, *v; PyObject *key, *v;
int i; int i;
long now;
if (self->cache_size < 1) for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1) }
static int
fullgc(ccobject *self, int dt)
{
long now;
if (check_size(self) <= 0)
return 0; return 0;
now = PER_TIME(); now = PER_TIME();
if (dt > 0)
dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; 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; return 0;
} }
...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt) ...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt)
static int static int
reallyfullgc(ccobject *self, int dt) reallyfullgc(ccobject *self, int dt)
{ {
PyObject *key, *v; int l, last;
int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) last = check_size(self);
if (last <= 0)
return 0; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now = PER_TIME(); now = PER_TIME();
if (dt > 0) /* Units are 3 seconds */
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); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; return -1;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
if (l < 0) if (l < 0)
return -1; return -1;
while (l < last) /* Now continue to collect until the size of the cache stops
{ decreasing. */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) while (l < last) {
if (gc_item(self, key, v, now, dt) < 0) if (gc_all_items(self, now, dt) < 0)
return -1; return -1;
last = l; last = l;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt) ...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt)
return -1; return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
self->position=0; self->position = 0;
return 0; return 0;
} }
...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv)
long now; long now;
PyObject *key=0, *v=0; PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0; s = check_size(self);
s=PyDict_Size(self->data); if (s <= 0)
if (s < 1) return s; return 0;
now = PER_TIME(); now = PER_TIME();
size=self->cache_size; size = self->cache_size;
self->cache_size=0; self->cache_size = 0;
/* Decide how many objects to look at */ /* Decide how many objects to look at */
n=(s-size)/10; n = (s - size) / 10;
if (n < 3) n=3; if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */ /* Decide how much time to give them before deactivating them */
s=8*size/s; s = 8 * size / s;
if (s > 100) s=100; if (s > 100)
dt=(long)(self->cache_age*(0.2+0.1*s)); s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */ /* Units are 3 seconds */
dt /= 3; dt /= 3;
if (dt < 1) dt=1; while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
while (--n >= 0) if (v != thisv && gc_item(self, key, v, now, dt) < 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; self->cache_size=size;
return -1; return -1;
} }
} }
else else
self->position=0; self->position = 0;
} }
self->cache_size=size; self->cache_size = size;
if (now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
return 0; return 0;
} }
...@@ -272,9 +275,9 @@ static PyObject * ...@@ -272,9 +275,9 @@ static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:full_sweep", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -288,9 +291,9 @@ static PyObject * ...@@ -288,9 +291,9 @@ static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:minimize", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args) ...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_incrgc(ccobject *self, PyObject *args) 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;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args)
static void static void
_invalidate(ccobject *self, PyObject *key) _invalidate(ccobject *self, PyObject *key)
{ {
PyObject *v; PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key))) if (!v)
{ return;
if (PyExtensionClass_Check(v)) if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1) if (v->ob_refcnt <= 1) {
{
self->sum_deal++; self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0) if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear(); PyErr_Clear();
} } else {
else
{
PyObject *t = PyTuple_New(1); PyObject *t = PyTuple_New(1);
if (t) if (t) {
{
PyTuple_SET_ITEM(t, 0, v); PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t); 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); PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t); Py_DECREF(t);
} } else
else
{
v = t; v = t;
} if (v)
if (v) Py_DECREF(v); Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else else
{
if (PyErr_Occurred())
PyErr_Clear(); 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 * static PyObject *
...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args)
PyObject *inv, *key, *v; PyObject *inv, *key, *v;
int i; int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) { if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
for (i=0; PyDict_Next(inv, &i, &key, &v); ) return NULL;
if (key==Py_None) if (PyDict_Check(inv)) {
{ /* Eek some nitwit invalidated everything! */ for (i = 0; PyDict_Next(inv, &i, &key, &v); )
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) if (key == Py_None) {
_invalidate(self, key); /* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break; break;
} }
else else
_invalidate(self, key); _invalidate(self, key);
PyDict_Clear(inv); PyDict_Clear(inv);
} } else if (PyString_Check(inv))
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv == Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) _invalidate_all(self);
_invalidate(self, key);
else { else {
int l; int l = PyObject_Length(inv);
PyErr_Clear(); if (l < 0)
if ((l=PyObject_Length(inv)) < 0) return NULL; return NULL;
for(i=l; --i >= 0; ) for (i = l; --i >= 0; ) {
{ key = PySequence_GetItem(inv, i);
UNLESS (key=PySequence_GetItem(inv, i)) return NULL; if (!key)
return NULL;
_invalidate(self, key); _invalidate(self, key);
Py_DECREF(key); Py_DECREF(key);
} }
PySequence_DelSlice(inv, 0, l); PySequence_DelSlice(inv, 0, l);
} }
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_get(ccobject *self, PyObject *args) cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d = NULL;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL; if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
if (d) if (d)
{ r = d;
if (PyErr_Occurred()) else {
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age) ...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; self = PyObject_NEW(ccobject, &Cctype);
self->setklassstate=self->jar=NULL; if (!self)
if((self->data=PyDict_New())) return NULL;
{ self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar; self->jar=jar;
Py_INCREF(jar); Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate")) self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
return NULL; if (!self->setklassstate) {
self->position=0; Py_DECREF(jar);
self->cache_size=cache_size; Py_DECREF(self->data);
self->cache_age=cache_age < 1 ? 1 : cache_age; goto error;
self->sum_deal=0; }
self->sum_deac=0; self->position = 0;
self->sum_age=0; self->cache_size = cache_size;
self->mean_deal=0; self->cache_age = cache_age < 1 ? 1 : cache_age;
self->mean_deac=0; self->sum_deal = 0;
self->mean_age=0; self->sum_deac = 0;
self->df=1; self->sum_age = 0;
self->dfa=1; self->mean_deal = 0;
self->n=0; self->mean_deac = 0;
self->na=0; self->mean_age = 0;
self->last_check=time(NULL); self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self; return self;
} }
error:
Py_DECREF(self); Py_DECREF(self);
return NULL; return NULL;
} }
...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name) ...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name)
{ {
PyObject *r; PyObject *r;
if(*name=='c') if (*name == 'c') {
{ if(strcmp(name, "cache_age") == 0)
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age); return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0) if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size); return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0) if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age); return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0) if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal); return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0) if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac); return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0) if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df); return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0) if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa); return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0) if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check); return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0) if(strcmp(name, "cache_data") == 0) {
{
Py_INCREF(self->data); Py_INCREF(self->data);
return self->data; return self->data;
} }
} }
if((*name=='h' && strcmp(name, "has_key")==0) || if ((strcmp(name, "has_key") == 0)
(*name=='i' && strcmp(name, "items")==0) || || (strcmp(name, "items") == 0)
(*name=='k' && strcmp(name, "keys")==0) || (strcmp(name, "keys") == 0))
)
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name))) r = Py_FindMethod(cc_methods, (PyObject *)self, name);
return r; if (!r) {
PyErr_Clear(); PyErr_Clear();
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
}
return r;
} }
static int static int
cc_setattr(ccobject *self, char *name, PyObject *value) cc_setattr(ccobject *self, char *name, PyObject *value)
{ {
if(value) if (value) {
{
int v; int v;
if(strcmp(name,"cache_age")==0) if (strcmp(name, "cache_age") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
if(v > 0)self->cache_age=v; return -1;
if (v > 0)
self->cache_age = v;
return 0; return 0;
} }
if(strcmp(name,"cache_size")==0) if (strcmp(name, "cache_size") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
self->cache_size=v; return -1;
self->cache_size = v;
return 0; return 0;
} }
} }
...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value) ...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int static int
cc_length(ccobject *self) cc_length(ccobject *self)
{ {
return PyObject_Length(self->data); return PyDict_Size(self->data);
} }
static PyObject * static PyObject *
...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key)
{ {
PyObject *r; PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) if (v) {
{
if (PyExtensionClass_Check(v) if (PyExtensionClass_Check(v)
|| ||
(PyExtensionInstance_Check(v) (PyExtensionInstance_Check(v)
...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = { ...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/ (hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/ (ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/ (reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
}; };
static PyObject * static PyObject *
...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args) ...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
PyObject *jar; 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 NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age); return (PyObject *)newccobject(jar, cache_size, cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = { ...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void void
initcPickleCache(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, m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION); (PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m); py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py_reload=PyString_FromString("reload"); py__p_changed = PyString_InternFromString("_p_changed");
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");
} }
...@@ -13,12 +13,7 @@ ...@@ -13,12 +13,7 @@
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.38 2002/01/25 14:51:55 gvanrossum Exp $\n"; "$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy 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)
/* Compute the current time in the units and range used for peristent /* Compute the current time in the units and range used for peristent
objects. */ objects. */
...@@ -74,11 +69,13 @@ staticforward PyTypeObject Cctype; ...@@ -74,11 +69,13 @@ 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))
{ return 0;
self->n++; self->n++;
if(v->ob_refcnt <= 1)
{ /* 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++; self->sum_deal++;
/* XXX The fact that this works will iterating over /* XXX The fact that this works will iterating over
self->data with PyDict_Next() is an accident of the self->data with PyDict_Next() is an accident of the
...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -87,18 +84,15 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
} }
if (dt >= 0 && 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) if (now < 0)
now += 65536; now += 65536;
self->na++; self->na++;
self->sum_age += now; self->sum_age += now;
if (now > dt) if (now > dt) {
{
/* We have a cPersistent object that hasn't been used in /* We have a cPersistent object that hasn't been used in
a while. Reinitialize it, hopefully freeing it's a while. Reinitialize it, hopefully freeing it's
state. state.
...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -108,7 +102,6 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
PyErr_Clear(); PyErr_Clear();
} }
} }
}
return 0; return 0;
} }
...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now) ...@@ -117,59 +110,75 @@ update_stats(ccobject *self, time_t now)
{ {
double d, deal, deac; double d, deal, deac;
d=now-self->last_check; d = now - self->last_check;
if(d < 1) return; if(d < 1)
return;
self->df *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->df *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->dfa *= WEIGHTING_PERIOD/(WEIGHTING_PERIOD+d); self->dfa *= WEIGHTING_PERIOD / (WEIGHTING_PERIOD + d);
self->mean_age=((self->mean_age*self->dfa+self->sum_age)/ self->mean_age = ((self->mean_age * self->dfa + self->sum_age)/
(self->dfa+self->na))*3; (self->dfa + self->na)) * 3;
self->sum_age=0; self->sum_age = 0;
deac=self->sum_deac/d; deac = self->sum_deac / d;
self->sum_deac=0; self->sum_deac = 0;
self->mean_deac=((self->mean_deac*self->dfa+deac)/ self->mean_deac = ((self->mean_deac * self->dfa+deac)/
(self->dfa+self->na)); (self->dfa + self->na));
self->sum_deac=0; self->sum_deac = 0;
self->dfa += self->na; self->dfa += self->na;
self->na=0; self->na = 0;
deal=self->sum_deal/d; deal=self->sum_deal/d;
self->sum_deal=0; self->sum_deal = 0;
self->mean_deal=((self->mean_deal*self->df +deal)/ self->mean_deal = ((self->mean_deal * self->df + deal)/
(self->df +self->n)); (self->df +self->n));
self->sum_deal=0; self->sum_deal = 0;
self->df += self->n; self->df += self->n;
self->n=0; self->n = 0;
self->last_check=now; self->last_check = now;
} }
static int static int
fullgc(ccobject *self, int dt) check_size(ccobject *self)
{
if (self->cache_size < 1)
return 0;
return PyDict_Size(self->data);
}
static int
gc_all_items(ccobject *self, int now, int dt)
{ {
PyObject *key, *v; PyObject *key, *v;
int i; int i;
long now;
if (self->cache_size < 1) for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
if (gc_item(self, key, v, now, dt) < 0)
return -1;
return 0; return 0;
if ((i=PyDict_Size(self->data)) < 1) }
static int
fullgc(ccobject *self, int dt)
{
long now;
if (check_size(self) <= 0)
return 0; return 0;
now = PER_TIME(); now = PER_TIME();
if (dt > 0)
dt /= 3; dt /= 3;
for(i=0; PyDict_Next(self->data, &i, &key, &v); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; 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; return 0;
} }
...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt) ...@@ -177,34 +186,29 @@ fullgc(ccobject *self, int dt)
static int static int
reallyfullgc(ccobject *self, int dt) reallyfullgc(ccobject *self, int dt)
{ {
PyObject *key, *v; int l, last;
int i, l, last;
time_t now; time_t now;
if (self->cache_size < 1) last = check_size(self);
if (last <= 0)
return 0; return 0;
last = PyDict_Size(self->data);
if (last < 0)
return -1;
now = PER_TIME(); now = PER_TIME();
if (dt > 0) /* Units are 3 seconds */
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); ) if (gc_all_items(self, now, dt) < 0)
if (gc_item(self, key, v, now, dt) < 0)
return -1; return -1;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
if (l < 0) if (l < 0)
return -1; return -1;
while (l < last) /* Now continue to collect until the size of the cache stops
{ decreasing. */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) while (l < last) {
if (gc_item(self, key, v, now, dt) < 0) if (gc_all_items(self, now, dt) < 0)
return -1; return -1;
last = l; last = l;
l = PyDict_Size(self->data); l = PyDict_Size(self->data);
...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt) ...@@ -212,9 +216,10 @@ reallyfullgc(ccobject *self, int dt)
return -1; return -1;
} }
if(now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
self->position=0; self->position = 0;
return 0; return 0;
} }
...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv) ...@@ -225,45 +230,43 @@ maybegc(ccobject *self, PyObject *thisv)
long now; long now;
PyObject *key=0, *v=0; PyObject *key=0, *v=0;
if (self->cache_size < 1) return 0; s = check_size(self);
s=PyDict_Size(self->data); if (s <= 0)
if (s < 1) return s; return 0;
now = PER_TIME(); now = PER_TIME();
size=self->cache_size; size = self->cache_size;
self->cache_size=0; self->cache_size = 0;
/* Decide how many objects to look at */ /* Decide how many objects to look at */
n=(s-size)/10; n = (s - size) / 10;
if (n < 3) n=3; if (n < 3)
n = 3;
/* Decide how much time to give them before deactivating them */ /* Decide how much time to give them before deactivating them */
s=8*size/s; s = 8 * size / s;
if (s > 100) s=100; if (s > 100)
dt=(long)(self->cache_age*(0.2+0.1*s)); s = 100;
dt = (long)(self->cache_age * (0.2 + 0.1 * s));
/* Units are 3 seconds */ /* Units are 3 seconds */
dt /= 3; dt /= 3;
if (dt < 1) dt=1; while (--n >= 0) {
if (PyDict_Next(self->data, &(self->position), &key, &v)) {
while (--n >= 0) if (v != thisv && gc_item(self, key, v, now, dt) < 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; self->cache_size=size;
return -1; return -1;
} }
} }
else else
self->position=0; self->position = 0;
} }
self->cache_size=size; self->cache_size = size;
if (now-self->last_check > 1) update_stats(self, now); if (now - self->last_check > 1)
update_stats(self, now);
return 0; return 0;
} }
...@@ -272,9 +275,9 @@ static PyObject * ...@@ -272,9 +275,9 @@ static PyObject *
cc_full_sweep(ccobject *self, PyObject *args) cc_full_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:full_sweep", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:full_sweep", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -288,9 +291,9 @@ static PyObject * ...@@ -288,9 +291,9 @@ static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args) cc_reallyfull_sweep(ccobject *self, PyObject *args)
{ {
int dt = self->cache_age; int dt = self->cache_age;
UNLESS(PyArg_ParseTuple(args, "|i:minimize", &dt)) return NULL; if (!PyArg_ParseTuple(args, "|i:minimize", &dt))
if (dt < -1) return NULL;
{ if (dt < -1) {
PyErr_SetString(PyExc_ValueError, "age must be >= -1"); PyErr_SetString(PyExc_ValueError, "age must be >= -1");
return NULL; return NULL;
} }
...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args) ...@@ -303,12 +306,14 @@ cc_reallyfull_sweep(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_incrgc(ccobject *self, PyObject *args) 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;) for (; --n >= 0;)
if(maybegc(self,NULL) < 0) return NULL; if (maybegc(self, NULL) < 0)
return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args) ...@@ -317,42 +322,44 @@ cc_incrgc(ccobject *self, PyObject *args)
static void static void
_invalidate(ccobject *self, PyObject *key) _invalidate(ccobject *self, PyObject *key)
{ {
PyObject *v; PyObject *v = PyDict_GetItem(self->data, key);
if ((v=PyDict_GetItem(self->data, key))) if (!v)
{ return;
if (PyExtensionClass_Check(v)) if (PyExtensionClass_Check(v))
if(v->ob_refcnt <= 1) if (v->ob_refcnt <= 1) {
{
self->sum_deal++; self->sum_deal++;
if (PyDict_DelItem(self->data, key) < 0) if (PyDict_DelItem(self->data, key) < 0)
PyErr_Clear(); PyErr_Clear();
} } else {
else
{
PyObject *t = PyTuple_New(1); PyObject *t = PyTuple_New(1);
if (t) if (t) {
{
PyTuple_SET_ITEM(t, 0, v); PyTuple_SET_ITEM(t, 0, v);
v = PyObject_CallObject(self->setklassstate, t); 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); PyTuple_SET_ITEM(t, 0, NULL);
Py_DECREF(t); Py_DECREF(t);
} } else
else
{
v = t; v = t;
} if (v)
if (v) Py_DECREF(v); Py_DECREF(v);
else PyErr_Clear();
}
else if (PyObject_DelAttr(v,py__p_changed) < 0)
PyErr_Clear();
}
else else
{
if (PyErr_Occurred())
PyErr_Clear(); 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 * static PyObject *
...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -361,40 +368,36 @@ cc_invalidate(ccobject *self, PyObject *args)
PyObject *inv, *key, *v; PyObject *inv, *key, *v;
int i; int i;
if (PyArg_ParseTuple(args, "O!", &PyDict_Type, &inv)) { if (!PyArg_ParseTuple(args, "O:invalidate", &inv))
for (i=0; PyDict_Next(inv, &i, &key, &v); ) return NULL;
if (key==Py_None) if (PyDict_Check(inv)) {
{ /* Eek some nitwit invalidated everything! */ for (i = 0; PyDict_Next(inv, &i, &key, &v); )
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) if (key == Py_None) {
_invalidate(self, key); /* Eek some nitwit invalidated everything! */
_invalidate_all(self);
break; break;
} }
else else
_invalidate(self, key); _invalidate(self, key);
PyDict_Clear(inv); PyDict_Clear(inv);
} } else if (PyString_Check(inv))
else {
PyErr_Clear();
UNLESS (PyArg_ParseTuple(args, "O:invalidate", &inv)) return NULL;
if (PyString_Check(inv))
_invalidate(self, inv); _invalidate(self, inv);
else if (inv==Py_None) /* All */ else if (inv == Py_None) /* All */
for (i=0; PyDict_Next(self->data, &i, &key, &v); ) _invalidate_all(self);
_invalidate(self, key);
else { else {
int l; int l = PyObject_Length(inv);
PyErr_Clear(); if (l < 0)
if ((l=PyObject_Length(inv)) < 0) return NULL; return NULL;
for(i=l; --i >= 0; ) for (i = l; --i >= 0; ) {
{ key = PySequence_GetItem(inv, i);
UNLESS (key=PySequence_GetItem(inv, i)) return NULL; if (!key)
return NULL;
_invalidate(self, key); _invalidate(self, key);
Py_DECREF(key); Py_DECREF(key);
} }
PySequence_DelSlice(inv, 0, l); PySequence_DelSlice(inv, 0, l);
} }
}
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args) ...@@ -404,20 +407,16 @@ cc_invalidate(ccobject *self, PyObject *args)
static PyObject * static PyObject *
cc_get(ccobject *self, PyObject *args) cc_get(ccobject *self, PyObject *args)
{ {
PyObject *r, *key, *d=0; PyObject *r, *key, *d = NULL;
UNLESS (PyArg_ParseTuple(args, "O|O:get", &key, &d)) return NULL; if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
if (d) if (d)
{ r = d;
if (PyErr_Occurred()) else {
PyErr_Clear();
r=d;
}
else
{
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age) ...@@ -456,30 +455,37 @@ newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; self = PyObject_NEW(ccobject, &Cctype);
self->setklassstate=self->jar=NULL; if (!self)
if((self->data=PyDict_New())) return NULL;
{ self->setklassstate = self->jar = NULL;
self->data = PyDict_New();
if (self->data) {
self->jar=jar; self->jar=jar;
Py_INCREF(jar); Py_INCREF(jar);
UNLESS (self->setklassstate=PyObject_GetAttrString(jar, "setklassstate")) self->setklassstate = PyObject_GetAttrString(jar, "setklassstate");
return NULL; if (!self->setklassstate) {
self->position=0; Py_DECREF(jar);
self->cache_size=cache_size; Py_DECREF(self->data);
self->cache_age=cache_age < 1 ? 1 : cache_age; goto error;
self->sum_deal=0; }
self->sum_deac=0; self->position = 0;
self->sum_age=0; self->cache_size = cache_size;
self->mean_deal=0; self->cache_age = cache_age < 1 ? 1 : cache_age;
self->mean_deac=0; self->sum_deal = 0;
self->mean_age=0; self->sum_deac = 0;
self->df=1; self->sum_age = 0;
self->dfa=1; self->mean_deal = 0;
self->n=0; self->mean_deac = 0;
self->na=0; self->mean_age = 0;
self->last_check=time(NULL); self->df = 1;
self->dfa = 1;
self->n = 0;
self->na = 0;
self->last_check = time(NULL);
return self; return self;
} }
error:
Py_DECREF(self); Py_DECREF(self);
return NULL; return NULL;
} }
...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name) ...@@ -498,60 +504,61 @@ cc_getattr(ccobject *self, char *name)
{ {
PyObject *r; PyObject *r;
if(*name=='c') if (*name == 'c') {
{ if(strcmp(name, "cache_age") == 0)
if(strcmp(name,"cache_age")==0)
return PyInt_FromLong(self->cache_age); return PyInt_FromLong(self->cache_age);
if(strcmp(name,"cache_size")==0) if(strcmp(name, "cache_size") == 0)
return PyInt_FromLong(self->cache_size); return PyInt_FromLong(self->cache_size);
if(strcmp(name,"cache_mean_age")==0) if(strcmp(name, "cache_mean_age") == 0)
return PyFloat_FromDouble(self->mean_age); return PyFloat_FromDouble(self->mean_age);
if(strcmp(name,"cache_mean_deal")==0) if(strcmp(name, "cache_mean_deal") == 0)
return PyFloat_FromDouble(self->mean_deal); return PyFloat_FromDouble(self->mean_deal);
if(strcmp(name,"cache_mean_deac")==0) if(strcmp(name, "cache_mean_deac") == 0)
return PyFloat_FromDouble(self->mean_deac); return PyFloat_FromDouble(self->mean_deac);
if(strcmp(name,"cache_df")==0) if(strcmp(name, "cache_df") == 0)
return PyFloat_FromDouble(self->df); return PyFloat_FromDouble(self->df);
if(strcmp(name,"cache_dfa")==0) if(strcmp(name, "cache_dfa") == 0)
return PyFloat_FromDouble(self->dfa); return PyFloat_FromDouble(self->dfa);
if(strcmp(name,"cache_last_gc_time")==0) if(strcmp(name, "cache_last_gc_time") == 0)
return PyFloat_FromDouble(self->last_check); return PyFloat_FromDouble(self->last_check);
if(strcmp(name,"cache_data")==0) if(strcmp(name, "cache_data") == 0) {
{
Py_INCREF(self->data); Py_INCREF(self->data);
return self->data; return self->data;
} }
} }
if((*name=='h' && strcmp(name, "has_key")==0) || if ((strcmp(name, "has_key") == 0)
(*name=='i' && strcmp(name, "items")==0) || || (strcmp(name, "items") == 0)
(*name=='k' && strcmp(name, "keys")==0) || (strcmp(name, "keys") == 0))
)
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
if((r=Py_FindMethod(cc_methods, (PyObject *)self, name))) r = Py_FindMethod(cc_methods, (PyObject *)self, name);
return r; if (!r) {
PyErr_Clear(); PyErr_Clear();
return PyObject_GetAttrString(self->data, name); return PyObject_GetAttrString(self->data, name);
}
return r;
} }
static int static int
cc_setattr(ccobject *self, char *name, PyObject *value) cc_setattr(ccobject *self, char *name, PyObject *value)
{ {
if(value) if (value) {
{
int v; int v;
if(strcmp(name,"cache_age")==0) if (strcmp(name, "cache_age") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
if(v > 0)self->cache_age=v; return -1;
if (v > 0)
self->cache_age = v;
return 0; return 0;
} }
if(strcmp(name,"cache_size")==0) if (strcmp(name, "cache_size") == 0) {
{ v = PyInt_AsLong(value);
UNLESS(PyArg_Parse(value,"i",&v)) return -1; if (v == -1 && PyErr_Occurred())
self->cache_size=v; return -1;
self->cache_size = v;
return 0; return 0;
} }
} }
...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value) ...@@ -562,7 +569,7 @@ cc_setattr(ccobject *self, char *name, PyObject *value)
static int static int
cc_length(ccobject *self) cc_length(ccobject *self)
{ {
return PyObject_Length(self->data); return PyDict_Size(self->data);
} }
static PyObject * static PyObject *
...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -570,8 +577,8 @@ cc_subscript(ccobject *self, PyObject *key)
{ {
PyObject *r; PyObject *r;
UNLESS (r=PyDict_GetItem(self->data, key)) r = PyDict_GetItem(self->data, key);
{ if (!r) {
PyErr_SetObject(PyExc_KeyError, key); PyErr_SetObject(PyExc_KeyError, key);
return NULL; return NULL;
} }
...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -583,8 +590,7 @@ cc_subscript(ccobject *self, PyObject *key)
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) if (v) {
{
if (PyExtensionClass_Check(v) if (PyExtensionClass_Check(v)
|| ||
(PyExtensionInstance_Check(v) (PyExtensionInstance_Check(v)
...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = { ...@@ -629,10 +635,6 @@ static PyTypeObject Cctype = {
(hashfunc)0, /*tp_hash*/ (hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/ (ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/ (reprfunc)0, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
""
}; };
static PyObject * static PyObject *
...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args) ...@@ -641,9 +643,9 @@ cCM_new(PyObject *self, PyObject *args)
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
PyObject *jar; 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 NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age); return (PyObject *)newccobject(jar, cache_size, cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = { ...@@ -654,22 +656,17 @@ static struct PyMethodDef cCM_methods[] = {
void void
initcPickleCache(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, m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
(PyObject*)NULL, PYTHON_API_VERSION); (PyObject*)NULL, PYTHON_API_VERSION);
d = PyModule_GetDict(m); py_reload = PyString_InternFromString("reload");
py__p_jar = PyString_InternFromString("_p_jar");
py_reload=PyString_FromString("reload"); py__p_changed = PyString_InternFromString("_p_changed");
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");
} }
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