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

*** empty log message ***

parent 3765adf4
......@@ -48,12 +48,12 @@
__doc__='''Python implementation of persistent base types
$Id: PersistentMapping.py,v 1.3 1998/11/11 02:00:56 jim Exp $'''
__version__='$Revision: 1.3 $'[11:-2]
$Id: PersistentMapping.py,v 1.4 1999/05/07 01:03:03 jim Exp $'''
__version__='$Revision: 1.4 $'[11:-2]
import Persistence
class PM(Persistence.Persistent):
class PersistentMapping(Persistence.Persistent):
"""A persistent wrapper for mapping objects.
This class allows wrapping of mapping objects so that
......@@ -113,4 +113,3 @@ class PM(Persistence.Persistent):
def values(self):
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
......@@ -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"
#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(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
static PyObject *debug_log=0;
......@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/*
printf("%s %p\n",event,self->ob_type->tp_name);
*/
r=PyObject_CallFunction(debug_log,"s(ss#i)",event,
self->ob_type->tp_name, self->oid, 8,
r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid,
self->state);
Py_XDECREF(r);
}
......@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys);
INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__);
#undef INIT_STRING
}
......@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args)
{
PyObject *v=0;
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,
"Only true arguments are allowed.");
return NULL;
if (changed(self) < 0) return NULL;
}
if (changed(self) < 0) return NULL;
else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self);
}
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*))
{
char *n=name;
if(*n++=='_')
if(n && *n++=='_')
if(*n++=='p' && *n++=='_')
{
switch(*n++)
{
case 'o':
if(*n++=='i' && *n++=='d' && ! *n)
return PyString_FromStringAndSize(self->oid, 8);
if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
break;
case 'j':
if(*n++=='a' && *n++=='r' && ! *n)
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
break;
case 'c':
if(strcmp(n,"hanged")==0)
......@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE);
}
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);
}
if(! (*name++=='_' && *name++=='_' &&
if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0)))
{
......@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name)
{
char *s;
char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro);
if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
}
static int
......@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{
if (! v) return bad_delattr();
if (PyString_Check(v) && PyString_GET_SIZE(v)==8)
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
Py_XINCREF(v);
ASSIGN(self->oid, v);
return 0;
}
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{
Py_XINCREF(v);
ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0;
}
if(strcmp(name+3,"changed")==0)
if(name[3]=='s' && strcmp(name+4,"erial")==0)
{
if (! v) return bad_delattr();
if (v==Py_None)
if (v)
{
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);
return 0;
......@@ -585,8 +617,15 @@ void
initcPersistence()
{
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,
"",
(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.
......@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \
char oid[8]; \
PyObject *oid; \
char serial[8]; \
unsigned short atime; \
signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
......@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_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)
#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 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
static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
int position;
int cache_size;
int cache_age;
......@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key);
}
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE)
if (dt &&
(! 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;
......@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
};
static ccobject *
newccobject(int cache_size, int cache_age)
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New())
{
self->jar=jar;
Py_INCREF(jar);
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
......@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self);
}
......@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r;
}
static PyExtensionClass *Persistent=0;
static int
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);
}
......@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args)
{
int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(cache_size,cache_age);
PyObject *jar;
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[] = {
......@@ -459,10 +479,20 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.16 $";
char *rev="$Revision: 1.17 $";
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, "",
(PyObject*)NULL,PYTHON_API_VERSION);
......
This diff is collapsed.
......@@ -47,10 +47,10 @@
##############################################################################
"""Database connection support
$Id: Connection.py,v 1.2 1999/04/28 11:10:48 jim Exp $"""
__version__='$Revision: 1.2 $'[11:-2]
$Id: Connection.py,v 1.3 1999/05/07 01:03:02 jim Exp $"""
__version__='$Revision: 1.3 $'[11:-2]
from PickleCache import PickleCache
from cPickleCache import PickleCache
from bpthread import allocate_lock
from POSException import ConflictError
from cStringIO import StringIO
......@@ -75,7 +75,7 @@ class Connection:
self._storage=storage
self.new_oid=storage.new_oid
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._invalidated={}
lock=allocate_lock()
......@@ -94,38 +94,25 @@ class Connection:
if cache.has_key(oid): return cache[oid]
__traceback_info__=oid
p=self._storage.load(oid, self._version)
p, serial = self._storage.load(oid, self._version)
file=StringIO(p)
unpickler=Unpickler(file)
unpickler.persistent_load=self._persistent_load
object = unpickler.load()
if type(object) is tt:
klass, args = object
if (args is None or
not args and not hasattr(klass,'__getinitargs__')):
if type(klass) is ct:
object=HelperClass()
object.__class__=klass
else: object=klass.__basicnew__()
else:
object=apply(klass,args)
object.__dict__.clear()
klass, args = object
if (args is None or
not args and not hasattr(klass,'__getinitargs__')):
object=klass.__basicnew__()
else:
object=apply(klass,args)
object.__dict__.clear()
klass=object.__class__
if type(klass) is ct:
d=object.__dict__
d['_p_oid']=oid
d['_p_jar']=self
d['_p_changed']=None
else:
object._p_oid=oid
object._p_jar=self
object._p_changed=None
object._p_oid=oid
object._p_jar=self
object._p_changed=None
object._p_serial=serial
cache[oid]=object
return object
......@@ -143,18 +130,10 @@ class Connection:
# to create the instance wo hitting the db, so go for it!
oid, klass = oid
if cache.has_key(oid): return cache[oid]
if type(klass) is ct:
object=HelperClass()
object.__class__=klass
d=object.__dict__
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
object=klass.__basicnew__()
object._p_oid=oid
object._p_jar=self
object._p_changed=None
cache[oid]=object
return object
......@@ -236,6 +215,7 @@ class Connection:
object=stack[-1]
del stack[-1]
oid=object._p_oid
serial=object._p_serial
if self._invalidated.has_key(oid): raise ConflictError, oid
cls = object.__class__
if hasattr(cls, '__getinitargs__'):
......@@ -249,7 +229,7 @@ class Connection:
state=object.__getstate__()
dump(state)
p=file()
dbstore(oid,p,version,transaction)
object._p_serial=dbstore(oid,serial,p,version,transaction)
object._p_changed=0
cache[oid]=object
......@@ -287,7 +267,7 @@ class Connection:
self._r()
raise ConflictError, oid
self._r()
p=self._storage.load(oid, self._version)
p, serial = self._storage.load(oid, self._version)
file=StringIO(p)
unpickler=Unpickler(file)
unpickler.persistent_load=self._persistent_load
......@@ -298,6 +278,7 @@ class Connection:
else:
d=object.__dict__
for k,v in state.items(): d[k]=v
object._p_serial=serial
def tpc_abort(self, transaction):
self._storage.tpc_abort(transaction)
......
......@@ -47,8 +47,8 @@
##############################################################################
"""Database objects
$Id: DB.py,v 1.2 1999/04/28 11:10:48 jim Exp $"""
__version__='$Revision: 1.2 $'[11:-2]
$Id: DB.py,v 1.3 1999/05/07 01:03:02 jim Exp $"""
__version__='$Revision: 1.3 $'[11:-2]
import cPickle, cStringIO, sys
from Connection import Connection
......@@ -90,7 +90,7 @@ class DB:
t=Transaction()
t.description='initial database creation'
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)
# Allocate locks:
......@@ -389,8 +389,8 @@ class DB:
def getCacheDeactivateAfter(self): return self._cache_deactivate_after
def getCacheSize(self): return self._cache_size
def getPoolSize(self): return self._pool_size
def getVersionCacheDeactivateAfter(self): return
self._version_cache_deactivate_after
def getVersionCacheDeactivateAfter(self):
return self._version_cache_deactivate_after
def getVersionCacheSize(self): return self._version_cache_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 @@
__doc__='''Python implementation of persistent base types
$Id: PersistentMapping.py,v 1.3 1998/11/11 02:00:56 jim Exp $'''
__version__='$Revision: 1.3 $'[11:-2]
$Id: PersistentMapping.py,v 1.4 1999/05/07 01:03:03 jim Exp $'''
__version__='$Revision: 1.4 $'[11:-2]
import Persistence
class PM(Persistence.Persistent):
class PersistentMapping(Persistence.Persistent):
"""A persistent wrapper for mapping objects.
This class allows wrapping of mapping objects so that
......@@ -113,4 +113,3 @@ class PM(Persistence.Persistent):
def values(self):
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*
cPersistence cPersistence.c -I../ExtensionClass -I../python
cPickleCache cPickleCache.c -I../ExtensionClass -I../python
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
cPersistence cPersistence.c -I../../Components/ExtensionClass
cPickleCache cPickleCache.c -I../../Components/ExtensionClass
#cPickleJar cPickleJar.c -I../../Components/ExtensionClass
#iTree iTree.c -I../../Components/ExtensionClass
......@@ -47,29 +47,26 @@
##############################################################################
"""Transaction management
$Id: Transaction.py,v 1.3 1998/11/11 02:00:56 jim Exp $"""
__version__='$Revision: 1.3 $'[11:-2]
$Id: Transaction.py,v 1.4 1999/05/07 01:03:03 jim Exp $"""
__version__='$Revision: 1.4 $'[11:-2]
import time, sys, struct
from struct import pack
from string import split, strip, join
ConflictError=""
from POSException import ConflictError
class Transaction:
'Simple transaction objects for single-threaded applications.'
user=''
description=''
_connections=None
_extension=None
def __init__(self,
time=time.time, pack=struct.pack, gmtime=time.gmtime):
self._objects=[]
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=''
if self._connections:
for c in self._connections.values(): c.close()
......@@ -136,15 +133,20 @@ class Transaction:
'Register the given object for transaction control.'
self._append(object)
def remark(self, text):
def note(self, text):
if self.description:
self.description = "%s\n\n%s" % (self.description, strip(text))
else:
self.description = strip(text)
def setUser(self, user_name, path='/'):
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
import __main__
__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 @@
This module provides a wrapper that causes a database connection to be created
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= (),
version_cookie_name=None):
......@@ -94,8 +94,14 @@ class BoboApplication:
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
......
......@@ -45,7 +45,26 @@
# (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 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
......@@ -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"
#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(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
static PyObject *debug_log=0;
......@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/*
printf("%s %p\n",event,self->ob_type->tp_name);
*/
r=PyObject_CallFunction(debug_log,"s(ss#i)",event,
self->ob_type->tp_name, self->oid, 8,
r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid,
self->state);
Py_XDECREF(r);
}
......@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys);
INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__);
#undef INIT_STRING
}
......@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args)
{
PyObject *v=0;
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,
"Only true arguments are allowed.");
return NULL;
if (changed(self) < 0) return NULL;
}
if (changed(self) < 0) return NULL;
else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self);
}
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*))
{
char *n=name;
if(*n++=='_')
if(n && *n++=='_')
if(*n++=='p' && *n++=='_')
{
switch(*n++)
{
case 'o':
if(*n++=='i' && *n++=='d' && ! *n)
return PyString_FromStringAndSize(self->oid, 8);
if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
break;
case 'j':
if(*n++=='a' && *n++=='r' && ! *n)
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
break;
case 'c':
if(strcmp(n,"hanged")==0)
......@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE);
}
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);
}
if(! (*name++=='_' && *name++=='_' &&
if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0)))
{
......@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name)
{
char *s;
char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro);
if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
}
static int
......@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{
if (! v) return bad_delattr();
if (PyString_Check(v) && PyString_GET_SIZE(v)==8)
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
Py_XINCREF(v);
ASSIGN(self->oid, v);
return 0;
}
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{
Py_XINCREF(v);
ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0;
}
if(strcmp(name+3,"changed")==0)
if(name[3]=='s' && strcmp(name+4,"erial")==0)
{
if (! v) return bad_delattr();
if (v==Py_None)
if (v)
{
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);
return 0;
......@@ -585,8 +617,15 @@ void
initcPersistence()
{
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,
"",
(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.
......@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \
char oid[8]; \
PyObject *oid; \
char serial[8]; \
unsigned short atime; \
signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
......@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_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)
#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 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
static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
int position;
int cache_size;
int cache_age;
......@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key);
}
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE)
if (dt &&
(! 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;
......@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
};
static ccobject *
newccobject(int cache_size, int cache_age)
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New())
{
self->jar=jar;
Py_INCREF(jar);
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
......@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self);
}
......@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r;
}
static PyExtensionClass *Persistent=0;
static int
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);
}
......@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args)
{
int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(cache_size,cache_age);
PyObject *jar;
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[] = {
......@@ -459,10 +479,20 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.16 $";
char *rev="$Revision: 1.17 $";
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, "",
(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
......@@ -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"
#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(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
static PyObject *debug_log=0;
......@@ -35,8 +38,8 @@ call_debug(char *event, cPersistentObject *self)
/*
printf("%s %p\n",event,self->ob_type->tp_name);
*/
r=PyObject_CallFunction(debug_log,"s(ss#i)",event,
self->ob_type->tp_name, self->oid, 8,
r=PyObject_CallFunction(debug_log,"s(sOi)",event,
self->ob_type->tp_name, self->oid,
self->state);
Py_XDECREF(r);
}
......@@ -48,6 +51,7 @@ init_strings()
#define INIT_STRING(S) py_ ## S = PyString_FromString(#S)
INIT_STRING(keys);
INIT_STRING(setstate);
INIT_STRING(timeTime);
INIT_STRING(__dict__);
#undef INIT_STRING
}
......@@ -201,14 +205,16 @@ static PyObject *
Per___changed__(cPersistentObject *self, PyObject *args)
{
PyObject *v=0;
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,
"Only true arguments are allowed.");
return NULL;
if (changed(self) < 0) return NULL;
}
if (changed(self) < 0) return NULL;
else if (self->state >= 0) self->state=cPersistent_UPTODATE_STATE;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -368,35 +374,30 @@ Per_dealloc(self)
PyMem_DEL(self);
}
static PyObject *
orNothing(PyObject *v)
{
if (! v) v=Py_None;
Py_INCREF(v);
return v;
}
static PyObject *
Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
PyObject *(*getattrf)(PyObject *, PyObject*))
{
char *n=name;
if(*n++=='_')
if(n && *n++=='_')
if(*n++=='p' && *n++=='_')
{
switch(*n++)
{
case 'o':
if(*n++=='i' && *n++=='d' && ! *n)
return PyString_FromStringAndSize(self->oid, 8);
if(*n++=='i' && *n++=='d' && ! *n) return orNothing(self->oid);
break;
case 'j':
if(*n++=='a' && *n++=='r' && ! *n)
{
if(self->jar)
{
Py_INCREF(self->jar);
return self->jar;
}
else
{
Py_INCREF(Py_None);
return Py_None;
}
}
if(*n++=='a' && *n++=='r' && ! *n) return orNothing(self->jar);
break;
case 'c':
if(strcmp(n,"hanged")==0)
......@@ -410,11 +411,32 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
cPersistent_CHANGED_STATE);
}
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);
}
if(! (*name++=='_' && *name++=='_' &&
if(! (name && *name++=='_' && *name++=='_' &&
(strcmp(name,"dict__")==0 || strcmp(name,"class__")==0
|| strcmp(name, "of__")==0)))
{
......@@ -429,10 +451,11 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
static PyObject*
Per_getattro(cPersistentObject *self, PyObject *name)
{
char *s;
char *s=NULL;
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self,name,s, PyExtensionClassCAPI->getattro);
if (PyString_Check(name))
UNLESS(s=PyString_AsString(name)) return NULL;
return Per_getattr(self, name, s, PyExtensionClassCAPI->getattro);
}
static int
......@@ -456,27 +479,36 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if(name[3]=='o' && name[4]=='i' && name[5]=='d' && ! name[6])
{
if (! v) return bad_delattr();
if (PyString_Check(v) && PyString_GET_SIZE(v)==8)
memcpy(self->oid, PyString_AS_STRING(v), 8);
else
{
PyErr_SetString(PyExc_AttributeError,
"_p_oid must be an 8-character string");
return -1;
}
Py_XINCREF(v);
ASSIGN(self->oid, v);
return 0;
}
if(name[3]=='j' && name[4]=='a' && name[5]=='r' && ! name[6])
{
Py_XINCREF(v);
ASSIGN(self->jar, v);
Py_XINCREF(self->jar);
return 0;
}
if(strcmp(name+3,"changed")==0)
if(name[3]=='s' && strcmp(name+4,"erial")==0)
{
if (! v) return bad_delattr();
if (v==Py_None)
if (v)
{
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);
return 0;
......@@ -585,8 +617,15 @@ void
initcPersistence()
{
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,
"",
(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.
......@@ -15,9 +15,11 @@
#define cPersistent_HEAD PyObject_HEAD \
PyObject *jar; \
char oid[8]; \
PyObject *oid; \
char serial[8]; \
unsigned short atime; \
signed char state; \
unsigned char reserved; \
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
......@@ -43,6 +45,8 @@ typedef struct {
static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......@@ -57,6 +61,10 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
((O)->state==cPersistent_STICKY_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)
#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 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
static PyObject *py_reload, *py__p_jar, *py__p_deactivate;
/* Declarations for objects of type cCache */
typedef struct {
PyObject_HEAD
PyObject *data;
PyObject *jar;
int position;
int cache_size;
int cache_age;
......@@ -65,8 +63,11 @@ gc_item(ccobject *self, PyObject *key, PyObject *v, long now, int dt)
return PyDict_DelItem(self->data, key);
}
if (dt && v->ob_type->tp_basicsize >= sizeof(cPersistentObject) &&
((cPersistentObject*)v)->state==cPersistent_UPTODATE_STATE)
if (dt &&
(! 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;
......@@ -281,13 +282,15 @@ static struct PyMethodDef cc_methods[] = {
};
static ccobject *
newccobject(int cache_size, int cache_age)
newccobject(PyObject *jar, int cache_size, int cache_age)
{
ccobject *self;
UNLESS(self = PyObject_NEW(ccobject, &Cctype)) return NULL;
if(self->data=PyDict_New())
{
self->jar=jar;
Py_INCREF(jar);
self->position=0;
self->cache_size=cache_size;
self->cache_age=cache_age < 1 ? 1 : cache_age;
......@@ -312,6 +315,7 @@ static void
cc_dealloc(ccobject *self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->jar);
PyMem_DEL(self);
}
......@@ -404,10 +408,24 @@ cc_subscript(ccobject *self, PyObject *key)
return r;
}
static PyExtensionClass *Persistent=0;
static int
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);
}
......@@ -446,8 +464,10 @@ static PyObject *
cCM_new(PyObject *self, PyObject *args)
{
int cache_size=100, cache_age=1000;
UNLESS(PyArg_ParseTuple(args, "|ii", &cache_size, &cache_age)) return NULL;
return (PyObject*)newccobject(cache_size,cache_age);
PyObject *jar;
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[] = {
......@@ -459,10 +479,20 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.16 $";
char *rev="$Revision: 1.17 $";
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, "",
(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