Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZODB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Nicolas Wavrant
ZODB
Commits
226ee421
Commit
226ee421
authored
Mar 27, 2002
by
Toby Dickenson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merged toby-stiff-cache-branch and toby-unicode-branch
parent
87c6d4a6
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2669 additions
and
1429 deletions
+2669
-1429
src/BTrees/BTreeTemplate.c
src/BTrees/BTreeTemplate.c
+3
-3
src/BTrees/BucketTemplate.c
src/BTrees/BucketTemplate.c
+2
-2
src/Persistence/cPersistence.c
src/Persistence/cPersistence.c
+107
-12
src/Persistence/cPersistence.h
src/Persistence/cPersistence.h
+19
-5
src/Persistence/cPickleCache.c
src/Persistence/cPickleCache.c
+744
-454
src/ZODB/Connection.py
src/ZODB/Connection.py
+40
-7
src/ZODB/DB.py
src/ZODB/DB.py
+14
-4
src/ZODB/cPersistence.c
src/ZODB/cPersistence.c
+107
-12
src/ZODB/cPersistence.h
src/ZODB/cPersistence.h
+19
-5
src/ZODB/cPickleCache.c
src/ZODB/cPickleCache.c
+744
-454
src/persistent/cPersistence.c
src/persistent/cPersistence.c
+107
-12
src/persistent/cPersistence.h
src/persistent/cPersistence.h
+19
-5
src/persistent/cPickleCache.c
src/persistent/cPickleCache.c
+744
-454
No files found.
src/BTrees/BTreeTemplate.c
View file @
226ee421
...
...
@@ -12,7 +12,7 @@
****************************************************************************/
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.2
5 2002/03/08 18:33:01 jeremy
Exp $\n"
#define BTREETEMPLATE_C "$Id: BTreeTemplate.c,v 1.2
6 2002/03/27 10:14:01 htrd
Exp $\n"
/*
** _BTree_get
...
...
@@ -540,7 +540,7 @@ _BTree_clear(BTree *self)
if
(
self
->
firstbucket
)
{
ASSERT
(
self
->
firstbucket
->
ob_refcnt
>
1
,
ASSERT
(
self
->
firstbucket
->
ob_refcnt
>
0
,
"Invalid firstbucket pointer"
,
-
1
);
Py_DECREF
(
self
->
firstbucket
);
self
->
firstbucket
=
NULL
;
...
...
@@ -573,7 +573,7 @@ BTree__p_deactivate(BTree *self, PyObject *args)
if
(
self
->
state
==
cPersistent_UPTODATE_STATE
&&
self
->
jar
)
{
if
(
_BTree_clear
(
self
)
<
0
)
return
NULL
;
self
->
state
=
cPersistent_GHOST_STATE
;
PER_GHOSTIFY
(
self
)
;
}
Py_INCREF
(
Py_None
);
...
...
src/BTrees/BucketTemplate.c
View file @
226ee421
...
...
@@ -12,7 +12,7 @@
****************************************************************************/
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.2
8 2002/03/08 18:33:01 jeremy
Exp $\n"
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.2
9 2002/03/27 10:14:01 htrd
Exp $\n"
/*
** _bucket_get
...
...
@@ -809,7 +809,7 @@ bucket__p_deactivate(Bucket *self, PyObject *args)
if
(
self
->
state
==
cPersistent_UPTODATE_STATE
&&
self
->
jar
)
{
if
(
_bucket_clear
(
self
)
<
0
)
return
NULL
;
self
->
state
=
cPersistent_GHOST_STATE
;
PER_GHOSTIFY
(
self
)
;
}
Py_INCREF
(
Py_None
);
...
...
src/Persistence/cPersistence.c
View file @
226ee421
...
...
@@ -14,11 +14,21 @@
static
char
cPersistence_doc_string
[]
=
"Defines Persistent mixin class for persistent objects.
\n
"
"
\n
"
"$Id: cPersistence.c,v 1.5
0 2002/03/08 18:36:13 jeremy
Exp $
\n
"
;
"$Id: cPersistence.c,v 1.5
1 2002/03/27 10:14:04 htrd
Exp $
\n
"
;
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct
ccobject_head_struct
{
PyObject_HEAD
CPersistentRing
ring_home
;
int
non_ghost_count
;
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#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)
...
...
@@ -112,21 +122,82 @@ if(self->state < 0 && self->jar) \
{ \
PyObject *r; \
\
int *count = NON_GHOST_COUNT(self); \
if(count) \
{ \
(*count)++; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; \
Py_INCREF(self); \
} \
self->state=cPersistent_CHANGED_STATE; \
UNLESS(r=callmethod1(self->jar,py_setstate,(PyObject*)self)) \
{ \
self->state=cPersistent_GHOST_STATE;
\
ghostify(self);
\
return ER; \
} \
self->state=cPersistent_UPTODATE_STATE; \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
/****************************************************************************/
staticforward
PyExtensionClass
Pertype
;
static
void
accessed
(
cPersistentObject
*
self
)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
}
static
void
ghostify
(
cPersistentObject
*
self
)
{
int
*
count
;
count
=
NON_GHOST_COUNT
(
self
);
if
(
count
&&
(
self
->
state
>=
0
))
{
(
*
count
)
--
;
self
->
ring
.
next
->
prev
=
self
->
ring
.
prev
;
self
->
ring
.
prev
->
next
=
self
->
ring
.
next
;
self
->
ring
.
prev
=
NULL
;
self
->
ring
.
next
=
NULL
;
self
->
state
=
cPersistent_GHOST_STATE
;
Py_DECREF
(
self
);
}
else
{
self
->
state
=
cPersistent_GHOST_STATE
;
}
}
static
void
deallocated
(
cPersistentObject
*
self
)
{
if
(
self
->
state
>=
0
)
ghostify
(
self
);
if
(
self
->
cache
)
{
PyObject
*
v
=
PyObject_CallMethod
(
self
->
cache
,
"_oid_unreferenced"
,
"O"
,
self
->
oid
);
if
(
!
v
)
PyErr_Clear
();
/* and explode later */
Py_XDECREF
(
v
);
}
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
}
static
int
changed
(
cPersistentObject
*
self
)
{
...
...
@@ -185,7 +256,7 @@ Per___changed__(cPersistentObject *self, PyObject *args)
static
PyObject
*
Per__p_deactivate
(
cPersistentObject
*
self
,
PyObject
*
args
)
{
PyObject
*
dict
;
PyObject
*
dict
,
*
dict2
=
NULL
;
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"reinit"
,
self
);
...
...
@@ -197,13 +268,22 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if
(
self
->
state
==
cPersistent_UPTODATE_STATE
&&
self
->
jar
&&
HasInstDict
(
self
)
&&
(
dict
=
INSTANCE_DICT
(
self
)))
{
dict2
=
PyDict_Copy
(
dict
);
PyDict_Clear
(
dict
);
/* Note that we need to set to ghost state unless we are
called directly. Methods that override this need to
do the same! */
self
->
state
=
cPersistent_GHOST_STATE
;
ghostify
(
self
)
;
}
/* need to delay releasing the last reference on instance attributes
until after we have finished accounting for losing our state */
if
(
dict2
)
{
PyDict_Clear
(
dict2
);
Py_DECREF
(
dict2
);
}
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -333,8 +413,8 @@ Per_dealloc(cPersistentObject *self)
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"del"
,
self
);
#endif
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
deallocated
(
self
);
Py_XDECREF
(
self
->
cache
);
Py_DECREF
(
self
->
ob_type
);
PyObject_DEL
(
self
);
}
...
...
@@ -387,7 +467,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
if
(
self
->
serial
[
7
]
==
'\0'
&&
self
->
serial
[
6
]
==
'\0'
&&
self
->
serial
[
5
]
==
'\0'
&&
self
->
serial
[
4
]
==
'\0'
&&
...
...
@@ -419,7 +499,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
}
return
getattrf
((
PyObject
*
)
self
,
oname
);
...
...
@@ -466,6 +546,21 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if
(
name
[
3
]
==
'o'
&&
name
[
4
]
==
'i'
&&
name
[
5
]
==
'd'
&&
!
name
[
6
])
{
if
(
HOME
(
self
))
{
int
result
;
if
(
!
v
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not delete the oid of a cached object"
);
return
-
1
;
}
if
(
PyObject_Cmp
(
self
->
oid
,
v
,
&
result
)
<
0
)
return
-
1
;
if
(
result
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not change the oid of a cached object"
);
return
-
1
;
}
}
Py_XINCREF
(
v
);
ASSIGN
(
self
->
oid
,
v
);
return
0
;
...
...
@@ -509,7 +604,6 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
v
=
PyObject_GetAttr
(
OBJECT
(
self
),
py__p_deactivate
);
if
(
v
)
{
ASSIGN
(
v
,
PyObject_CallObject
(
v
,
NULL
));
}
if
(
v
)
{
Py_DECREF
(
v
);
}
self
->
state
=
cPersistent_GHOST_STATE
;
return
0
;
}
if
(
PyObject_IsTrue
(
v
))
return
changed
(
self
);
...
...
@@ -521,8 +615,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
-
1
);
/* Record access times */
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
if
((
!
(
*
name
==
'_'
&&
name
[
1
]
==
'v'
&&
name
[
2
]
==
'_'
))
&&
(
self
->
state
!=
cPersistent_CHANGED_STATE
&&
self
->
jar
)
...
...
@@ -680,9 +773,11 @@ truecPersistenceCAPI = {
(
getattrofunc
)
Per_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
Per_setattro
,
/*tp_setattr with object key*/
changed
,
accessed
,
ghostify
,
deallocated
,
(
intfunctionwithpythonarg
)
Per_setstate
,
(
pergetattr
)
Per_getattr
,
(
persetattr
)
_setattro
,
};
void
...
...
src/Persistence/cPersistence.h
View file @
226ee421
...
...
@@ -18,12 +18,21 @@
#include "ExtensionClass.h"
#include <time.h>
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid; char serial[8]; unsigned short atime; signed char state; unsigned char reserved;
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct
ccobject_head_struct
;
typedef
struct
CPersistentRing_struct
{
struct
CPersistentRing_struct
*
prev
;
struct
CPersistentRing_struct
*
next
;
}
CPersistentRing
;
typedef
struct
{
cPersistent_HEAD
}
cPersistentObject
;
...
...
@@ -36,6 +45,9 @@ typedef struct {
getattrofunc
getattro
;
setattrofunc
setattro
;
int
(
*
changed
)(
cPersistentObject
*
);
void
(
*
accessed
)(
cPersistentObject
*
);
void
(
*
ghostify
)(
cPersistentObject
*
);
void
(
*
deallocated
)(
cPersistentObject
*
);
int
(
*
setstate
)(
PyObject
*
);
pergetattr
pergetattro
;
persetattr
persetattro
;
...
...
@@ -59,11 +71,13 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define PER_CHANGED(O) (cPersistenceCAPI->changed((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((O)->state==cPersistent_STICKY_STATE && ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_GHOSTIFY(O) (cPersistenceCAPI->ghostify((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((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_PREVENT_DEACTIVATION(O) ((O)->state==cPersistent_UPTODATE_STATE && ((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O)
Py_XDECREF((O)->jar); Py_XDECREF((O)->oid);
#define PER_DEL(O)
(cPersistenceCAPI->deallocated((cPersistentObject*)(O)))
#define PER_USE(O) \
(((O)->state != cPersistent_GHOST_STATE \
...
...
@@ -71,7 +85,7 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
? (((O)->state==cPersistent_UPTODATE_STATE) \
? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
#define PER_ACCESSED(O)
((O)->atime=((long)(time(NULL)/3))%65536)
#define PER_ACCESSED(O)
(cPersistenceCAPI->accessed((cPersistentObject*)(O)))
#endif
...
...
src/Persistence/cPickleCache.c
View file @
226ee421
This diff is collapsed.
Click to expand it.
src/ZODB/Connection.py
View file @
226ee421
...
...
@@ -13,14 +13,14 @@
##############################################################################
"""Database connection support
$Id: Connection.py,v 1.6
3 2002/02/11 23:40:42 gvanrossum
Exp $"""
__version__
=
'$Revision: 1.6
3
$'
[
11
:
-
2
]
$Id: Connection.py,v 1.6
4 2002/03/27 10:14:03 htrd
Exp $"""
__version__
=
'$Revision: 1.6
4
$'
[
11
:
-
2
]
from
cPickleCache
import
PickleCache
from
cPickleCache
import
PickleCache
,
MUCH_RING_CHECKING
from
POSException
import
ConflictError
,
ReadConflictError
from
ExtensionClass
import
Base
import
ExportImport
,
TmpStore
from
zLOG
import
LOG
,
ERROR
,
BLATHER
from
zLOG
import
LOG
,
ERROR
,
BLATHER
,
WARNING
from
coptimizations
import
new_persistent_id
from
ConflictResolution
import
ResolvedSerial
...
...
@@ -32,6 +32,11 @@ from types import StringType, ClassType
global_code_timestamp
=
0
if
MUCH_RING_CHECKING
:
# To get rid of this warning, change the define inside cPickleCache.c and recompile.
LOG
(
'ZODB'
,
WARNING
,
'Using cPickleCache with low performance (but extra debugging checks)'
)
del
MUCH_RING_CHECKING
def
updateCodeTimestamp
():
'''
Called after changes are made to persistence-based classes.
...
...
@@ -65,12 +70,35 @@ class Connection(ExportImport.ExportImport):
"""Create a new Connection"""
self
.
_version
=
version
self
.
_cache
=
cache
=
PickleCache
(
self
,
cache_size
,
cache_deactivate_after
)
if
version
:
# Caches for versions end up empty if the version
# is not used for a while. Non-version caches
# keep their content indefinitely.
self
.
_cache
.
cache_drain_resistance
=
100
self
.
_incrgc
=
self
.
cacheGC
=
cache
.
incrgc
self
.
_invalidated
=
d
=
{}
self
.
_invalid
=
d
.
has_key
self
.
_committed
=
[]
self
.
_code_timestamp
=
global_code_timestamp
def
_cache_items
(
self
):
# find all items on the lru list
items
=
self
.
_cache
.
lru_items
()
# fine everything. some on the lru list, some not
everything
=
self
.
_cache
.
cache_data
# remove those items that are on the lru list
for
k
,
v
in
items
:
del
everything
[
k
]
# return a list of [ghosts....not recently used.....recently used]
return
everything
.
items
()
+
items
def
__repr__
(
self
):
if
self
.
_version
:
ver
=
' (in version %s)'
%
`self._version`
else
:
ver
=
''
return
'<Connection at %08x%s>'
%
(
id
(
self
),
ver
)
def
_breakcr
(
self
):
try
:
del
self
.
_cache
except
:
pass
...
...
@@ -414,9 +442,9 @@ class Connection(ExportImport.ExportImport):
for
oid
in
creating
:
o
=
cache_get
(
oid
,
None
)
if
o
is
not
None
:
del
cache
[
oid
]
del
o
.
_p_jar
del
o
.
_p_oid
del
cache
[
oid
]
#XXX
...
...
@@ -441,9 +469,14 @@ class Connection(ExportImport.ExportImport):
def
root
(
self
):
return
self
[
'
\
0
\
0
\
0
\
0
\
0
\
0
\
0
\
0
'
]
def
setstate
(
self
,
object
):
oid
=
object
.
_p_oid
if
self
.
_storage
is
None
:
msg
=
"Shouldn't load state for %s when the connection is closed"
%
`oid`
LOG
(
'ZODB'
,
ERROR
,
msg
)
raise
RuntimeError
(
msg
)
try
:
oid
=
object
.
_p_oid
p
,
serial
=
self
.
_storage
.
load
(
oid
,
self
.
_version
)
# XXX this is quite conservative!
...
...
src/ZODB/DB.py
View file @
226ee421
...
...
@@ -13,8 +13,8 @@
##############################################################################
"""Database objects
$Id: DB.py,v 1.
39 2002/02/11 23:40:42 gvanrossum
Exp $"""
__version__
=
'$Revision: 1.
39
$'
[
11
:
-
2
]
$Id: DB.py,v 1.
40 2002/03/27 10:14:04 htrd
Exp $"""
__version__
=
'$Revision: 1.
40
$'
[
11
:
-
2
]
import
cPickle
,
cStringIO
,
sys
,
POSException
,
UndoLogCompatible
from
Connection
import
Connection
...
...
@@ -177,7 +177,7 @@ class DB(UndoLogCompatible.UndoLogCompatible):
def
f
(
con
,
detail
=
detail
,
rc
=
sys
.
getrefcount
,
conn_no
=
conn_no
):
conn_no
[
0
]
=
conn_no
[
0
]
+
1
cn
=
conn_no
[
0
]
for
oid
,
ob
in
con
.
_cache
.
items
():
for
oid
,
ob
in
con
.
_cache
_
items
():
id
=
''
if
hasattr
(
ob
,
'__dict__'
):
d
=
ob
.
__dict__
...
...
@@ -224,11 +224,21 @@ class DB(UndoLogCompatible.UndoLogCompatible):
def
cacheSize
(
self
):
m
=
[
0
]
def
f
(
con
,
m
=
m
):
m
[
0
]
=
m
[
0
]
+
len
(
con
.
_cache
)
m
[
0
]
=
m
[
0
]
+
con
.
_cache
.
cache_non_ghost_count
self
.
_connectionMap
(
f
)
return
m
[
0
]
def
cacheDetailSize
(
self
):
m
=
[]
def
f
(
con
,
m
=
m
):
m
.
append
({
'connection'
:
repr
(
con
),
'ngsize'
:
con
.
_cache
.
cache_non_ghost_count
,
'size'
:
len
(
con
.
_cache
)})
self
.
_connectionMap
(
f
)
m
.
sort
()
return
m
def
close
(
self
):
self
.
_storage
.
close
()
def
commitVersion
(
self
,
source
,
destination
=
''
):
...
...
src/ZODB/cPersistence.c
View file @
226ee421
...
...
@@ -14,11 +14,21 @@
static
char
cPersistence_doc_string
[]
=
"Defines Persistent mixin class for persistent objects.
\n
"
"
\n
"
"$Id: cPersistence.c,v 1.5
0 2002/03/08 18:36:13 jeremy
Exp $
\n
"
;
"$Id: cPersistence.c,v 1.5
1 2002/03/27 10:14:04 htrd
Exp $
\n
"
;
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct
ccobject_head_struct
{
PyObject_HEAD
CPersistentRing
ring_home
;
int
non_ghost_count
;
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#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)
...
...
@@ -112,21 +122,82 @@ if(self->state < 0 && self->jar) \
{ \
PyObject *r; \
\
int *count = NON_GHOST_COUNT(self); \
if(count) \
{ \
(*count)++; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; \
Py_INCREF(self); \
} \
self->state=cPersistent_CHANGED_STATE; \
UNLESS(r=callmethod1(self->jar,py_setstate,(PyObject*)self)) \
{ \
self->state=cPersistent_GHOST_STATE;
\
ghostify(self);
\
return ER; \
} \
self->state=cPersistent_UPTODATE_STATE; \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
/****************************************************************************/
staticforward
PyExtensionClass
Pertype
;
static
void
accessed
(
cPersistentObject
*
self
)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
}
static
void
ghostify
(
cPersistentObject
*
self
)
{
int
*
count
;
count
=
NON_GHOST_COUNT
(
self
);
if
(
count
&&
(
self
->
state
>=
0
))
{
(
*
count
)
--
;
self
->
ring
.
next
->
prev
=
self
->
ring
.
prev
;
self
->
ring
.
prev
->
next
=
self
->
ring
.
next
;
self
->
ring
.
prev
=
NULL
;
self
->
ring
.
next
=
NULL
;
self
->
state
=
cPersistent_GHOST_STATE
;
Py_DECREF
(
self
);
}
else
{
self
->
state
=
cPersistent_GHOST_STATE
;
}
}
static
void
deallocated
(
cPersistentObject
*
self
)
{
if
(
self
->
state
>=
0
)
ghostify
(
self
);
if
(
self
->
cache
)
{
PyObject
*
v
=
PyObject_CallMethod
(
self
->
cache
,
"_oid_unreferenced"
,
"O"
,
self
->
oid
);
if
(
!
v
)
PyErr_Clear
();
/* and explode later */
Py_XDECREF
(
v
);
}
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
}
static
int
changed
(
cPersistentObject
*
self
)
{
...
...
@@ -185,7 +256,7 @@ Per___changed__(cPersistentObject *self, PyObject *args)
static
PyObject
*
Per__p_deactivate
(
cPersistentObject
*
self
,
PyObject
*
args
)
{
PyObject
*
dict
;
PyObject
*
dict
,
*
dict2
=
NULL
;
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"reinit"
,
self
);
...
...
@@ -197,13 +268,22 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if
(
self
->
state
==
cPersistent_UPTODATE_STATE
&&
self
->
jar
&&
HasInstDict
(
self
)
&&
(
dict
=
INSTANCE_DICT
(
self
)))
{
dict2
=
PyDict_Copy
(
dict
);
PyDict_Clear
(
dict
);
/* Note that we need to set to ghost state unless we are
called directly. Methods that override this need to
do the same! */
self
->
state
=
cPersistent_GHOST_STATE
;
ghostify
(
self
)
;
}
/* need to delay releasing the last reference on instance attributes
until after we have finished accounting for losing our state */
if
(
dict2
)
{
PyDict_Clear
(
dict2
);
Py_DECREF
(
dict2
);
}
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -333,8 +413,8 @@ Per_dealloc(cPersistentObject *self)
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"del"
,
self
);
#endif
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
deallocated
(
self
);
Py_XDECREF
(
self
->
cache
);
Py_DECREF
(
self
->
ob_type
);
PyObject_DEL
(
self
);
}
...
...
@@ -387,7 +467,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
if
(
self
->
serial
[
7
]
==
'\0'
&&
self
->
serial
[
6
]
==
'\0'
&&
self
->
serial
[
5
]
==
'\0'
&&
self
->
serial
[
4
]
==
'\0'
&&
...
...
@@ -419,7 +499,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
}
return
getattrf
((
PyObject
*
)
self
,
oname
);
...
...
@@ -466,6 +546,21 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if
(
name
[
3
]
==
'o'
&&
name
[
4
]
==
'i'
&&
name
[
5
]
==
'd'
&&
!
name
[
6
])
{
if
(
HOME
(
self
))
{
int
result
;
if
(
!
v
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not delete the oid of a cached object"
);
return
-
1
;
}
if
(
PyObject_Cmp
(
self
->
oid
,
v
,
&
result
)
<
0
)
return
-
1
;
if
(
result
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not change the oid of a cached object"
);
return
-
1
;
}
}
Py_XINCREF
(
v
);
ASSIGN
(
self
->
oid
,
v
);
return
0
;
...
...
@@ -509,7 +604,6 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
v
=
PyObject_GetAttr
(
OBJECT
(
self
),
py__p_deactivate
);
if
(
v
)
{
ASSIGN
(
v
,
PyObject_CallObject
(
v
,
NULL
));
}
if
(
v
)
{
Py_DECREF
(
v
);
}
self
->
state
=
cPersistent_GHOST_STATE
;
return
0
;
}
if
(
PyObject_IsTrue
(
v
))
return
changed
(
self
);
...
...
@@ -521,8 +615,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
-
1
);
/* Record access times */
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
if
((
!
(
*
name
==
'_'
&&
name
[
1
]
==
'v'
&&
name
[
2
]
==
'_'
))
&&
(
self
->
state
!=
cPersistent_CHANGED_STATE
&&
self
->
jar
)
...
...
@@ -680,9 +773,11 @@ truecPersistenceCAPI = {
(
getattrofunc
)
Per_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
Per_setattro
,
/*tp_setattr with object key*/
changed
,
accessed
,
ghostify
,
deallocated
,
(
intfunctionwithpythonarg
)
Per_setstate
,
(
pergetattr
)
Per_getattr
,
(
persetattr
)
_setattro
,
};
void
...
...
src/ZODB/cPersistence.h
View file @
226ee421
...
...
@@ -18,12 +18,21 @@
#include "ExtensionClass.h"
#include <time.h>
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid; char serial[8]; unsigned short atime; signed char state; unsigned char reserved;
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct
ccobject_head_struct
;
typedef
struct
CPersistentRing_struct
{
struct
CPersistentRing_struct
*
prev
;
struct
CPersistentRing_struct
*
next
;
}
CPersistentRing
;
typedef
struct
{
cPersistent_HEAD
}
cPersistentObject
;
...
...
@@ -36,6 +45,9 @@ typedef struct {
getattrofunc
getattro
;
setattrofunc
setattro
;
int
(
*
changed
)(
cPersistentObject
*
);
void
(
*
accessed
)(
cPersistentObject
*
);
void
(
*
ghostify
)(
cPersistentObject
*
);
void
(
*
deallocated
)(
cPersistentObject
*
);
int
(
*
setstate
)(
PyObject
*
);
pergetattr
pergetattro
;
persetattr
persetattro
;
...
...
@@ -59,11 +71,13 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define PER_CHANGED(O) (cPersistenceCAPI->changed((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((O)->state==cPersistent_STICKY_STATE && ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_GHOSTIFY(O) (cPersistenceCAPI->ghostify((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((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_PREVENT_DEACTIVATION(O) ((O)->state==cPersistent_UPTODATE_STATE && ((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O)
Py_XDECREF((O)->jar); Py_XDECREF((O)->oid);
#define PER_DEL(O)
(cPersistenceCAPI->deallocated((cPersistentObject*)(O)))
#define PER_USE(O) \
(((O)->state != cPersistent_GHOST_STATE \
...
...
@@ -71,7 +85,7 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
? (((O)->state==cPersistent_UPTODATE_STATE) \
? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
#define PER_ACCESSED(O)
((O)->atime=((long)(time(NULL)/3))%65536)
#define PER_ACCESSED(O)
(cPersistenceCAPI->accessed((cPersistentObject*)(O)))
#endif
...
...
src/ZODB/cPickleCache.c
View file @
226ee421
This diff is collapsed.
Click to expand it.
src/persistent/cPersistence.c
View file @
226ee421
...
...
@@ -14,11 +14,21 @@
static
char
cPersistence_doc_string
[]
=
"Defines Persistent mixin class for persistent objects.
\n
"
"
\n
"
"$Id: cPersistence.c,v 1.5
0 2002/03/08 18:36:13 jeremy
Exp $
\n
"
;
"$Id: cPersistence.c,v 1.5
1 2002/03/27 10:14:04 htrd
Exp $
\n
"
;
#include <string.h>
#include "cPersistence.h"
/* the layout of this struct is the same as the start of ccobject in cPickleCache.c */
struct
ccobject_head_struct
{
PyObject_HEAD
CPersistentRing
ring_home
;
int
non_ghost_count
;
};
#define HOME(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->ring_home)) )
#define NON_GHOST_COUNT(O) ((!((O)->cache))?(NULL): (&(((struct ccobject_head_struct *)((O)->cache))->non_ghost_count)) )
#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)
...
...
@@ -112,21 +122,82 @@ if(self->state < 0 && self->jar) \
{ \
PyObject *r; \
\
int *count = NON_GHOST_COUNT(self); \
if(count) \
{ \
(*count)++; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; \
Py_INCREF(self); \
} \
self->state=cPersistent_CHANGED_STATE; \
UNLESS(r=callmethod1(self->jar,py_setstate,(PyObject*)self)) \
{ \
self->state=cPersistent_GHOST_STATE;
\
ghostify(self);
\
return ER; \
} \
self->state=cPersistent_UPTODATE_STATE; \
Py_DECREF(r); \
}
#define KEEP_THIS_ONE_AROUND_FOR_A_WHILE(self) \
if(HOME(self) && self->state>=0) { \
self->ring.prev->next = self->ring.next; \
self->ring.next->prev = self->ring.prev; \
self->ring.next = HOME(self); \
self->ring.prev = HOME(self)->prev; \
HOME(self)->prev->next = &self->ring; \
HOME(self)->prev = &self->ring; }
/****************************************************************************/
staticforward
PyExtensionClass
Pertype
;
static
void
accessed
(
cPersistentObject
*
self
)
{
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
}
static
void
ghostify
(
cPersistentObject
*
self
)
{
int
*
count
;
count
=
NON_GHOST_COUNT
(
self
);
if
(
count
&&
(
self
->
state
>=
0
))
{
(
*
count
)
--
;
self
->
ring
.
next
->
prev
=
self
->
ring
.
prev
;
self
->
ring
.
prev
->
next
=
self
->
ring
.
next
;
self
->
ring
.
prev
=
NULL
;
self
->
ring
.
next
=
NULL
;
self
->
state
=
cPersistent_GHOST_STATE
;
Py_DECREF
(
self
);
}
else
{
self
->
state
=
cPersistent_GHOST_STATE
;
}
}
static
void
deallocated
(
cPersistentObject
*
self
)
{
if
(
self
->
state
>=
0
)
ghostify
(
self
);
if
(
self
->
cache
)
{
PyObject
*
v
=
PyObject_CallMethod
(
self
->
cache
,
"_oid_unreferenced"
,
"O"
,
self
->
oid
);
if
(
!
v
)
PyErr_Clear
();
/* and explode later */
Py_XDECREF
(
v
);
}
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
}
static
int
changed
(
cPersistentObject
*
self
)
{
...
...
@@ -185,7 +256,7 @@ Per___changed__(cPersistentObject *self, PyObject *args)
static
PyObject
*
Per__p_deactivate
(
cPersistentObject
*
self
,
PyObject
*
args
)
{
PyObject
*
dict
;
PyObject
*
dict
,
*
dict2
=
NULL
;
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"reinit"
,
self
);
...
...
@@ -197,13 +268,22 @@ Per__p_deactivate(cPersistentObject *self, PyObject *args)
if
(
self
->
state
==
cPersistent_UPTODATE_STATE
&&
self
->
jar
&&
HasInstDict
(
self
)
&&
(
dict
=
INSTANCE_DICT
(
self
)))
{
dict2
=
PyDict_Copy
(
dict
);
PyDict_Clear
(
dict
);
/* Note that we need to set to ghost state unless we are
called directly. Methods that override this need to
do the same! */
self
->
state
=
cPersistent_GHOST_STATE
;
ghostify
(
self
)
;
}
/* need to delay releasing the last reference on instance attributes
until after we have finished accounting for losing our state */
if
(
dict2
)
{
PyDict_Clear
(
dict2
);
Py_DECREF
(
dict2
);
}
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -333,8 +413,8 @@ Per_dealloc(cPersistentObject *self)
#ifdef DEBUG_LOG
if
(
idebug_log
<
0
)
call_debug
(
"del"
,
self
);
#endif
Py_XDECREF
(
self
->
jar
);
Py_XDECREF
(
self
->
oid
);
deallocated
(
self
);
Py_XDECREF
(
self
->
cache
);
Py_DECREF
(
self
->
ob_type
);
PyObject_DEL
(
self
);
}
...
...
@@ -387,7 +467,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
if
(
self
->
serial
[
7
]
==
'\0'
&&
self
->
serial
[
6
]
==
'\0'
&&
self
->
serial
[
5
]
==
'\0'
&&
self
->
serial
[
4
]
==
'\0'
&&
...
...
@@ -419,7 +499,7 @@ Per_getattr(cPersistentObject *self, PyObject *oname, char *name,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
NULL
);
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
)
;
}
return
getattrf
((
PyObject
*
)
self
,
oname
);
...
...
@@ -466,6 +546,21 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
if
(
name
[
3
]
==
'o'
&&
name
[
4
]
==
'i'
&&
name
[
5
]
==
'd'
&&
!
name
[
6
])
{
if
(
HOME
(
self
))
{
int
result
;
if
(
!
v
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not delete the oid of a cached object"
);
return
-
1
;
}
if
(
PyObject_Cmp
(
self
->
oid
,
v
,
&
result
)
<
0
)
return
-
1
;
if
(
result
)
{
PyErr_SetString
(
PyExc_ValueError
,
"can not change the oid of a cached object"
);
return
-
1
;
}
}
Py_XINCREF
(
v
);
ASSIGN
(
self
->
oid
,
v
);
return
0
;
...
...
@@ -509,7 +604,6 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
v
=
PyObject_GetAttr
(
OBJECT
(
self
),
py__p_deactivate
);
if
(
v
)
{
ASSIGN
(
v
,
PyObject_CallObject
(
v
,
NULL
));
}
if
(
v
)
{
Py_DECREF
(
v
);
}
self
->
state
=
cPersistent_GHOST_STATE
;
return
0
;
}
if
(
PyObject_IsTrue
(
v
))
return
changed
(
self
);
...
...
@@ -521,8 +615,7 @@ _setattro(cPersistentObject *self, PyObject *oname, PyObject *v,
{
UPDATE_STATE_IF_NECESSARY
(
self
,
-
1
);
/* Record access times */
self
->
atime
=
((
long
)(
time
(
NULL
)
/
3
))
%
65536
;
KEEP_THIS_ONE_AROUND_FOR_A_WHILE
(
self
);
if
((
!
(
*
name
==
'_'
&&
name
[
1
]
==
'v'
&&
name
[
2
]
==
'_'
))
&&
(
self
->
state
!=
cPersistent_CHANGED_STATE
&&
self
->
jar
)
...
...
@@ -680,9 +773,11 @@ truecPersistenceCAPI = {
(
getattrofunc
)
Per_getattro
,
/*tp_getattr with object key*/
(
setattrofunc
)
Per_setattro
,
/*tp_setattr with object key*/
changed
,
accessed
,
ghostify
,
deallocated
,
(
intfunctionwithpythonarg
)
Per_setstate
,
(
pergetattr
)
Per_getattr
,
(
persetattr
)
_setattro
,
};
void
...
...
src/persistent/cPersistence.h
View file @
226ee421
...
...
@@ -18,12 +18,21 @@
#include "ExtensionClass.h"
#include <time.h>
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid; char serial[8]; unsigned short atime; signed char state; unsigned char reserved;
#define cPersistent_HEAD PyObject_HEAD PyObject *jar, *oid, *cache; CPersistentRing ring; char serial[8]; signed char state; unsigned char reserved[3];
#define cPersistent_GHOST_STATE -1
#define cPersistent_UPTODATE_STATE 0
#define cPersistent_CHANGED_STATE 1
#define cPersistent_STICKY_STATE 2
struct
ccobject_head_struct
;
typedef
struct
CPersistentRing_struct
{
struct
CPersistentRing_struct
*
prev
;
struct
CPersistentRing_struct
*
next
;
}
CPersistentRing
;
typedef
struct
{
cPersistent_HEAD
}
cPersistentObject
;
...
...
@@ -36,6 +45,9 @@ typedef struct {
getattrofunc
getattro
;
setattrofunc
setattro
;
int
(
*
changed
)(
cPersistentObject
*
);
void
(
*
accessed
)(
cPersistentObject
*
);
void
(
*
ghostify
)(
cPersistentObject
*
);
void
(
*
deallocated
)(
cPersistentObject
*
);
int
(
*
setstate
)(
PyObject
*
);
pergetattr
pergetattro
;
persetattr
persetattro
;
...
...
@@ -59,11 +71,13 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
#define PER_CHANGED(O) (cPersistenceCAPI->changed((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((O)->state==cPersistent_STICKY_STATE && ((O)->state=cPersistent_UPTODATE_STATE))
#define PER_GHOSTIFY(O) (cPersistenceCAPI->ghostify((cPersistentObject*)(O)))
#define PER_ALLOW_DEACTIVATION(O) ((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_PREVENT_DEACTIVATION(O) ((O)->state==cPersistent_UPTODATE_STATE && ((O)->state=cPersistent_STICKY_STATE))
#define PER_DEL(O)
Py_XDECREF((O)->jar); Py_XDECREF((O)->oid);
#define PER_DEL(O)
(cPersistenceCAPI->deallocated((cPersistentObject*)(O)))
#define PER_USE(O) \
(((O)->state != cPersistent_GHOST_STATE \
...
...
@@ -71,7 +85,7 @@ static cPersistenceCAPIstruct *cPersistenceCAPI;
? (((O)->state==cPersistent_UPTODATE_STATE) \
? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
#define PER_ACCESSED(O)
((O)->atime=((long)(time(NULL)/3))%65536)
#define PER_ACCESSED(O)
(cPersistenceCAPI->accessed((cPersistentObject*)(O)))
#endif
...
...
src/persistent/cPickleCache.c
View file @
226ee421
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment