Commit 351c5750 authored by Jim Fulton's avatar Jim Fulton

*** empty log message ***

parent 3765adf4
...@@ -48,12 +48,12 @@ ...@@ -48,12 +48,12 @@
__doc__='''Python implementation of persistent base types __doc__='''Python implementation of persistent base types
$Id: PersistentMapping.py,v 1.3 1998/11/11 02:00:56 jim Exp $''' $Id: PersistentMapping.py,v 1.4 1999/05/07 01:03:03 jim Exp $'''
__version__='$Revision: 1.3 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import Persistence import Persistence
class PM(Persistence.Persistent): class PersistentMapping(Persistence.Persistent):
"""A persistent wrapper for mapping objects. """A persistent wrapper for mapping objects.
This class allows wrapping of mapping objects so that This class allows wrapping of mapping objects so that
...@@ -113,4 +113,3 @@ class PM(Persistence.Persistent): ...@@ -113,4 +113,3 @@ class PM(Persistence.Persistent):
def values(self): def values(self):
return map(lambda k, d=self: d[k], self.keys()) return map(lambda k, d=self: d[k], self.keys())
PersistentMapping=PM
/*********************************************************************** /***********************************************************************
$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $
C Persistence Module C Persistence Module
...@@ -12,16 +12,19 @@ ...@@ -12,16 +12,19 @@
*****************************************************************************/ *****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $";
#include <time.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(V) ((PyObject*)(V))
static PyObject *py_keys, *py_setstate, *py___dict__; static PyObject *py_keys, *py_setstate, *py___dict__, *py_timeTime;
static PyObject *TimeStamp;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
static PyObject *debug_log=0; static PyObject *debug_log=0;
...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self) ...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/* /*
printf("%s %p\n",event,self->ob_type->tp_name); printf("%s %p\n",event,self->ob_type->tp_name);
*/ */
r=PyObject_CallFunction(debug_log,"s(ss#i)",event, r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid, 8, self->ob_type->tp_name, self->oid,
self->state); self->state);
Py_XDECREF(r); Py_XDECREF(r);
} }
...@@ -48,6 +51,7 @@ init_strings() ...@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S) #define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys); INIT_STRING(keys);
INIT_STRING(setstate); INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__); INIT_STRING(__dict__);
#undef INIT_STRING #undef INIT_STRING
} }
...@@ -201,14 +205,16 @@ static PyObject * ...@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args) Per___changed__(cPersistentObject *self, PyObject *args)
{ {
PyObject *v=0; PyObject *v=0;
if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL; if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL;
if (v && ! PyObject_IsTrue(v)) if (! v) return PyObject_GetAttrString(OBJECT(self), "_p_changed");
if (PyObject_IsTrue(v))
{ {
PyErr_SetString(PyExc_TypeError, if (changed(self) < 0) return NULL;
"Only true arguments are allowed.");
return NULL;
} }
if (changed(self) < 0) return NULL; else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -368,35 +374,30 @@ Per_dealloc(self) ...@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self); PyMem_DEL(self);
} }
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject * static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name, Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*)) PyObject *(*getattrf)(PyObject *, PyObject*))
{ {
char *n=name; char *n=name;
if(*n++=='_') if(n && *n++=='_')
if(*n++=='p' && *n++=='_') if(*n++=='p' && *n++=='_')
{ {
switch(*n++) switch(*n++)
{ {
case 'o': case 'o':
if(*n++=='i' && *n++=='d' && ! *n) if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
return PyString_FromStringAndSize(self->oid, 8);
break; break;
case 'j': case 'j':
if(*n++=='a' && *n++=='r' && ! *n) if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
break; break;
case 'c': case 'c':
if(strcmp(n,"hanged")==0) if(strcmp(n,"hanged")==0)
...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE); cPersistent_CHANGED_STATE);
} }
break; break;
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
break;
case 'm':
if(strcmp(n,"time")==0)
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
self->atime=((long)(time(NULL)/3))%65536;
oname=PyString_FromStringAndSize(self->serial, 8);
if (! oname) return oname;
ASSIGN(oname, PyObject_CallFunction(TimeStamp, "O", oname));
if (! oname) return oname;
ASSIGN(oname, PyObject_GetAttr(oname, py_timeTime));
if (! oname) return oname;
ASSIGN(oname, PyObject_CallObject(oname, NULL));
return oname;
}
break;
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
} }
if(! (*name++=='_' && *name++=='_' && if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0 (strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0))) || strcmp(name, "of__")==0)))
{ {
...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject* static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name) Per_getattro(cPersistentObject *self, PyObject *name)
{ {
char *s; char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL; if (PyString_Check(name))
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro); UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
} }
static int static int
...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6]) if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{ {
if (! v) return bad_delattr(); Py_XINCREF(v);
if (PyString_Check(v) && PyString_GET_SIZE(v)==8) ASSIGN(self->oid, v);
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
return 0; return 0;
} }
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6]) if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{ {
Py_XINCREF(v);
ASSIGN(self->jar, v); ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0; return 0;
} }
if(strcmp(name+3,"changed")==0) if(name[3]=='s' && strcmp(name+4,"erial")==0)
{ {
if (! v) return bad_delattr(); if (v)
if (v==Py_None) {
if (PyString_Check(v) && PyString_Size(v)==8)
memcpy(self->serial, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_ValueError,
"_p_serial must be an 8-character string");
return -1;
}
}
else
memset(self->serial, 0, 8);
return 0;
}
if(name[3]=='c' && strcmp(name+4,"hanged")==0)
{
if (! v || v==Py_None)
{ {
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None); if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
return 0; return 0;
...@@ -585,8 +617,15 @@ void ...@@ -585,8 +617,15 @@ void
initcPersistence() initcPersistence()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.25 $"; char *rev="$Revision: 1.26 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyImport_Import(TimeStamp));
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyObject_GetAttrString(TimeStamp, "TimeStamp"));
if (! TimeStamp) return;
m = Py_InitModule4("cPersistence", cP_methods, m = Py_InitModule4("cPersistence", cP_methods,
"", "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
/* /*
$Id: cPersistence.h,v 1.10 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.h,v 1.11 1999/05/07 01:03:03 jim Exp $
Definitions to facilitate making cPersistent subclasses in C. Definitions to facilitate making cPersistent subclasses in C.
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \ #define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \ PyObject *jar; \
char oid[8]; \ PyObject *oid; \
char serial[8]; \
unsigned short atime; \ unsigned short atime; \
signed char state; \ signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1 #define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
...@@ -43,6 +45,8 @@ typedef struct { ...@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI; static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \ #define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \ if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \ cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI; ...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_STATE && \ ((O)->state==cPersistent_STICKY_STATE && \
((O)->state=cPersistent_UPTODATE_STATE)) ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_PREVENT_DEACTIVATION(O) \
((O)->state==cPersistent_UPTODATE_STATE && \
((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O) Py_XDECREF((O)->jar) #define PER_DEL(O) Py_XDECREF((O)->jar)
#endif #endif
......
static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPickleCache.c,v 1.17 1999/05/07 01:03:03 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E ...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E
static PyObject *py_reload, *py__p_jar, *py__p_deactivate; static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *data; PyObject *data;
PyObject *jar;
int position; int position;
int cache_size; int cache_size;
int cache_age; int cache_age;
...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) && if (dt &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE) (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE
)
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0) now += 65536;
...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = { ...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
}; };
static ccobject * static ccobject *
newccobject(int cache_size, int cache_age) newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New()) if(self->data=PyDict_New())
{ {
self->jar=jar;
Py_INCREF(jar);
self->position=0; self->position=0;
self->cache_size=cache_size; self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age; self->cache_age=cache_age < 1 ? 1 : cache_age;
...@@ -312,6 +315,7 @@ static void ...@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self) cc_dealloc(ccobject *self)
{ {
Py_XDECREF(self->data); Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self); PyMem_DEL(self);
} }
...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r; return r;
} }
static PyExtensionClass *Persistent=0;
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) return PyDict_SetItem(self->data, key, v); if(v)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
)
)
return PyDict_SetItem(self->data, key, v);
PyErr_SetString(PyExc_ValueError,
"Cache values must be persistent objects or classes.");
return -1;
}
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
...@@ -446,8 +464,10 @@ static PyObject * ...@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args) cCM_new(PyObject *self, PyObject *args)
{ {
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL; PyObject *jar;
return (PyObject*)newccobject(cache_size,cache_age);
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -459,10 +479,20 @@ void ...@@ -459,10 +479,20 @@ void
initcPickleCache() initcPickleCache()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.16 $"; char *rev="$Revision: 1.17 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
UNLESS(ExtensionClassImported) return;
/* Get the Persistent base class */
UNLESS(m=PyString_FromString(cPersistanceModuleName)) return;
ASSIGN(m, PyImport_Import(m));
UNLESS(m) return;
ASSIGN(m, PyObject_GetAttrString(m, "Persistent"));
UNLESS(m) return;
Persistent=(PyExtensionClass *)m;
m = Py_InitModule4("cPickleCache", cCM_methods, "", m = Py_InitModule4("cPickleCache", cCM_methods, "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
This diff is collapsed.
...@@ -47,10 +47,10 @@ ...@@ -47,10 +47,10 @@
############################################################################## ##############################################################################
"""Database connection support """Database connection support
$Id: Connection.py,v 1.2 1999/04/28 11:10:48 jim Exp $""" $Id: Connection.py,v 1.3 1999/05/07 01:03:02 jim Exp $"""
__version__='$Revision: 1.2 $'[11:-2] __version__='$Revision: 1.3 $'[11:-2]
from PickleCache import PickleCache from cPickleCache import PickleCache
from bpthread import allocate_lock from bpthread import allocate_lock
from POSException import ConflictError from POSException import ConflictError
from cStringIO import StringIO from cStringIO import StringIO
...@@ -75,7 +75,7 @@ class Connection: ...@@ -75,7 +75,7 @@ class Connection:
self._storage=storage self._storage=storage
self.new_oid=storage.new_oid self.new_oid=storage.new_oid
self._version=version self._version=version
self._cache=cache=PickleCache(cache_size, cache_deactivate_after) self._cache=cache=PickleCache(self, cache_size, cache_deactivate_after)
self._incrgc=cache.incrgc self._incrgc=cache.incrgc
self._invalidated={} self._invalidated={}
lock=allocate_lock() lock=allocate_lock()
...@@ -94,38 +94,25 @@ class Connection: ...@@ -94,38 +94,25 @@ class Connection:
if cache.has_key(oid): return cache[oid] if cache.has_key(oid): return cache[oid]
__traceback_info__=oid __traceback_info__=oid
p=self._storage.load(oid, self._version) p, serial = self._storage.load(oid, self._version)
file=StringIO(p) file=StringIO(p)
unpickler=Unpickler(file) unpickler=Unpickler(file)
unpickler.persistent_load=self._persistent_load unpickler.persistent_load=self._persistent_load
object = unpickler.load() object = unpickler.load()
if type(object) is tt: klass, args = object
klass, args = object if (args is None or
if (args is None or not args and not hasattr(klass,'__getinitargs__')):
not args and not hasattr(klass,'__getinitargs__')): object=klass.__basicnew__()
if type(klass) is ct:
object=HelperClass()
object.__class__=klass
else: object=klass.__basicnew__()
else:
object=apply(klass,args)
object.__dict__.clear()
else: else:
object=apply(klass,args)
object.__dict__.clear() object.__dict__.clear()
klass=object.__class__
object._p_oid=oid
if type(klass) is ct: object._p_jar=self
d=object.__dict__ object._p_changed=None
d['_p_oid']=oid object._p_serial=serial
d['_p_jar']=self
d['_p_changed']=None
else:
object._p_oid=oid
object._p_jar=self
object._p_changed=None
cache[oid]=object cache[oid]=object
return object return object
...@@ -143,18 +130,10 @@ class Connection: ...@@ -143,18 +130,10 @@ class Connection:
# to create the instance wo hitting the db, so go for it! # to create the instance wo hitting the db, so go for it!
oid, klass = oid oid, klass = oid
if cache.has_key(oid): return cache[oid] if cache.has_key(oid): return cache[oid]
if type(klass) is ct: object=klass.__basicnew__()
object=HelperClass() object._p_oid=oid
object.__class__=klass object._p_jar=self
d=object.__dict__ object._p_changed=None
d['_p_oid']=oid
d['_p_jar']=self
d['_p_changed']=None
else:
object=klass.__basicnew__()
object._p_oid=oid
object._p_jar=self
object._p_changed=None
cache[oid]=object cache[oid]=object
return object return object
...@@ -236,6 +215,7 @@ class Connection: ...@@ -236,6 +215,7 @@ class Connection:
object=stack[-1] object=stack[-1]
del stack[-1] del stack[-1]
oid=object._p_oid oid=object._p_oid
serial=object._p_serial
if self._invalidated.has_key(oid): raise ConflictError, oid if self._invalidated.has_key(oid): raise ConflictError, oid
cls = object.__class__ cls = object.__class__
if hasattr(cls, '__getinitargs__'): if hasattr(cls, '__getinitargs__'):
...@@ -249,7 +229,7 @@ class Connection: ...@@ -249,7 +229,7 @@ class Connection:
state=object.__getstate__() state=object.__getstate__()
dump(state) dump(state)
p=file() p=file()
dbstore(oid,p,version,transaction) object._p_serial=dbstore(oid,serial,p,version,transaction)
object._p_changed=0 object._p_changed=0
cache[oid]=object cache[oid]=object
...@@ -287,7 +267,7 @@ class Connection: ...@@ -287,7 +267,7 @@ class Connection:
self._r() self._r()
raise ConflictError, oid raise ConflictError, oid
self._r() self._r()
p=self._storage.load(oid, self._version) p, serial = self._storage.load(oid, self._version)
file=StringIO(p) file=StringIO(p)
unpickler=Unpickler(file) unpickler=Unpickler(file)
unpickler.persistent_load=self._persistent_load unpickler.persistent_load=self._persistent_load
...@@ -298,6 +278,7 @@ class Connection: ...@@ -298,6 +278,7 @@ class Connection:
else: else:
d=object.__dict__ d=object.__dict__
for k,v in state.items(): d[k]=v for k,v in state.items(): d[k]=v
object._p_serial=serial
def tpc_abort(self, transaction): def tpc_abort(self, transaction):
self._storage.tpc_abort(transaction) self._storage.tpc_abort(transaction)
......
...@@ -47,8 +47,8 @@ ...@@ -47,8 +47,8 @@
############################################################################## ##############################################################################
"""Database objects """Database objects
$Id: DB.py,v 1.2 1999/04/28 11:10:48 jim Exp $""" $Id: DB.py,v 1.3 1999/05/07 01:03:02 jim Exp $"""
__version__='$Revision: 1.2 $'[11:-2] __version__='$Revision: 1.3 $'[11:-2]
import cPickle, cStringIO, sys import cPickle, cStringIO, sys
from Connection import Connection from Connection import Connection
...@@ -90,7 +90,7 @@ class DB: ...@@ -90,7 +90,7 @@ class DB:
t=Transaction() t=Transaction()
t.description='initial database creation' t.description='initial database creation'
storage.tpc_begin(t) storage.tpc_begin(t)
storage.store('\0\0\0\0\0\0\0\0', file.getvalue(), '', t) storage.store('\0\0\0\0\0\0\0\0', None, file.getvalue(), '', t)
storage.tpc_finish(t) storage.tpc_finish(t)
# Allocate locks: # Allocate locks:
...@@ -389,8 +389,8 @@ class DB: ...@@ -389,8 +389,8 @@ class DB:
def getCacheDeactivateAfter(self): return self._cache_deactivate_after def getCacheDeactivateAfter(self): return self._cache_deactivate_after
def getCacheSize(self): return self._cache_size def getCacheSize(self): return self._cache_size
def getPoolSize(self): return self._pool_size def getPoolSize(self): return self._pool_size
def getVersionCacheDeactivateAfter(self): return def getVersionCacheDeactivateAfter(self):
self._version_cache_deactivate_after return self._version_cache_deactivate_after
def getVersionCacheSize(self): return self._version_cache_size def getVersionCacheSize(self): return self._version_cache_size
def getVersionPoolSize(self): return self._version_pool_size def getVersionPoolSize(self): return self._version_pool_size
......
This diff is collapsed.
/* $Id: IIBTree.c,v 1.4 1997/10/10 18:23:37 jim Exp $ */
#define INTKEY int
#define INTVAL int
static char *needed_to_make_release_happy="$Id: IIBTree.c,v 1.4 1997/10/10 18:23:37 jim Exp $";
#include "BTree.c"
/* $Id: IOBTree.c,v 1.4 1997/10/10 18:24:11 jim Exp $ */
static char *needed_to_make_release_happy=
"$Id: IOBTree.c,v 1.4 1997/10/10 18:24:11 jim Exp $";
#define INTKEY int
#include "BTree.c"
/* $Id: OIBTree.c,v 1.4 1997/10/10 18:24:35 jim Exp $ */
static char *needed_to_make_release_happy=
"$Id: OIBTree.c,v 1.4 1997/10/10 18:24:35 jim Exp $";
#define INTVAL int
#include "BTree.c"
##############################################################################
#
# Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS IS*
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
#
# If you have questions regarding this software, contact:
#
# Digital Creations, L.C.
# 910 Princess Ann Street
# Fredericksburge, Virginia 22401
#
# info@digicool.com
#
# (540) 371-6909
#
##############################################################################
'''Python implementation of a persistent base types
$Id: Persistence.py,v 1.17 1998/11/11 02:00:56 jim Exp $'''
__version__='$Revision: 1.17 $'[11:-2]
_marker=[]
class Persistent:
"""\
Persistent object support mix-in class
When a persistent object is loaded from a database, the object's
data is not immediately loaded. Loading of the objects data is
defered until an attempt is made to access an attribute of the
object.
The object also tries to keep track of whether it has changed. It
is easy for this to be done incorrectly. For this reason, methods
of subclasses that change state other than by setting attributes
should: 'self.__changed__(1)' to flag instances as changed.
You must not override the object's '__getattr__' and '__setattr__'
methods. If you override the objects '__getstate__' method, then
you must be careful not to include any attributes with names
starting with '_p_' or '_v_' in the state.
"""
_p_oid=None # A Persistent object-id, unique within a jar
_p_changed=0 # The object state: None=ghost, 0=normal, 1=changed
_p_jar=None # The last jar that this object was stored in.
def _p_deactivate(self):
d=self.__dict__
oid=d['_p_oid']
jar=d['_p_jar']
d.clear()
d['_p_oid']=oid
d['_p_jar']=jar
d['_p_changed']=None
def __getattr__(self,key):
'Get an item'
if self._p_changed is None and key[:3] != '_p_':
self._p_jar.setstate(self)
if self.__dict__.has_key(key): return self.__dict__[key]
raise AttributeError, key
def __setattr__(self,key,value):
' '
changed=self._p_changed
if changed:
self.__dict__[key]=value
return
k=key[:3]
if k=='_p_' or k=='_v_':
if key=='_p_changed':
if changed == value: return
if value:
if changed: return
try:
if self._p_jar and self._p_oid:
get_transaction().register(self)
except: pass
elif value is None:
if self._p_jar and self._p_oid:
return self._p_deactivate()
return
value=not not value
self.__dict__[key]=value
return
jar=self._p_jar
if jar is None:
self.__dict__[key]=value
return
d=self.__dict__
if changed is None:
d['_p_changed']=1
jar.setstate(self)
d[key]=value
try:
get_transaction().register(self)
d['_p_changed']=1
except: pass
def __changed__(self,v=_marker):
if v is _marker: return not not self._p_changed
self._p_changed = not not v
def __getstate__(self):
# First, update my state, if necessary:
if self._p_changed is None: self._p_jar.setstate(self)
state={}
d=self.__dict__
for k,v in d.items():
if k[:3] != '_p_' and k[:3] != '_v_': state[k]=v
return state
def __setstate__(self,state):
self.__dict__.update(state)
def __repr__(self):
' '
return '<%s instance at %s>' % (self.__class__.__name__,
hex(id(self)))
...@@ -48,12 +48,12 @@ ...@@ -48,12 +48,12 @@
__doc__='''Python implementation of persistent base types __doc__='''Python implementation of persistent base types
$Id: PersistentMapping.py,v 1.3 1998/11/11 02:00:56 jim Exp $''' $Id: PersistentMapping.py,v 1.4 1999/05/07 01:03:03 jim Exp $'''
__version__='$Revision: 1.3 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import Persistence import Persistence
class PM(Persistence.Persistent): class PersistentMapping(Persistence.Persistent):
"""A persistent wrapper for mapping objects. """A persistent wrapper for mapping objects.
This class allows wrapping of mapping objects so that This class allows wrapping of mapping objects so that
...@@ -113,4 +113,3 @@ class PM(Persistence.Persistent): ...@@ -113,4 +113,3 @@ class PM(Persistence.Persistent):
def values(self): def values(self):
return map(lambda k, d=self: d[k], self.keys()) return map(lambda k, d=self: d[k], self.keys())
PersistentMapping=PM
##############################################################################
#
# Copyright (c) 1996-1998, Digital Creations, Fredericksburg, VA, USA.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# o Redistributions of source code must retain the above copyright
# notice, this list of conditions, and the disclaimer that follows.
#
# o Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions, and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# o Neither the name of Digital Creations nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS IS*
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
#
# If you have questions regarding this software, contact:
#
# Digital Creations, L.C.
# 910 Princess Ann Street
# Fredericksburge, Virginia 22401
#
# info@digicool.com
#
# (540) 371-6909
#
##############################################################################
__doc__='''PickleJar Object Cache
$Id: PickleCache.py,v 1.5 1998/11/11 02:00:56 jim Exp $'''
__version__='$Revision: 1.5 $'[11:-2]
from sys import getrefcount
class PickleCache:
def __init__(self, cache_size, cache_age=1000):
if cache_size < 1: cache_size=1
self.cache_size=cache_size
self.data, self.cache_ids, self.cache_location ={}, [], 0
for a in 'keys', 'items', 'values', 'has_key':
setattr(self,a,getattr(self.data,a))
def __getitem__(self, key):
v=self.data[key]
self.incrgc()
return v
def incrgc(self):
# Do cache GC
cache=self.data
n=min(len(cache)/self.cache_size,10)
if n:
l=self.cache_location
ids=self.cache_ids
while n:
if not l:
ids=self.cache_ids=cache.keys()
l=len(ids)
l=l-1
n=n-1
id=ids[l]
if getrefcount(cache[id]) <= 2:
del cache[id]
self.cache_location=l
def __setitem__(self, key, v):
self.data[key]=v
self.incrgc()
def __delitem__(self, key):
del self.data[key]
self.incrgc()
def __len__(self): return len(self.data)
def values(self): return self.data.values()
def full_sweep(self):
cache=self.data
for id in cache.keys():
if getrefcount(cache[id]) <= 2: del cache[id]
def minimize(self):
cache=self.data
keys=cache.keys()
rc=getrefcount
last=None
l=len(cache)
while l != last:
for id in keys():
if rc(cache[id]) <= 2: del cache[id]
cache[id]._p_deactivate()
l=len(cache)
*shared* *shared*
cPersistence cPersistence.c -I../ExtensionClass -I../python cPersistence cPersistence.c -I../../Components/ExtensionClass
cPickleCache cPickleCache.c -I../ExtensionClass -I../python cPickleCache cPickleCache.c -I../../Components/ExtensionClass
cPickleJar ./cPickleJar.c -I../ExtensionClass
iTree ./iTree.c -I../ExtensionClass
intSet ./intSet.c -I/projects/_/ExtensionClass -I/projects/_/cPersistence -I/projects/_/python
BTree ./BTree.c -I/projects/_/ExtensionClass -I/projects/_/cPersistence -I/projects/_/python
IIBTree ./IIBTree.c -I/projects/_/ExtensionClass -I/projects/_/cPersistence -I/projects/_/python
IOBTree ./IOBTree.c -I/projects/_/ExtensionClass -I/projects/_/cPersistence -I/projects/_/python
OIBTree ./OIBTree.c -I/projects/_/ExtensionClass -I/projects/_/cPersistence -I/projects/_/python
#cPickleJar cPickleJar.c -I../../Components/ExtensionClass
#iTree iTree.c -I../../Components/ExtensionClass
...@@ -47,29 +47,26 @@ ...@@ -47,29 +47,26 @@
############################################################################## ##############################################################################
"""Transaction management """Transaction management
$Id: Transaction.py,v 1.3 1998/11/11 02:00:56 jim Exp $""" $Id: Transaction.py,v 1.4 1999/05/07 01:03:03 jim Exp $"""
__version__='$Revision: 1.3 $'[11:-2] __version__='$Revision: 1.4 $'[11:-2]
import time, sys, struct import time, sys, struct
from struct import pack from struct import pack
from string import split, strip, join from string import split, strip, join
ConflictError="" from POSException import ConflictError
class Transaction: class Transaction:
'Simple transaction objects for single-threaded applications.' 'Simple transaction objects for single-threaded applications.'
user='' user=''
description='' description=''
_connections=None _connections=None
_extension=None
def __init__(self, def __init__(self,
time=time.time, pack=struct.pack, gmtime=time.gmtime): time=time.time, pack=struct.pack, gmtime=time.gmtime):
self._objects=[] self._objects=[]
self._append=self._objects.append self._append=self._objects.append
self.time=now=time()
y,mo,d,h,m=gmtime(now)[:5]
s=int((now%60)*1000000)
self.id=pack("<II", (((y*12+mo)*31+d)*24+h)*60+m, s)
self._note=self._user=self._description='' self._note=self._user=self._description=''
if self._connections: if self._connections:
for c in self._connections.values(): c.close() for c in self._connections.values(): c.close()
...@@ -136,15 +133,20 @@ class Transaction: ...@@ -136,15 +133,20 @@ class Transaction:
'Register the given object for transaction control.' 'Register the given object for transaction control.'
self._append(object) self._append(object)
def remark(self, text): def note(self, text):
if self.description: if self.description:
self.description = "%s\n\n%s" % (self.description, strip(text)) self.description = "%s\n\n%s" % (self.description, strip(text))
else: else:
self.description = strip(text) self.description = strip(text)
def setUser(self, user_name, path='/'): def setUser(self, user_name, path='/'):
self.user="%s %s" % (path, user_name) self.user="%s %s" % (path, user_name)
def setExtendedInfo(self, name, value):
ext=self._extension
if ext is None:
ext=self._extension={}
ext[name]=value
############################################################################ ############################################################################
...@@ -175,9 +177,4 @@ del _t ...@@ -175,9 +177,4 @@ del _t
import __main__ import __main__
__main__.__builtins__.get_transaction=get_transaction __main__.__builtins__.get_transaction=get_transaction
def time2id(now, gmtime=time.gmtime, pack=struct.pack):
y,m,d,h,m=gmtime(now)[:5]
s=int((now%60)*1000000)
return pack("<II", ((y*12+m)*31+d)*24, s)
...@@ -50,9 +50,9 @@ ...@@ -50,9 +50,9 @@
This module provides a wrapper that causes a database connection to be created This module provides a wrapper that causes a database connection to be created
and used when bobo publishes a bobo_application object. and used when bobo publishes a bobo_application object.
""" """
__version__='$Revision: 1.1 $'[11:-2] __version__='$Revision: 1.2 $'[11:-2]
class BoboApplication: class ZApplicationWrapper:
def __init__(self, db, name, klass= None, klass_args= (), def __init__(self, db, name, klass= None, klass_args= (),
version_cookie_name=None): version_cookie_name=None):
...@@ -94,8 +94,14 @@ class BoboApplication: ...@@ -94,8 +94,14 @@ class BoboApplication:
return v return v
__call__=__bobo_traverse__ # A convenience for command-line use
def __call__(self, connection=None):
db, aname, version_support = self._stuff
if connection is None:
connection=db.open()
return connection.root()[aname]
class Cleanup: pass class Cleanup: pass
......
...@@ -45,7 +45,26 @@ ...@@ -45,7 +45,26 @@
# (540) 371-6909 # (540) 371-6909
# #
############################################################################## ##############################################################################
import sys, ExtensionClass, TimeStamp, cPersistence, Persistence
# This is lame. Don't look. :(
sys.modules['cPersistence']=cPersistence
Persistent=cPersistence.Persistent
del cPersistence
# Install Persistent and PersistentMapping in Persistence
if not hasattr(Persistence, 'Persistent'):
Persistence.Persistent=Persistent
Persistent.__module__='Persistence'
if not hasattr(Persistence, 'PersistentMapping'):
from PersistentMapping import PersistentMapping
Persistence.PersistentMapping=PersistentMapping
PersistentMapping.__module__='Persistence'
del PersistentMapping
from DB import DB from DB import DB
from Persistence import Persistent
from POSException import *
import Transaction
del Transaction
/*********************************************************************** /***********************************************************************
$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $
C Persistence Module C Persistence Module
...@@ -12,16 +12,19 @@ ...@@ -12,16 +12,19 @@
*****************************************************************************/ *****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $";
#include <time.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(V) ((PyObject*)(V))
static PyObject *py_keys, *py_setstate, *py___dict__; static PyObject *py_keys, *py_setstate, *py___dict__, *py_timeTime;
static PyObject *TimeStamp;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
static PyObject *debug_log=0; static PyObject *debug_log=0;
...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self) ...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/* /*
printf("%s %p\n",event,self->ob_type->tp_name); printf("%s %p\n",event,self->ob_type->tp_name);
*/ */
r=PyObject_CallFunction(debug_log,"s(ss#i)",event, r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid, 8, self->ob_type->tp_name, self->oid,
self->state); self->state);
Py_XDECREF(r); Py_XDECREF(r);
} }
...@@ -48,6 +51,7 @@ init_strings() ...@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S) #define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys); INIT_STRING(keys);
INIT_STRING(setstate); INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__); INIT_STRING(__dict__);
#undef INIT_STRING #undef INIT_STRING
} }
...@@ -201,14 +205,16 @@ static PyObject * ...@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args) Per___changed__(cPersistentObject *self, PyObject *args)
{ {
PyObject *v=0; PyObject *v=0;
if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL; if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL;
if (v && ! PyObject_IsTrue(v)) if (! v) return PyObject_GetAttrString(OBJECT(self), "_p_changed");
if (PyObject_IsTrue(v))
{ {
PyErr_SetString(PyExc_TypeError, if (changed(self) < 0) return NULL;
"Only true arguments are allowed.");
return NULL;
} }
if (changed(self) < 0) return NULL; else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -368,35 +374,30 @@ Per_dealloc(self) ...@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self); PyMem_DEL(self);
} }
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject * static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name, Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*)) PyObject *(*getattrf)(PyObject *, PyObject*))
{ {
char *n=name; char *n=name;
if(*n++=='_') if(n && *n++=='_')
if(*n++=='p' && *n++=='_') if(*n++=='p' && *n++=='_')
{ {
switch(*n++) switch(*n++)
{ {
case 'o': case 'o':
if(*n++=='i' && *n++=='d' && ! *n) if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
return PyString_FromStringAndSize(self->oid, 8);
break; break;
case 'j': case 'j':
if(*n++=='a' && *n++=='r' && ! *n) if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
break; break;
case 'c': case 'c':
if(strcmp(n,"hanged")==0) if(strcmp(n,"hanged")==0)
...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE); cPersistent_CHANGED_STATE);
} }
break; break;
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
break;
case 'm':
if(strcmp(n,"time")==0)
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
self->atime=((long)(time(NULL)/3))%65536;
oname=PyString_FromStringAndSize(self->serial, 8);
if (! oname) return oname;
ASSIGN(oname, PyObject_CallFunction(TimeStamp, "O", oname));
if (! oname) return oname;
ASSIGN(oname, PyObject_GetAttr(oname, py_timeTime));
if (! oname) return oname;
ASSIGN(oname, PyObject_CallObject(oname, NULL));
return oname;
}
break;
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
} }
if(! (*name++=='_' && *name++=='_' && if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0 (strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0))) || strcmp(name, "of__")==0)))
{ {
...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject* static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name) Per_getattro(cPersistentObject *self, PyObject *name)
{ {
char *s; char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL; if (PyString_Check(name))
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro); UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
} }
static int static int
...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6]) if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{ {
if (! v) return bad_delattr(); Py_XINCREF(v);
if (PyString_Check(v) && PyString_GET_SIZE(v)==8) ASSIGN(self->oid, v);
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
return 0; return 0;
} }
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6]) if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{ {
Py_XINCREF(v);
ASSIGN(self->jar, v); ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0; return 0;
} }
if(strcmp(name+3,"changed")==0) if(name[3]=='s' && strcmp(name+4,"erial")==0)
{ {
if (! v) return bad_delattr(); if (v)
if (v==Py_None) {
if (PyString_Check(v) && PyString_Size(v)==8)
memcpy(self->serial, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_ValueError,
"_p_serial must be an 8-character string");
return -1;
}
}
else
memset(self->serial, 0, 8);
return 0;
}
if(name[3]=='c' && strcmp(name+4,"hanged")==0)
{
if (! v || v==Py_None)
{ {
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None); if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
return 0; return 0;
...@@ -585,8 +617,15 @@ void ...@@ -585,8 +617,15 @@ void
initcPersistence() initcPersistence()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.25 $"; char *rev="$Revision: 1.26 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyImport_Import(TimeStamp));
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyObject_GetAttrString(TimeStamp, "TimeStamp"));
if (! TimeStamp) return;
m = Py_InitModule4("cPersistence", cP_methods, m = Py_InitModule4("cPersistence", cP_methods,
"", "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
/* /*
$Id: cPersistence.h,v 1.10 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.h,v 1.11 1999/05/07 01:03:03 jim Exp $
Definitions to facilitate making cPersistent subclasses in C. Definitions to facilitate making cPersistent subclasses in C.
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \ #define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \ PyObject *jar; \
char oid[8]; \ PyObject *oid; \
char serial[8]; \
unsigned short atime; \ unsigned short atime; \
signed char state; \ signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1 #define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
...@@ -43,6 +45,8 @@ typedef struct { ...@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI; static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \ #define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \ if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \ cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI; ...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_STATE && \ ((O)->state==cPersistent_STICKY_STATE && \
((O)->state=cPersistent_UPTODATE_STATE)) ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_PREVENT_DEACTIVATION(O) \
((O)->state==cPersistent_UPTODATE_STATE && \
((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O) Py_XDECREF((O)->jar) #define PER_DEL(O) Py_XDECREF((O)->jar)
#endif #endif
......
static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPickleCache.c,v 1.17 1999/05/07 01:03:03 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E ...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E
static PyObject *py_reload, *py__p_jar, *py__p_deactivate; static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *data; PyObject *data;
PyObject *jar;
int position; int position;
int cache_size; int cache_size;
int cache_age; int cache_age;
...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) && if (dt &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE) (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE
)
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0) now += 65536;
...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = { ...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
}; };
static ccobject * static ccobject *
newccobject(int cache_size, int cache_age) newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New()) if(self->data=PyDict_New())
{ {
self->jar=jar;
Py_INCREF(jar);
self->position=0; self->position=0;
self->cache_size=cache_size; self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age; self->cache_age=cache_age < 1 ? 1 : cache_age;
...@@ -312,6 +315,7 @@ static void ...@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self) cc_dealloc(ccobject *self)
{ {
Py_XDECREF(self->data); Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self); PyMem_DEL(self);
} }
...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r; return r;
} }
static PyExtensionClass *Persistent=0;
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) return PyDict_SetItem(self->data, key, v); if(v)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
)
)
return PyDict_SetItem(self->data, key, v);
PyErr_SetString(PyExc_ValueError,
"Cache values must be persistent objects or classes.");
return -1;
}
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
...@@ -446,8 +464,10 @@ static PyObject * ...@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args) cCM_new(PyObject *self, PyObject *args)
{ {
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL; PyObject *jar;
return (PyObject*)newccobject(cache_size,cache_age);
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -459,10 +479,20 @@ void ...@@ -459,10 +479,20 @@ void
initcPickleCache() initcPickleCache()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.16 $"; char *rev="$Revision: 1.17 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
UNLESS(ExtensionClassImported) return;
/* Get the Persistent base class */
UNLESS(m=PyString_FromString(cPersistanceModuleName)) return;
ASSIGN(m, PyImport_Import(m));
UNLESS(m) return;
ASSIGN(m, PyObject_GetAttrString(m, "Persistent"));
UNLESS(m) return;
Persistent=(PyExtensionClass *)m;
m = Py_InitModule4("cPickleCache", cCM_methods, "", m = Py_InitModule4("cPickleCache", cCM_methods, "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
This diff is collapsed.
/*********************************************************************** /***********************************************************************
$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $
C Persistence Module C Persistence Module
...@@ -12,16 +12,19 @@ ...@@ -12,16 +12,19 @@
*****************************************************************************/ *****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.25 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPersistence.c,v 1.26 1999/05/07 01:03:03 jim Exp $";
#include <time.h> #include <string.h>
#include "cPersistence.h" #include "cPersistence.h"
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
#define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V) #define UNLESS_ASSIGN(V,E) ASSIGN(V,E) UNLESS(V)
#define OBJECT(V) ((PyObject*)(V))
static PyObject *py_keys, *py_setstate, *py___dict__; static PyObject *py_keys, *py_setstate, *py___dict__, *py_timeTime;
static PyObject *TimeStamp;
#ifdef DEBUG_LOG #ifdef DEBUG_LOG
static PyObject *debug_log=0; static PyObject *debug_log=0;
...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self) ...@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/* /*
printf("%s %p\n",event,self->ob_type->tp_name); printf("%s %p\n",event,self->ob_type->tp_name);
*/ */
r=PyObject_CallFunction(debug_log,"s(ss#i)",event, r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid, 8, self->ob_type->tp_name, self->oid,
self->state); self->state);
Py_XDECREF(r); Py_XDECREF(r);
} }
...@@ -48,6 +51,7 @@ init_strings() ...@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S) #define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys); INIT_STRING(keys);
INIT_STRING(setstate); INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__); INIT_STRING(__dict__);
#undef INIT_STRING #undef INIT_STRING
} }
...@@ -201,14 +205,16 @@ static PyObject * ...@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args) Per___changed__(cPersistentObject *self, PyObject *args)
{ {
PyObject *v=0; PyObject *v=0;
if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL; if (args && ! PyArg_ParseTuple(args, "|O",&v)) return NULL;
if (v && ! PyObject_IsTrue(v)) if (! v) return PyObject_GetAttrString(OBJECT(self), "_p_changed");
if (PyObject_IsTrue(v))
{ {
PyErr_SetString(PyExc_TypeError, if (changed(self) < 0) return NULL;
"Only true arguments are allowed.");
return NULL;
} }
if (changed(self) < 0) return NULL; else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -368,35 +374,30 @@ Per_dealloc(self) ...@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self); PyMem_DEL(self);
} }
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject * static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name, Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*)) PyObject *(*getattrf)(PyObject *, PyObject*))
{ {
char *n=name; char *n=name;
if(*n++=='_') if(n && *n++=='_')
if(*n++=='p' && *n++=='_') if(*n++=='p' && *n++=='_')
{ {
switch(*n++) switch(*n++)
{ {
case 'o': case 'o':
if(*n++=='i' && *n++=='d' && ! *n) if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
return PyString_FromStringAndSize(self->oid, 8);
break; break;
case 'j': case 'j':
if(*n++=='a' && *n++=='r' && ! *n) if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
break; break;
case 'c': case 'c':
if(strcmp(n,"hanged")==0) if(strcmp(n,"hanged")==0)
...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE); cPersistent_CHANGED_STATE);
} }
break; break;
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
break;
case 'm':
if(strcmp(n,"time")==0)
{
UPDATE_STATE_IF_NECESSARY(self, NULL);
self->atime=((long)(time(NULL)/3))%65536;
oname=PyString_FromStringAndSize(self->serial, 8);
if (! oname) return oname;
ASSIGN(oname, PyObject_CallFunction(TimeStamp, "O", oname));
if (! oname) return oname;
ASSIGN(oname, PyObject_GetAttr(oname, py_timeTime));
if (! oname) return oname;
ASSIGN(oname, PyObject_CallObject(oname, NULL));
return oname;
}
break;
} }
return getattrf((PyObject *)self, oname); return getattrf((PyObject *)self, oname);
} }
if(! (*name++=='_' && *name++=='_' && if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0 (strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0))) || strcmp(name, "of__")==0)))
{ {
...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name, ...@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject* static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name) Per_getattro(cPersistentObject *self, PyObject *name)
{ {
char *s; char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL; if (PyString_Check(name))
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro); UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
} }
static int static int
...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v, ...@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{ {
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6]) if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{ {
if (! v) return bad_delattr(); Py_XINCREF(v);
if (PyString_Check(v) && PyString_GET_SIZE(v)==8) ASSIGN(self->oid, v);
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
return 0; return 0;
} }
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6]) if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{ {
Py_XINCREF(v);
ASSIGN(self->jar, v); ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0; return 0;
} }
if(strcmp(name+3,"changed")==0) if(name[3]=='s' && strcmp(name+4,"erial")==0)
{ {
if (! v) return bad_delattr(); if (v)
if (v==Py_None) {
if (PyString_Check(v) && PyString_Size(v)==8)
memcpy(self->serial, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_ValueError,
"_p_serial must be an 8-character string");
return -1;
}
}
else
memset(self->serial, 0, 8);
return 0;
}
if(name[3]=='c' && strcmp(name+4,"hanged")==0)
{
if (! v || v==Py_None)
{ {
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None); if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
return 0; return 0;
...@@ -585,8 +617,15 @@ void ...@@ -585,8 +617,15 @@ void
initcPersistence() initcPersistence()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.25 $"; char *rev="$Revision: 1.26 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyImport_Import(TimeStamp));
if (! TimeStamp) return;
ASSIGN(TimeStamp, PyObject_GetAttrString(TimeStamp, "TimeStamp"));
if (! TimeStamp) return;
m = Py_InitModule4("cPersistence", cP_methods, m = Py_InitModule4("cPersistence", cP_methods,
"", "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
/* /*
$Id: cPersistence.h,v 1.10 1998/11/11 02:00:56 jim Exp $ $Id: cPersistence.h,v 1.11 1999/05/07 01:03:03 jim Exp $
Definitions to facilitate making cPersistent subclasses in C. Definitions to facilitate making cPersistent subclasses in C.
...@@ -15,9 +15,11 @@ ...@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \ #define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \ PyObject *jar; \
char oid[8]; \ PyObject *oid; \
char serial[8]; \
unsigned short atime; \ unsigned short atime; \
signed char state; \ signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1 #define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0 #define cPersistent_UPTODATE_STATE 0
...@@ -43,6 +45,8 @@ typedef struct { ...@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI; static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \ #define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \ if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \ cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI; ...@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_STATE && \ ((O)->state==cPersistent_STICKY_STATE && \
((O)->state=cPersistent_UPTODATE_STATE)) ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_PREVENT_DEACTIVATION(O) \
((O)->state==cPersistent_UPTODATE_STATE && \
((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O) Py_XDECREF((O)->jar) #define PER_DEL(O) Py_XDECREF((O)->jar)
#endif #endif
......
static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim Exp $"; static char *what_string = "$Id: cPickleCache.c,v 1.17 1999/05/07 01:03:03 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;} #define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E)) #define UNLESS(E) if(!(E))
...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E ...@@ -12,12 +12,10 @@ static char *what_string = "$Id: cPickleCache.c,v 1.16 1998/11/11 02:00:56 jim E
static PyObject *py_reload, *py__p_jar, *py__p_deactivate; static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PyObject *data; PyObject *data;
PyObject *jar;
int position; int position;
int cache_size; int cache_size;
int cache_age; int cache_age;
...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt) ...@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) && if (dt &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE) (! PyExtensionClass_Check(v)) &&
((cPersistentObject*)v)->jar==self->jar /* I'm paranoid */ &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE
)
{ {
now -= ((cPersistentObject*)v)->atime; now -= ((cPersistentObject*)v)->atime;
if (now < 0) now += 65536; if (now < 0) now += 65536;
...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = { ...@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
}; };
static ccobject * static ccobject *
newccobject(int cache_size, int cache_age) newccobject(PyObject *jar, int cache_size, int cache_age)
{ {
ccobject *self; ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL; UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New()) if(self->data=PyDict_New())
{ {
self->jar=jar;
Py_INCREF(jar);
self->position=0; self->position=0;
self->cache_size=cache_size; self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age; self->cache_age=cache_age < 1 ? 1 : cache_age;
...@@ -312,6 +315,7 @@ static void ...@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self) cc_dealloc(ccobject *self)
{ {
Py_XDECREF(self->data); Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self); PyMem_DEL(self);
} }
...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key) ...@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r; return r;
} }
static PyExtensionClass *Persistent=0;
static int static int
cc_ass_sub(ccobject *self, PyObject *key, PyObject *v) cc_ass_sub(ccobject *self, PyObject *key, PyObject *v)
{ {
if(v) return PyDict_SetItem(self->data, key, v); if(v)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
)
)
return PyDict_SetItem(self->data, key, v);
PyErr_SetString(PyExc_ValueError,
"Cache values must be persistent objects or classes.");
return -1;
}
return PyDict_DelItem(self->data, key); return PyDict_DelItem(self->data, key);
} }
...@@ -446,8 +464,10 @@ static PyObject * ...@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args) cCM_new(PyObject *self, PyObject *args)
{ {
int cache_size=100, cache_age=1000; int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL; PyObject *jar;
return (PyObject*)newccobject(cache_size,cache_age);
UNLESS(PyArg_ParseTuple(args, "O|ii", &jar, &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(jar, cache_size,cache_age);
} }
static struct PyMethodDef cCM_methods[] = { static struct PyMethodDef cCM_methods[] = {
...@@ -459,10 +479,20 @@ void ...@@ -459,10 +479,20 @@ void
initcPickleCache() initcPickleCache()
{ {
PyObject *m, *d; PyObject *m, *d;
char *rev="$Revision: 1.16 $"; char *rev="$Revision: 1.17 $";
Cctype.ob_type=&PyType_Type; Cctype.ob_type=&PyType_Type;
UNLESS(ExtensionClassImported) return;
/* Get the Persistent base class */
UNLESS(m=PyString_FromString(cPersistanceModuleName)) return;
ASSIGN(m, PyImport_Import(m));
UNLESS(m) return;
ASSIGN(m, PyObject_GetAttrString(m, "Persistent"));
UNLESS(m) return;
Persistent=(PyExtensionClass *)m;
m = Py_InitModule4("cPickleCache", cCM_methods, "", m = Py_InitModule4("cPickleCache", cCM_methods, "",
(PyObject*)NULL,PYTHON_API_VERSION); (PyObject*)NULL,PYTHON_API_VERSION);
......
This diff is collapsed.
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