cPickleCache.c 15.5 KB
Newer Older
1
/*****************************************************************************
matt@zope.com's avatar
matt@zope.com committed
2 3

  Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
4
  
matt@zope.com's avatar
matt@zope.com committed
5 6 7 8 9 10
  This software is subject to the provisions of the Zope Public License,
  Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  FOR A PARTICULAR PURPOSE
11 12
  
 ****************************************************************************/
Jeremy Hylton's avatar
Jeremy Hylton committed
13 14 15
static char cPickleCache_doc_string[] = 
"Defines the PickleCache used by ZODB Connection objects.\n"
"\n"
16
"$Id: cPickleCache.c,v 1.39 2002/02/11 19:43:55 jeremy Exp $\n";
Jim Fulton's avatar
Jim Fulton committed
17

18 19 20 21
/* Compute the current time in the units and range used for peristent
   objects. */
#define PER_TIME() ((long)(time(NULL) / 3)) % 65536

22
#define DONT_USE_CPERSISTENCECAPI
23
#include "cPersistence.h"
Jim Fulton's avatar
Jim Fulton committed
24
#include <time.h>
Jim Fulton's avatar
Jim Fulton committed
25

26 27
#undef Py_FindMethod

28
static PyObject *py_reload, *py__p_jar, *py__p_changed;
29

Jim Fulton's avatar
Jim Fulton committed
30
typedef struct {
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    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 */
Jim Fulton's avatar
Jim Fulton committed
48 49
} ccobject;

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#define WEIGHTING_PERIOD 600

/*
  How to compute weighted means?

  Assume we have two means, a current mean, M, and a mean as of some
  time d seconds in the past, Md.  The means have effective degrees
  of freedom, N, and Nd. Where Nd is adjusted by d is some fashion.
  The combined mean is (M*N+Md*Nd)/(N+Nd).  The degrees of freedom
  of the combined mean, Nc, is N+Nd.  Nd is computed by weighting
  an old degree of freedom with the weight: I/(I+d), where I is some
  suitably chosen constant, which we will call a "weighting period".
  
 */

Jim Fulton's avatar
Jim Fulton committed
65 66 67 68
staticforward PyTypeObject Cctype;

/* ---------------------------------------------------------------- */

69
static int 
Jim Fulton's avatar
Jim Fulton committed
70
gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
71
{
72 73 74 75 76 77 78 79 80 81 82 83 84
    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);
    }
Jim Fulton's avatar
Jim Fulton committed
85

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    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)
102
		PyErr_Clear();
103
	}
104
    }
105
    return 0;
106
}
Jim Fulton's avatar
Jim Fulton committed
107

108 109 110
static void
update_stats(ccobject *self, time_t now)
{
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    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;
}
144

145 146 147 148 149 150 151
static int
check_size(ccobject *self)
{
    if (self->cache_size < 1) 
	return 0;
    return PyDict_Size(self->data);
}
152

153 154 155 156 157
static int
gc_all_items(ccobject *self, int now, int dt)
{
    PyObject *key, *v;
    int i;
158

159 160 161 162
    for(i = 0; PyDict_Next(self->data, &i, &key, &v); )
	if (gc_item(self, key, v, now, dt) < 0) 
	    return -1;
    return 0;
163 164
}

Jim Fulton's avatar
Jim Fulton committed
165
static int
166
fullgc(ccobject *self, int dt)
Jim Fulton's avatar
Jim Fulton committed
167
{
168
    long now;
Jim Fulton's avatar
Jim Fulton committed
169

170 171
    if (check_size(self) <= 0)
	return 0;
Jim Fulton's avatar
Jim Fulton committed
172

173 174
    now = PER_TIME();
    dt /= 3; 
Jim Fulton's avatar
Jim Fulton committed
175

176
    if (gc_all_items(self, now, dt) < 0)
177
	return -1;
178
    self->position = 0;
179

180 181
    if (now - self->last_check > 1) 
	update_stats(self, now);
182
  
Jim Fulton's avatar
Jim Fulton committed
183 184 185
  return 0;
}

Jim Fulton's avatar
Jim Fulton committed
186
static int
187
reallyfullgc(ccobject *self, int dt)
Jim Fulton's avatar
Jim Fulton committed
188
{
189 190
    int l, last;
    time_t now;
Jim Fulton's avatar
Jim Fulton committed
191

192 193 194
    last = check_size(self);
    if (last <= 0)
	return 0;
195

196 197 198
    now = PER_TIME();
    /* Units are 3 seconds */
    dt /= 3; 
199

200 201 202
    /* First time through should get refcounts to 1 */
    if (gc_all_items(self, now, dt) < 0)
	return -1;
Jim Fulton's avatar
Jim Fulton committed
203

204 205 206
    l = PyDict_Size(self->data);
    if (l < 0)
	return -1;
207

208 209 210 211 212 213 214 215 216
    /* 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;
217
    }
218 219 220 221 222 223
    
    if (now - self->last_check > 1) 
	update_stats(self, now);
    
    self->position = 0;
    return 0;
Jim Fulton's avatar
Jim Fulton committed
224 225
}

Jim Fulton's avatar
Jim Fulton committed
226
static int
227
maybegc(ccobject *self, PyObject *thisv)
Jim Fulton's avatar
Jim Fulton committed
228
{
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
    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;
261
	    }
Jim Fulton's avatar
Jim Fulton committed
262
	}
263 264
	else
	    self->position = 0;
Jim Fulton's avatar
Jim Fulton committed
265
    }
266 267 268 269
    self->cache_size = size;
    
    if (now - self->last_check > 1) 
	update_stats(self, now);
270

271
    return 0;
Jim Fulton's avatar
Jim Fulton committed
272 273 274
}

static PyObject *
275
cc_full_sweep(ccobject *self, PyObject *args)
Jim Fulton's avatar
Jim Fulton committed
276
{
277 278 279 280 281 282
    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;
283
    }
284 285 286 287
    if (fullgc(self, dt) == -1)
	return NULL;
    Py_INCREF(Py_None);
    return Py_None;
Jim Fulton's avatar
Jim Fulton committed
288 289
}

Jim Fulton's avatar
Jim Fulton committed
290 291 292
static PyObject *
cc_reallyfull_sweep(ccobject *self, PyObject *args)
{
293 294 295 296 297 298
    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;
299
    }
300 301 302 303
    if (reallyfullgc(self, dt) == -1)
	return NULL;
    Py_INCREF(Py_None);
    return Py_None;
Jim Fulton's avatar
Jim Fulton committed
304 305
}

306 307 308
static PyObject *
cc_incrgc(ccobject *self, PyObject *args)
{
309
  int n = 1;
310

311 312
  if (!PyArg_ParseTuple(args, "|i:incrgr", &n)) 
      return NULL;
313 314

  for (; --n >= 0;)
315 316 317
      if (maybegc(self, NULL) < 0) 
	  return NULL;
  
318 319 320 321
  Py_INCREF(Py_None);
  return Py_None;
}

322 323 324
static void 
_invalidate(ccobject *self, PyObject *key)
{
325
    PyObject *v = PyDict_GetItem(self->data, key);
326

327 328 329 330
    if (!v)
	return;
    if (PyExtensionClass_Check(v))
	if (v->ob_refcnt <= 1) {
331 332
	    self->sum_deal++;
	    if (PyDict_DelItem(self->data, key) < 0) 
333 334
		PyErr_Clear();
	} else {
335
	    PyObject *t = PyTuple_New(1);
336
	    if (t) {
337
		PyTuple_SET_ITEM(t, 0, v);
338
		v = PyObject_CallObject(self->setklassstate, t);
339 340 341
		/* Set tuple element to NULL so that deallocating the
		   tuple does not decref t.
		 */
342 343
		PyTuple_SET_ITEM(t, 0, NULL);
		Py_DECREF(t);
344
	    } else 
345
		v = t;
346 347 348 349 350 351
	    if (v) 
		Py_DECREF(v);
	    else
		PyErr_Clear();
	}
    else if (PyObject_DelAttr(v, py__p_changed) < 0)
352
	PyErr_Clear();
353 354 355 356 357 358 359 360 361 362
}

static void
_invalidate_all(ccobject *self)
{
    PyObject *key, *v;
    int i;

    for (i = 0; PyDict_Next(self->data, &i, &key, &v); )
	_invalidate(self, key);
363 364 365 366 367
}

static PyObject *
cc_invalidate(ccobject *self, PyObject *args)
{
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
    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);
387
    else {
388 389 390 391 392 393 394 395 396 397
	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);
398
	}
399
	PySequence_DelSlice(inv, 0, l);
400
    }
401 402 403
    
    Py_INCREF(Py_None);
    return Py_None;
404 405
}
  
Jim Fulton's avatar
Jim Fulton committed
406 407 408 409
  
static PyObject *
cc_get(ccobject *self, PyObject *args)
{
410
    PyObject *r, *key, *d = NULL;
Jim Fulton's avatar
Jim Fulton committed
411

412 413 414 415 416 417 418 419 420 421
    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;
Jim Fulton's avatar
Jim Fulton committed
422 423 424
	}
    }

425 426
    Py_INCREF(r);
    return r;
Jim Fulton's avatar
Jim Fulton committed
427 428
}

429

Jim Fulton's avatar
Jim Fulton committed
430
static struct PyMethodDef cc_methods[] = {
Jim Fulton's avatar
Jim Fulton committed
431
  {"full_sweep", (PyCFunction)cc_full_sweep, METH_VARARGS,
432 433 434 435 436
   "full_sweep([age]) -- Perform a full sweep of the cache\n\n"
   "Make a single pass through the cache, removing any objects that are no\n"
   "longer referenced, and deactivating objects that have not been\n"
   "accessed in the number of seconds given by 'age'.  "
   "'age defaults to the cache age.\n"
437
   },
Jim Fulton's avatar
Jim Fulton committed
438
  {"minimize",	(PyCFunction)cc_reallyfull_sweep, METH_VARARGS,
439 440 441 442 443
   "minimize([age]) -- Remove as many objects as possible\n\n"
   "Make multiple passes through the cache, removing any objects that are no\n"
   "longer referenced, and deactivating objects that have not been\n"
   "accessed in the number of seconds given by 'age'.  'age defaults to 0.\n"
   },
Jim Fulton's avatar
Jim Fulton committed
444
  {"incrgc", (PyCFunction)cc_incrgc, METH_VARARGS,
445
   "incrgc() -- Perform incremental garbage collection"},
446 447
  {"invalidate", (PyCFunction)cc_invalidate, METH_VARARGS,
   "invalidate(oids) -- invalidate one, many, or all ids"},
Jim Fulton's avatar
Jim Fulton committed
448 449
  {"get", (PyCFunction)cc_get, METH_VARARGS,
   "get(key [, default]) -- get an item, or a default"},
Jim Fulton's avatar
Jim Fulton committed
450 451 452 453
  {NULL,		NULL}		/* sentinel */
};

static ccobject *
Jim Fulton's avatar
Jim Fulton committed
454
newccobject(PyObject *jar, int cache_size, int cache_age)
Jim Fulton's avatar
Jim Fulton committed
455
{
456
    ccobject *self;
Jim Fulton's avatar
Jim Fulton committed
457
  
458 459
    self = PyObject_NEW(ccobject, &Cctype);
    if (!self)
460
	return NULL;
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
    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;
Jim Fulton's avatar
Jim Fulton committed
487
    }
488 489 490
 error:
    Py_DECREF(self);
    return NULL;
Jim Fulton's avatar
Jim Fulton committed
491 492 493
}

static void
494
cc_dealloc(ccobject *self)
Jim Fulton's avatar
Jim Fulton committed
495
{
496 497 498 499
    Py_XDECREF(self->data);
    Py_XDECREF(self->jar);
    Py_XDECREF(self->setklassstate);
    PyMem_DEL(self);
Jim Fulton's avatar
Jim Fulton committed
500 501 502
}

static PyObject *
503
cc_getattr(ccobject *self, char *name)
Jim Fulton's avatar
Jim Fulton committed
504
{
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    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;
527
	}
528
    }
529 530 531 532 533 534 535 536 537 538
    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);
    }
Jim Fulton's avatar
Jim Fulton committed
539 540 541
    return r;
}

Jim Fulton's avatar
Jim Fulton committed
542 543 544
static int
cc_setattr(ccobject *self, char *name, PyObject *value)
{
545
  if (value) {
Jim Fulton's avatar
Jim Fulton committed
546 547
      int v;

548 549 550 551 552 553
      if (strcmp(name, "cache_age") == 0) {
	  v = PyInt_AsLong(value);
	  if (v == -1 && PyErr_Occurred())
	      return -1;
	  if (v > 0)
	      self->cache_age = v;
554
	  return 0;
555
      }
Jim Fulton's avatar
Jim Fulton committed
556

557 558 559 560 561
      if (strcmp(name, "cache_size") == 0) {
	  v = PyInt_AsLong(value);
	  if (v == -1 && PyErr_Occurred())
	      return -1;
	  self->cache_size = v;
562
	  return 0;
563 564
      }
  }
Jim Fulton's avatar
Jim Fulton committed
565 566 567 568
  PyErr_SetString(PyExc_AttributeError, name);
  return -1;
}

Jim Fulton's avatar
Jim Fulton committed
569
static int
570
cc_length(ccobject *self)
Jim Fulton's avatar
Jim Fulton committed
571
{
572
    return PyDict_Size(self->data);
Jim Fulton's avatar
Jim Fulton committed
573 574 575
}
  
static PyObject *
576
cc_subscript(ccobject *self, PyObject *key)
Jim Fulton's avatar
Jim Fulton committed
577 578 579
{
  PyObject *r;

580 581 582 583
  r = PyDict_GetItem(self->data, key);
  if (!r) {
      PyErr_SetObject(PyExc_KeyError, key);
      return NULL;
Jim Fulton's avatar
Jim Fulton committed
584
  }
Jim Fulton's avatar
Jim Fulton committed
585 586

  Py_INCREF(r);
Jim Fulton's avatar
Jim Fulton committed
587 588 589 590
  return r;
}

static int
591
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
Jim Fulton's avatar
Jim Fulton committed
592
{
593
  if (v) {
594 595 596 597 598 599 600 601
      if (PyExtensionClass_Check(v) 
	  ||
	  (PyExtensionInstance_Check(v) 
	   &&
	   (((PyExtensionClass*)(v->ob_type))->class_flags 
	    & PERSISTENT_TYPE_FLAG)
	   &&
	   (v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
Jim Fulton's avatar
Jim Fulton committed
602 603 604 605 606 607 608 609
	   )
	  )	  
	return PyDict_SetItem(self->data, key, v);

      PyErr_SetString(PyExc_ValueError,
		      "Cache values must be persistent objects or classes.");
      return -1;
    }
Jim Fulton's avatar
Jim Fulton committed
610
  return PyDict_DelItem(self->data, key);
Jim Fulton's avatar
Jim Fulton committed
611 612 613 614 615 616 617 618 619
}

static PyMappingMethods cc_as_mapping = {
  (inquiry)cc_length,		/*mp_length*/
  (binaryfunc)cc_subscript,	/*mp_subscript*/
  (objobjargproc)cc_ass_sub,	/*mp_ass_subscript*/
};

static PyTypeObject Cctype = {
620
  PyObject_HEAD_INIT(NULL)
Jim Fulton's avatar
Jim Fulton committed
621 622 623 624 625 626 627 628
  0,				/*ob_size*/
  "cPickleCache",		/*tp_name*/
  sizeof(ccobject),		/*tp_basicsize*/
  0,				/*tp_itemsize*/
  /* methods */
  (destructor)cc_dealloc,	/*tp_dealloc*/
  (printfunc)0,			/*tp_print*/
  (getattrfunc)cc_getattr,	/*tp_getattr*/
Jim Fulton's avatar
Jim Fulton committed
629
  (setattrfunc)cc_setattr,	/*tp_setattr*/
Jim Fulton's avatar
Jim Fulton committed
630
  (cmpfunc)0,			/*tp_compare*/
Jim Fulton's avatar
Jim Fulton committed
631
  (reprfunc)0,   		/*tp_repr*/
Jim Fulton's avatar
Jim Fulton committed
632 633 634 635 636
  0,				/*tp_as_number*/
  0,				/*tp_as_sequence*/
  &cc_as_mapping,		/*tp_as_mapping*/
  (hashfunc)0,			/*tp_hash*/
  (ternaryfunc)0,		/*tp_call*/
Jim Fulton's avatar
Jim Fulton committed
637
  (reprfunc)0,  		/*tp_str*/
Jim Fulton's avatar
Jim Fulton committed
638 639 640
};

static PyObject *
641
cCM_new(PyObject *self, PyObject *args)
Jim Fulton's avatar
Jim Fulton committed
642
{
643
  int cache_size=100, cache_age=1000;
Jim Fulton's avatar
Jim Fulton committed
644 645
  PyObject *jar;

646
  if (!PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age))
Jeremy Hylton's avatar
Jeremy Hylton committed
647
      return NULL;
648
  return (PyObject *)newccobject(jar, cache_size, cache_age);
Jim Fulton's avatar
Jim Fulton committed
649 650 651
}

static struct PyMethodDef cCM_methods[] = {
Jim Fulton's avatar
Jim Fulton committed
652
  {"PickleCache",(PyCFunction)cCM_new,	METH_VARARGS, ""},
Jim Fulton's avatar
Jim Fulton committed
653 654 655 656
  {NULL,		NULL}		/* sentinel */
};

void
Jeremy Hylton's avatar
Jeremy Hylton committed
657
initcPickleCache(void)
Jim Fulton's avatar
Jim Fulton committed
658
{
659
  PyObject *m;
660

661
  Cctype.ob_type = &PyType_Type;
662

663 664
  if (!ExtensionClassImported) 
      return;
Jim Fulton's avatar
Jim Fulton committed
665

Jeremy Hylton's avatar
Jeremy Hylton committed
666 667
  m = Py_InitModule4("cPickleCache", cCM_methods, cPickleCache_doc_string,
		     (PyObject*)NULL, PYTHON_API_VERSION);
Jim Fulton's avatar
Jim Fulton committed
668

669 670 671
  py_reload = PyString_InternFromString("reload");
  py__p_jar = PyString_InternFromString("_p_jar");
  py__p_changed = PyString_InternFromString("_p_changed");
Jim Fulton's avatar
Jim Fulton committed
672
}