Commit 724c428b authored by Jim Fulton's avatar Jim Fulton

many changes resulting from debugging

parent 97005d8e
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.27 1999/05/10 23:15:56 jim Exp $";
static char *what_string = "$Id: cPersistence.c,v 1.28 1999/05/12 15:55:44 jim Exp $";
#include <string.h>
#include "cPersistence.h"
......@@ -484,6 +484,8 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
if(strcmp(n,"elf")==0)
return orNothing(OBJECT(self));
break;
case 'm':
if(strcmp(n,"time")==0)
......@@ -581,6 +583,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
if (! v || v==Py_None)
{
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
self->state=cPersistent_GHOST_STATE;
return 0;
}
if (PyObject_IsTrue(v)) return changed(self);
......@@ -635,7 +638,7 @@ static PyExtensionClass Pertype = {
/* Space for future expansion */
0L,0L,"",
METHOD_CHAIN(Per_methods),
EXTENSIONCLASS_BASICNEW_FLAG,
EXTENSIONCLASS_BASICNEW_FLAG | PERSISTENT_TYPE_FLAG,
};
/* End of code for Persistent objects */
......@@ -687,7 +690,7 @@ void
initcPersistence()
{
PyObject *m, *d;
char *rev="$Revision: 1.27 $";
char *rev="$Revision: 1.28 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
......
......@@ -123,6 +123,8 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PERSISTENT_TYPE_FLAG EXTENSIONCLASS_USER_FLAG8
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPickleCache.c,v 1.18 1999/05/10 23:15:57 jim Exp $";
static char *what_string = "$Id: cPickleCache.c,v 1.19 1999/05/12 15:55:44 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -492,16 +492,19 @@ 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)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
&&
(((PyExtensionClass*)(v->ob_type))->class_flags
& PERSISTENT_TYPE_FLAG)
&&
(v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
)
)
return PyDict_SetItem(self->data, key, v);
......@@ -563,20 +566,12 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.18 $";
char *rev="$Revision: 1.19 $";
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);
......
......@@ -84,14 +84,17 @@
##############################################################################
"""Database connection support
$Id: Connection.py,v 1.4 1999/05/10 23:15:55 jim Exp $"""
__version__='$Revision: 1.4 $'[11:-2]
$Id: Connection.py,v 1.5 1999/05/12 15:55:43 jim Exp $"""
__version__='$Revision: 1.5 $'[11:-2]
from cPickleCache import PickleCache
from bpthread import allocate_lock
from POSException import ConflictError
from cStringIO import StringIO
from cPickle import Unpickler, Pickler
from ExtensionClass import Base
ExtensionKlass=Base.__class__
class HelperClass: pass
ClassType=type(HelperClass)
......@@ -139,11 +142,17 @@ class Connection:
object = unpickler.load()
klass, args = object
if type(klass) is tt:
module, name = klass
klass=self._db._classFactory(self, module, name)
if (args is None or
not args and not hasattr(klass,'__getinitargs__')):
object=klass.__basicnew__()
else:
object=apply(klass,args)
if klass is not ExtensionKlass:
object.__dict__.clear()
object._p_oid=oid
......@@ -167,19 +176,27 @@ 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 tt:
module, name = klass
try: klass=self._db._classFactory(self, module, name)
except:
# Eek, we couldn't get the class. Hm.
# Maybe their's more current data in the
# object's actual record!
return self[oid]
object=klass.__basicnew__()
object._p_oid=oid
object._p_jar=self
object._p_changed=None
cache[oid]=object
return object
if type(oid) is st: oid=atoi(oid)
return object
if cache.has_key(oid): return cache[oid]
object=cache[oid]=self[oid]
return object
return self[oid]
def _planToStore(self,object,stackp):
oid=object._p_oid
......@@ -188,8 +205,10 @@ class Connection:
object._p_jar=self
object._p_oid=oid
stackp(object)
elif object._p_changed:
stackp(object)
return oid
def _setDB(self, odb=None):
......@@ -220,6 +239,7 @@ class Connection:
stackup=stack.append
topoid=plan(object,stackup)
version=self._version
if stack:
# Create a special persistent_id that passes T and the subobject
# stack along:
......@@ -235,8 +255,17 @@ class Connection:
object._p_oid=oid
stackup(object)
if hasattr(object.__class__, '__getinitargs__'): return oid
return oid, object.__class__
klass=object.__class__
if klass is ExtensionKlass: return oid
if hasattr(klass, '__getinitargs__'): return oid
try: module=klass.__module__
except: module=''
if module: klass=module, klass.__name__
return oid, klass
file=StringIO()
seek=file.seek
......@@ -252,23 +281,42 @@ class Connection:
object=stack[-1]
del stack[-1]
oid=object._p_oid
serial=object._p_serial
try: serial=object._p_serial
except: serial='\0'*8
if self._invalidated.has_key(oid): raise ConflictError, oid
cls = object.__class__
if hasattr(cls, '__getinitargs__'):
klass = object.__class__
if klass is ExtensionKlass:
# Ye Ha!
dict={}
dict.update(object.__dict__)
del dict['_p_jar']
args=object.__name__, object.__bases__, dict
state=None
else:
if hasattr(klass, '__getinitargs__'):
args = object.__getinitargs__()
len(args) # XXX Assert it's a sequence
else:
args = None # New no-constructor protocol!
try: module=klass.__module__
except: module=''
if module: klass=module, klass.__name__
state=object.__getstate__()
seek(0)
clear_memo()
dump((cls,args))
state=object.__getstate__()
dump((klass,args))
dump(state)
p=file()
object._p_serial=dbstore(oid,serial,p,version,transaction)
object._p_changed=0
cache[oid]=object
try: cache[oid]=object
except:
# Dang, I bet its wrapped:
if hasattr(object, 'aq_base'):
cache[oid]=object.aq_base
return topoid
......
......@@ -84,8 +84,8 @@
##############################################################################
"""Database objects
$Id: DB.py,v 1.4 1999/05/10 23:15:55 jim Exp $"""
__version__='$Revision: 1.4 $'[11:-2]
$Id: DB.py,v 1.5 1999/05/12 15:55:43 jim Exp $"""
__version__='$Revision: 1.5 $'[11:-2]
import cPickle, cStringIO, sys
from Connection import Connection
......@@ -148,7 +148,8 @@ class DB:
# Pass through methods:
for m in ('history', 'modifiedInVersion',
'supportsUndo', 'supportsVersions',
'undo', 'undoLog', 'versionEmpty'):
'undo', 'undoLog',
'versionEmpty', 'versions'):
setattr(self, m, getattr(storage, m))
......@@ -164,6 +165,11 @@ class DB:
else: m=None
return m
def _classFactory(self, connection, location, name,
_silly=('__doc__',), _globals={}):
return getattr(__import__(location, _globals, _globals, _silly),
name)
def _closeConnection(self, connection):
"""Return a connection to the pool"""
self._a()
......@@ -270,10 +276,21 @@ class DB:
def exportFile(self, oid, file=None):
raise 'Not yet implemented'
def getCacheDeactivateAfter(self): return self._cache_deactivate_after
def getCacheSize(self): return self._cache_size
def getName(self): return self._storage.getName()
def getPoolSize(self): return self._pool_size
def getSize(self): return self._storage.getSize()
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
def importFile(self, file):
raise 'Not yet implemented'
......@@ -369,7 +386,7 @@ class DB:
if not pool:
c=None
if version:
if self._version_pool_size < len(allocated) or force:
if self._version_pool_size > len(allocated) or force:
c=Connection(
storage=self._storage,
version=version,
......@@ -417,20 +434,16 @@ class DB:
def setCacheDeactivateAfter(self, v): self._cache_deactivate_after=v
def setCacheSize(self, v): self._cache_size=v
def setClassFactory(self, factory):
self._classFactory=factory
def setPoolSize(self, v): self._pool_size=v
def setVersionCacheDeactivateAfter(self, v):
self._version_cache_deactivate_after=v
def setVersionCacheSize(self, v): self._version_cache_size=v
def setVersionPoolSize(self, v): self._version_pool_size=v
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 getVersionCacheSize(self): return self._version_cache_size
def getVersionPoolSize(self): return self._version_pool_size
def cacheStatistics(self): return () # :(
def versionEmpty(self, version):
......
......@@ -151,7 +151,7 @@ Also, the object ids time stamps are big-endian, so comparisons
are meaningful.
"""
__version__='$Revision: 1.4 $'[11:-2]
__version__='$Revision: 1.5 $'[11:-2]
import struct, time, os, bpthread
now=time.time
......@@ -159,6 +159,7 @@ from struct import pack, unpack
from cPickle import dumps
import POSException
from TimeStamp import TimeStamp
from lock_file import lock_file
t32 = 1L << 32
......@@ -199,7 +200,7 @@ def error(log, message, *data):
def panic(log, message, *data):
message=message%data
log("%s ERROR: %s\n" % (packed_version, message))
raise CorruptedTransactionRecordError, message
raise CorruptedTransactionError, message
class FileStorageError: pass
......@@ -238,11 +239,12 @@ class FileStorage:
self.__name__=file_name
self._tfile=open(file_name+'.tmp','w+b')
index, vindex, tindex = self._newIndexes()
index, vindex, tindex, tvindex = self._newIndexes()
self._index=index
self._vindex=vindex
self._tindex=tindex
self._tvindex=tvindex
self._indexpos=index.get
self._vindexpos=vindex.get
self._tappend=tindex.append
......@@ -268,6 +270,7 @@ class FileStorage:
if os.path.exists(file_name):
file=open(file_name, read_only and 'rb' or 'r+b')
if not read_only: lock_file(file)
else:
if read_only:
raise ValueError, "can\'t create a read-only file"
......@@ -286,7 +289,7 @@ class FileStorage:
def __len__(self): return len(self._index)
def _newIndexes(self): return {}, {}, []
def _newIndexes(self): return {}, {}, [], {}
def abortVersion(self, version, transaction):
if transaction is not self._transaction:
......@@ -395,12 +398,12 @@ class FileStorage:
(read(8) # skip past version link
and version != read(vlen))
):
return _loadBack(file, oid, u64(pnv))
return _loadBack(file, oid, pnv)
# If we get here, then either this was not a version record,
# or we've already read past the version data!
if plen != z64: return read(u64(plen)), serial
return _loadBack(file, oid, u64(pnv))
return _loadBack(file, oid, pnv)
finally: self._r()
def modifiedInVersion(self, oid):
......@@ -408,13 +411,14 @@ class FileStorage:
try:
pos=self._index[oid]
file=self._file
file.seek(pos)
seek=file.seek
seek(pos)
doid,serial,prev,tloc,vlen = unpack(">8s8s8s8sH", file.read(34))
if doid != oid:
raise CorruptedDataError, h
if vlen:
seek(16,1)
return read(vlen)
seek(24,1) # skip plen, pnv, and pv
return file.read(vlen)
return ''
finally: self._r()
......@@ -449,10 +453,10 @@ class FileStorage:
if old:
file=self._file
file.seek(old)
h=file.read(42)
read=file.read
h=read(42)
doid,oserial,sprev,stloc,vlen,splen = unpack(">8s8s8s8sH8s", h)
if doid != oid: raise CorruptedDataError, h
if serial != oserial: raise POSException.ConflictError
if vlen:
pnv=read(8) # non-version data pointer
if (len(version) != vlen or
......@@ -461,10 +465,13 @@ class FileStorage:
):
raise POSException.VersionLockError, oid
if serial != oserial: raise POSException.ConflictError
tfile=self._tfile
write=tfile.write
self._tappend(oid, tfile.tell())
pos=self._pos
here=tfile.tell()+pos+self._thl
self._tappend(oid, here)
serial=self._serial
write(pack(">8s8s8s8sH8s",
oid,serial,p64(old),p64(pos),
......@@ -475,10 +482,12 @@ class FileStorage:
if pnv: write(pnv)
else: write(p64(old))
# Link to last record for this version:
vindex=self._vindex
write(p64(vindex[version]))
vindex[version]=pos
tvindex=self._tvindex
pv=tvindex.get(version, 0) or self._vindexpos(version, 0)
write(p64(pv))
tvindex[version]=here
write(version)
write(data)
return serial
......@@ -506,11 +515,29 @@ class FileStorage:
self._a()
self._transaction=transaction
del self._tindex[:] # Just to be sure!
self._tvindex.clear() # ''
self._tfile.seek(0)
t=time.time()
t=apply(TimeStamp,(time.gmtime(t)[:5]+(t%60,)))
self._ts=t=t.laterThan(self._ts)
self._serial=`t`
user=transaction.user
desc=transaction.description
ext=transaction._extension
if ext: ext=dumps(ext,1)
else: ext=""
# Ugh, we have to record the transaction header length
# so that we can get version pointers right.
self._thl=33+len(user)+len(desc)+len(ext)
# And we have to save the data used to compute the
# header length. It's unlikely that this stuff would
# change, but if it did, it would be a disaster.
self._ude=user, desc, ext
finally: self._r()
def tpc_finish(self, transaction, f=None):
......@@ -524,13 +551,10 @@ class FileStorage:
dlen=tfile.tell()
tfile.seek(0)
id=self._serial
user=transaction.user
desc=transaction.description
ext=transaction._extension
if ext: ext=dumps(ext,1)
else: ext=""
user, desc, ext = self._ude
self._ude=None
tlen=33+len(user)+len(desc)+len(ext)
tlen=self._thl
pos=self._pos
file.seek(pos)
stpos=p64(self._tpos)
......@@ -551,11 +575,15 @@ class FileStorage:
self._tpos=pos
self._pos=pos+tl+8
tindex=self._tindex
index=self._index
dpos=pos+tlen
for oid, pos in self._tindex: index[oid]=pos+dpos
for oid, pos in tindex: index[oid]=pos
del tindex[:]
tvindex=self._tvindex
self._vindex.update(tvindex)
tvindex.clear()
del self._tindex[:]
self._transaction=None
self._cr()
finally: self._r()
......@@ -571,6 +599,10 @@ class FileStorage:
def versionEmpty(self, version):
return not self._vindex.has_key(version)
def versions(self, max=None):
if max: return self._vindex.keys()[:max]
return self._vindex.keys()
def read_index(file, name, index, vindex, tindex, stop='\377'*8,
log=lambda s: None):
......@@ -677,7 +709,7 @@ def read_index(file, name, index, vindex, tindex, stop='\377'*8,
tappend((oid,pos))
if vlen:
dlen=vlen+16
dlen=dlen+16
seek(8,1)
pv=u64(read(8))
version=read(vlen)
......@@ -716,16 +748,19 @@ def read_index(file, name, index, vindex, tindex, stop='\377'*8,
def _loadBack(file, oid, back):
seek=file.seek
read=file.read
while 1:
old=unpack(">i",back)[0]
old=u64(back)
if not old: raise KeyError, oid
file.seek(old)
h=file.read(42)
seek(old)
h=read(42)
doid,serial,prev,tloc,vlen,plen = unpack(">8s8s8s8sH8s", h)
if doid != oid or vlen:
panic(lambda x: None,
"%s version record back pointer points to "
"invalid record as %s", name, back)
if plen: return read(plen), serial
back=read(4) # We got a back pointer!
if plen: return read(u64(plen)), serial
back=read(8) # We got a back pointer!
*shared*
cPersistence cPersistence.c -I../../Components/ExtensionClass
cPickleCache cPickleCache.c -I../../Components/ExtensionClass
TimeStamp TimeStamp.c -DUSE_EXTENSION_CLASS
TimeStamp TimeStamp.c -I../../Components/ExtensionClass -DUSE_EXTENSION_CLASS
......@@ -84,8 +84,8 @@
##############################################################################
"""Transaction management
$Id: Transaction.py,v 1.5 1999/05/10 23:15:56 jim Exp $"""
__version__='$Revision: 1.5 $'[11:-2]
$Id: Transaction.py,v 1.6 1999/05/12 15:55:44 jim Exp $"""
__version__='$Revision: 1.6 $'[11:-2]
import time, sys, struct
from struct import pack
......@@ -130,7 +130,7 @@ class Transaction:
This aborts any transaction in progres.
'''
if self._objects: self._abort(0)
if self._objects: self.abort(0)
self.__init__()
if info:
info=split(info,'\t')
......
......@@ -87,7 +87,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.3 $'[11:-2]
__version__='$Revision: 1.4 $'[11:-2]
StringType=type('')
class ZApplicationWrapper:
......@@ -137,6 +139,8 @@ class ZApplicationWrapper:
if connection is None:
connection=db.open()
elif type(connection) is StringType:
connection=db.open(connection)
return connection.root()[aname]
......
......@@ -83,7 +83,7 @@
#
##############################################################################
import sys, ExtensionClass, TimeStamp, cPersistence, Persistence
import cStringIO, cPickle
# This is lame. Don't look. :(
sys.modules['cPersistence']=cPersistence
......
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.27 1999/05/10 23:15:56 jim Exp $";
static char *what_string = "$Id: cPersistence.c,v 1.28 1999/05/12 15:55:44 jim Exp $";
#include <string.h>
#include "cPersistence.h"
......@@ -484,6 +484,8 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
if(strcmp(n,"elf")==0)
return orNothing(OBJECT(self));
break;
case 'm':
if(strcmp(n,"time")==0)
......@@ -581,6 +583,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
if (! v || v==Py_None)
{
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
self->state=cPersistent_GHOST_STATE;
return 0;
}
if (PyObject_IsTrue(v)) return changed(self);
......@@ -635,7 +638,7 @@ static PyExtensionClass Pertype = {
/* Space for future expansion */
0L,0L,"",
METHOD_CHAIN(Per_methods),
EXTENSIONCLASS_BASICNEW_FLAG,
EXTENSIONCLASS_BASICNEW_FLAG | PERSISTENT_TYPE_FLAG,
};
/* End of code for Persistent objects */
......@@ -687,7 +690,7 @@ void
initcPersistence()
{
PyObject *m, *d;
char *rev="$Revision: 1.27 $";
char *rev="$Revision: 1.28 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
......
......@@ -123,6 +123,8 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PERSISTENT_TYPE_FLAG EXTENSIONCLASS_USER_FLAG8
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPickleCache.c,v 1.18 1999/05/10 23:15:57 jim Exp $";
static char *what_string = "$Id: cPickleCache.c,v 1.19 1999/05/12 15:55:44 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -492,16 +492,19 @@ 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)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
&&
(((PyExtensionClass*)(v->ob_type))->class_flags
& PERSISTENT_TYPE_FLAG)
&&
(v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
)
)
return PyDict_SetItem(self->data, key, v);
......@@ -563,20 +566,12 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.18 $";
char *rev="$Revision: 1.19 $";
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);
......
##############################################################################
#
# Zope Public License (ZPL) Version 1.0
# -------------------------------------
#
# Copyright (c) Digital Creations. All rights reserved.
#
# This license has been certified as Open Source(tm).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions in source code must retain the above copyright
# notice, this list of conditions, and the following disclaimer.
#
# 2. 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.
#
# 3. Digital Creations requests that attribution be given to Zope
# in any manner possible. Zope includes a "Powered by Zope"
# button that is installed by default. While it is not a license
# violation to remove this button, it is requested that the
# attribution remain. A significant investment has been put
# into Zope, and this effort will continue if the Zope community
# continues to grow. This is one way to assure that growth.
#
# 4. All advertising materials and documentation mentioning
# features derived from or use of this software must display
# the following acknowledgement:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# In the event that the product being advertised includes an
# intact Zope distribution (with copyright and license included)
# then this clause is waived.
#
# 5. Names associated with Zope or Digital Creations must not be used to
# endorse or promote products derived from this software without
# prior written permission from Digital Creations.
#
# 6. Modified redistributions of any form whatsoever must retain
# the following acknowledgment:
#
# "This product includes software developed by Digital Creations
# for use in the Z Object Publishing Environment
# (http://www.zope.org/)."
#
# Intact (re-)distributions of any official Zope release do not
# require an external acknowledgement.
#
# 7. Modifications are encouraged but must be packaged separately as
# patches to official Zope releases. Distributions that do not
# clearly separate the patches from the original work must be clearly
# labeled as unofficial distributions. Modifications which do not
# carry the name Zope may be packaged in any form, as long as they
# conform to all of the clauses above.
#
#
# Disclaimer
#
# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
# EXPRESSED 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 ITS
# 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.
#
#
# This software consists of contributions made by Digital Creations and
# many individuals on behalf of Digital Creations. Specific
# attributions are listed in the accompanying credits file.
#
##############################################################################
import POSException
# Try to create a function that creates Unix file locks. On windows
# this will fail.
try:
import fcntl, FCNTL
lock_file_FLAG=FCNTL.LOCK_EX|FCNTL.LOCK_NB
def lock_file(file, error=POSException.StorageSystemError):
try: un=file.fileno()
except: return # don't care if not a real file
try: fcntl.flock(un,lock_file_FLAG)
except:
raise error, (
"Could not lock the database file. There must be\n"
"another process that has opened the file.\n"
"<p>")
except:
# Try windows-specific code:
try:
from winlock import LockFile
def lock_file(file, error=POSException.StorageSystemError):
try: un=file.fileno()
except: return # don't care if not a real file
try: LockFile(un,0,0,1,0) # just lock the first byte, who cares
except:
raise error, (
"Could not lock the database file. There must be\n"
"another process that has opened the file.\n"
"<p>")
except:
def lock_file(file, error=None): pass
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPersistence.c,v 1.27 1999/05/10 23:15:56 jim Exp $";
static char *what_string = "$Id: cPersistence.c,v 1.28 1999/05/12 15:55:44 jim Exp $";
#include <string.h>
#include "cPersistence.h"
......@@ -484,6 +484,8 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
case 's':
if(strcmp(n,"erial")==0)
return PyString_FromStringAndSize(self->serial, 8);
if(strcmp(n,"elf")==0)
return orNothing(OBJECT(self));
break;
case 'm':
if(strcmp(n,"time")==0)
......@@ -581,6 +583,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
if (! v || v==Py_None)
{
if (Per__p_deactivate(self, NULL)) Py_DECREF(Py_None);
self->state=cPersistent_GHOST_STATE;
return 0;
}
if (PyObject_IsTrue(v)) return changed(self);
......@@ -635,7 +638,7 @@ static PyExtensionClass Pertype = {
/* Space for future expansion */
0L,0L,"",
METHOD_CHAIN(Per_methods),
EXTENSIONCLASS_BASICNEW_FLAG,
EXTENSIONCLASS_BASICNEW_FLAG | PERSISTENT_TYPE_FLAG,
};
/* End of code for Persistent objects */
......@@ -687,7 +690,7 @@ void
initcPersistence()
{
PyObject *m, *d;
char *rev="$Revision: 1.27 $";
char *rev="$Revision: 1.28 $";
TimeStamp=PyString_FromString("TimeStamp");
if (! TimeStamp) return;
......
......@@ -123,6 +123,8 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define cPersistanceModuleName "cPersistence"
#define PERSISTENT_TYPE_FLAG EXTENSIONCLASS_USER_FLAG8
#define PER_USE_OR_RETURN(O,R) { \
if ((O)->state==cPersistent_GHOST_STATE && \
cPersistenceCAPI->setstate((PyObject*)(O)) < 0) \
......
......@@ -82,7 +82,7 @@
attributions are listed in the accompanying credits file.
****************************************************************************/
static char *what_string = "$Id: cPickleCache.c,v 1.18 1999/05/10 23:15:57 jim Exp $";
static char *what_string = "$Id: cPickleCache.c,v 1.19 1999/05/12 15:55:44 jim Exp $";
#define ASSIGN(V,E) {PyObject *__e; __e=(E); Py_XDECREF(V); (V)=__e;}
#define UNLESS(E) if(!(E))
......@@ -492,16 +492,19 @@ 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)
{
if (PyExtensionClass_Check(v) ||
(PyExtensionInstance_Check(v) &&
ExtensionClassSubclassInstance_Check(v, Persistent)
if (PyExtensionClass_Check(v)
||
(PyExtensionInstance_Check(v)
&&
(((PyExtensionClass*)(v->ob_type))->class_flags
& PERSISTENT_TYPE_FLAG)
&&
(v->ob_type->tp_basicsize >= sizeof(cPersistentObject))
)
)
return PyDict_SetItem(self->data, key, v);
......@@ -563,20 +566,12 @@ void
initcPickleCache()
{
PyObject *m, *d;
char *rev="$Revision: 1.18 $";
char *rev="$Revision: 1.19 $";
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);
......
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