Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Kirill Smelkov
Zope
Commits
c91c4047
Commit
c91c4047
authored
Oct 22, 2001
by
matt@zope.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated with more code from the original CoreSessionTracking SessionDataManager
for object expiry.
parent
8eea6b70
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
238 additions
and
23 deletions
+238
-23
lib/python/Products/Transience/Transience.py
lib/python/Products/Transience/Transience.py
+238
-23
No files found.
lib/python/Products/Transience/Transience.py
View file @
c91c4047
...
@@ -85,10 +85,10 @@
...
@@ -85,10 +85,10 @@
"""
"""
Core session tracking SessionData class.
Core session tracking SessionData class.
$Id: Transience.py,v 1.
2 2001/10/22 16:23:51
matt Exp $
$Id: Transience.py,v 1.
3 2001/10/22 18:48:17
matt Exp $
"""
"""
__version__
=
'$Revision: 1.
2
$'
[
11
:
-
2
]
__version__
=
'$Revision: 1.
3
$'
[
11
:
-
2
]
import
Globals
import
Globals
from
Globals
import
HTMLFile
,
MessageDialog
from
Globals
import
HTMLFile
,
MessageDialog
...
@@ -99,16 +99,20 @@ from OFS.SimpleItem import SimpleItem
...
@@ -99,16 +99,20 @@ from OFS.SimpleItem import SimpleItem
from
Persistence
import
Persistent
,
PersistentMapping
from
Persistence
import
Persistent
,
PersistentMapping
from
Acquisition
import
Implicit
,
aq_base
from
Acquisition
import
Implicit
,
aq_base
from
AccessControl
import
ClassSecurityInfo
from
AccessControl
import
ClassSecurityInfo
from
BTrees
import
OOBTree
import
os.path
import
os.path
import
math
import
time
import
time
_notfound
=
[]
_notfound
=
[]
_marker
=
[]
# permissions
# permissions
ADD_DATAMGR_PERM
=
'Add Transient Object Container'
ADD_DATAMGR_PERM
=
'Add Transient Object Container'
CHANGE_DATAMGR_PERM
=
'Change Transient Object Containers'
CHANGE_DATAMGR_PERM
=
'Change Transient Object Containers'
MGMT_SCREEN_PERM
=
'View management screens'
MGMT_SCREEN_PERM
=
'View management screens'
ACCESS_CONTENTS_PERM
=
'Access contents information'
ACCESS_CONTENTS_PERM
=
'Access contents information'
CREATE_TRANSIENTS_PERM
=
'Create Transient Objects'
ACCESS_SESSIONDATA_PERM
=
'Access Transient Objects'
ACCESS_SESSIONDATA_PERM
=
'Access Transient Objects'
MANAGE_CONTAINER_PERM
=
'Manage Transient Object Container'
MANAGE_CONTAINER_PERM
=
'Manage Transient Object Container'
...
@@ -165,6 +169,8 @@ class TransientObjectContainer(SimpleItem):
...
@@ -165,6 +169,8 @@ class TransientObjectContainer(SimpleItem):
[
'Manager'
,
'Anonymous'
])
[
'Manager'
,
'Anonymous'
])
security
.
setPermissionDefault
(
ACCESS_SESSIONDATA_PERM
,
security
.
setPermissionDefault
(
ACCESS_SESSIONDATA_PERM
,
[
'Manager'
,
'Anonymous'
])
[
'Manager'
,
'Anonymous'
])
security
.
setPermissionDefault
(
CREATE_TRANSIENTS_PERM
,
[
'Manager'
,])
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'manage_container'
)
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'manage_container'
)
manage_container
=
HTMLFile
(
'dtml/manageTransientObjectContainer'
,
manage_container
=
HTMLFile
(
'dtml/manageTransientObjectContainer'
,
...
@@ -180,17 +186,23 @@ class TransientObjectContainer(SimpleItem):
...
@@ -180,17 +186,23 @@ class TransientObjectContainer(SimpleItem):
#
#
def
__init__
(
self
,
id
,
title
=
''
,
timeout_mins
=
20
,
addNotification
=
None
,
def
__init__
(
self
,
id
,
title
=
''
,
timeout_mins
=
20
,
addNotification
=
None
,
delNotification
=
None
):
delNotification
=
None
,
err_margin
=
.
20
,
ctype
=
OOBTree
.
OOBTree
):
self
.
id
=
id
self
.
id
=
id
self
.
title
=
title
self
.
title
=
title
self
.
_container
=
{}
self
.
_ctype
=
ctype
self
.
_addCallback
=
None
self
.
_addCallback
=
None
self
.
_delCallback
=
None
self
.
_delCallback
=
None
self
.
setTimeoutMinutes
(
timeout_mins
)
self
.
_err_margin
=
err_margin
self
.
_setTimeout
(
timeout_mins
)
self
.
_reset
()
self
.
setAddNotificationTarget
(
addNotification
)
self
.
setDelNotificationTarget
(
delNotification
)
self
.
setDelNotificationTarget
(
delNotification
)
self
.
setAddNotificationTarget
(
addNotification
)
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# ItemWithID
# ItemWithID
...
@@ -204,24 +216,28 @@ class TransientObjectContainer(SimpleItem):
...
@@ -204,24 +216,28 @@ class TransientObjectContainer(SimpleItem):
# StringKeyedHomogenousItemContainer
# StringKeyedHomogenousItemContainer
#
#
security
.
declareProtected
(
CREATE_TRANSIENTS_PERM
,
'new'
)
def
new
(
self
,
key
):
def
new
(
self
,
key
):
if
type
(
key
)
is
not
type
(
''
):
if
type
(
key
)
is
not
type
(
''
):
raise
TypeError
,
(
key
,
"key is not a string type"
)
raise
TypeError
,
(
key
,
"key is not a string type"
)
if
self
.
_container
.
has_key
(
key
):
if
self
.
has_key
(
key
):
raise
KeyError
,
key
# Not allowed to dup keys
raise
KeyError
,
key
# Not allowed to dup keys
item
=
TransientObject
(
key
,
parent
=
self
)
item
=
TransientObject
(
key
,
parent
=
self
)
self
.
_container
[
key
]
=
item
self
[
key
]
=
item
self
.
notifyAdd
(
item
)
return
item
return
item
security
.
declareProtected
(
CREATE_TRANSIENTS_PERM
,
'new_or_existing'
)
def
new_or_existing
(
self
,
key
):
def
new_or_existing
(
self
,
key
):
item
=
self
.
_container
.
get
(
key
,
_notfound
)
item
=
self
.
get
(
key
,
_notfound
)
if
item
is
not
_notfound
:
return
item
if
item
is
not
_notfound
:
return
item
return
self
.
new
(
key
)
return
self
.
new
(
key
)
...
@@ -232,11 +248,15 @@ class TransientObjectContainer(SimpleItem):
...
@@ -232,11 +248,15 @@ class TransientObjectContainer(SimpleItem):
security
.
declareProtected
(
MANAGE_CONTAINER_PERM
,
'setTimeoutMinutes'
)
security
.
declareProtected
(
MANAGE_CONTAINER_PERM
,
'setTimeoutMinutes'
)
def
setTimeoutMinutes
(
self
,
timeout_mins
):
def
setTimeoutMinutes
(
self
,
timeout_mins
):
self
.
_timeout
=
timeout_mins
""" """
if
timeout_mins
!=
self
.
getTimeoutMinutes
():
self
.
_setTimeout
(
timeout_mins
)
self
.
_reset
()
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'getTimeoutMinutes'
)
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'getTimeoutMinutes'
)
def
getTimeoutMinutes
(
self
):
def
getTimeoutMinutes
(
self
):
return
self
.
_timeout
""" """
return
self
.
_timeout_secs
/
60
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'getAddNotificationTarget'
)
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'getAddNotificationTarget'
)
def
getAddNotificationTarget
(
self
):
def
getAddNotificationTarget
(
self
):
...
@@ -279,16 +299,6 @@ class TransientObjectContainer(SimpleItem):
...
@@ -279,16 +299,6 @@ class TransientObjectContainer(SimpleItem):
#
#
security
.
declareProtected
(
MGMT_SCREEN_PERM
,
'getLen'
)
def
getLen
(
self
):
"""
Potentially expensive helper function to figure out how
many items are contained.
"""
return
len
(
self
.
_container
)
security
.
declareProtected
(
MANAGE_CONTAINER_PERM
,
security
.
declareProtected
(
MANAGE_CONTAINER_PERM
,
'manage_changeTransientObjectContainer'
)
'manage_changeTransientObjectContainer'
)
def
manage_changeTransientObjectContainer
(
self
,
title
=
''
,
def
manage_changeTransientObjectContainer
(
self
,
title
=
''
,
...
@@ -318,7 +328,7 @@ class TransientObjectContainer(SimpleItem):
...
@@ -318,7 +328,7 @@ class TransientObjectContainer(SimpleItem):
f
=
os
.
path
.
join
(
Globals
.
data_dir
,
"transientobjects.zexp"
)
f
=
os
.
path
.
join
(
Globals
.
data_dir
,
"transientobjects.zexp"
)
self
.
c
=
PersistentMapping
()
self
.
c
=
PersistentMapping
()
for
k
,
v
in
self
.
_container
.
items
():
for
k
,
v
in
self
.
items
():
self
.
c
[
k
]
=
v
self
.
c
[
k
]
=
v
get_transaction
().
commit
()
get_transaction
().
commit
()
...
@@ -340,13 +350,218 @@ class TransientObjectContainer(SimpleItem):
...
@@ -340,13 +350,218 @@ class TransientObjectContainer(SimpleItem):
conn
=
self
.
_p_jar
conn
=
self
.
_p_jar
ob
=
conn
.
importFile
(
f
)
ob
=
conn
.
importFile
(
f
)
for
k
,
v
in
ob
.
items
():
for
k
,
v
in
ob
.
items
():
self
.
_container
[
k
]
=
v
self
[
k
]
=
v
if
REQUEST
is
not
None
:
if
REQUEST
is
not
None
:
return
MessageDialog
(
return
MessageDialog
(
title
=
"Transient objects imported"
,
title
=
"Transient objects imported"
,
message
=
"Transient objects imported from %s"
%
f
,
message
=
"Transient objects imported from %s"
%
f
,
action
=
"manage_container"
)
action
=
"manage_container"
)
def
_setTimeout
(
self
,
timeout_mins
):
if
type
(
timeout_mins
)
is
not
type
(
1
):
raise
TypeError
,
(
timeout_mins
,
"Must be integer"
)
self
.
_timeout_secs
=
timeout_mins
*
60
def
_reset
(
self
):
t_secs
=
self
.
_timeout_secs
r_secs
=
self
.
_resolution_secs
=
int
(
t_secs
*
self
.
_err_margin
)
or
1
numbuckets
=
int
(
math
.
floor
(
t_secs
/
r_secs
))
or
1
l
=
[]
i
=
0
now
=
int
(
time
.
time
())
for
x
in
range
(
numbuckets
):
dump_after
=
now
+
i
c
=
self
.
_ctype
()
l
.
insert
(
0
,
[
c
,
dump_after
])
i
=
i
+
r_secs
index
=
self
.
_ctype
()
self
.
_ring
=
Ring
(
l
,
index
)
def
_getCurrentBucket
(
self
,
get_dump
=
0
):
# no timeout always returns last bucket
if
not
self
.
_timeout_secs
:
b
,
dump_after
=
self
.
_ring
.
_data
[
0
]
return
b
index
=
self
.
_ring
.
_index
now
=
int
(
time
.
time
())
i
=
self
.
_timeout_secs
# expire all buckets in the ring which have a dump_after time that
# is before now, turning the ring as many turns as necessary to
# get to a non-expirable bucket.
while
1
:
l
=
b
,
dump_after
=
self
.
_ring
.
_data
[
-
1
]
if
now
>
dump_after
:
self
.
_ring
.
turn
()
# mutate elements in-place in the ring
new_dump_after
=
now
+
i
l
[
1
]
=
new_dump_after
self
.
_clean
(
b
,
index
)
i
=
i
+
self
.
_resolution_secs
else
:
break
if
get_dump
:
return
self
.
_ring
.
_data
[
0
],
dump_after
,
now
else
:
b
,
dump_after
=
self
.
_ring
.
_data
[
0
]
return
b
def
_clean
(
self
,
b
,
index
):
# What is all this?
#for ob in b.values():
# d = last = None
# f = getattr(ob, self._onend, None)
# #
# # HUH?
# #
# getDataMgr = getattr(ob, 'getDataMgr', None)
# if getDataMgr is not None:
# if callable(getDataMgr):
# d = getDataMgr()
# if d != last:
# mgr = self.aq_parent.unrestrictedTraverse(d)
# last = d
# if callable(f): f(mgr)
for
k
,
v
in
list
(
index
.
items
()):
if
v
is
b
:
self
.
notifyDestruct
(
index
[
k
])
del
index
[
k
]
b
.
clear
()
def
_show
(
self
):
""" debug method """
b
,
dump
,
now
=
self
.
_getCurrentBucket
(
1
)
ringdumps
=
map
(
lambda
x
:
`x[1]`
[
-
4
],
self
.
_ring
)
t
=
(
"now: "
+
`now`
[
-
4
:],
"dump_after: "
+
`dump`
[
-
4
:],
"ring_dumps: "
+
`ringdumps`
,
"ring: "
+
`self._ring`
)
for
x
in
t
:
print
x
def
__setitem__
(
self
,
k
,
v
):
current
=
self
.
_getCurrentBucket
()
index
=
self
.
_ring
.
_index
b
=
index
.
get
(
k
)
if
b
is
None
:
# this is a new key
index
[
k
]
=
current
elif
b
is
not
current
:
# this is an old key that isn't in the current bucket.
del
b
[
k
]
# delete it from the old bucket
index
[
k
]
=
current
# change the value
current
[
k
]
=
v
def
__getitem__
(
self
,
k
):
current
=
self
.
_getCurrentBucket
()
index
=
self
.
_ring
.
_index
# the next line will raise the proper error if the item has expired
b
=
index
[
k
]
v
=
b
[
k
]
# grab the value before we potentially time it out.
if
b
is
not
current
:
# it's not optimal to do writes in getitem, but there's no choice.
# we accessed the object, so it should become current.
index
[
k
]
=
current
# change the index to the current bucket.
current
[
k
]
=
v
# add the value to the current bucket.
del
b
[
k
]
# delete the item from the old bucket.
return
v
security
.
declareProtected
(
ACCESS_SESSIONDATA_PERM
,
'get'
)
def
set
(
self
,
k
,
v
):
""" """
if
type
(
k
)
is
not
type
(
''
):
raise
TypeError
,
"Transient Object Container keys must be strings"
self
[
k
]
=
v
security
.
declareProtected
(
ACCESS_SESSIONDATA_PERM
,
'get'
)
# Uses a different marker than _notfound
def
get
(
self
,
k
,
default
=
_marker
):
try
:
v
=
self
[
k
]
except
KeyError
:
v
=
_marker
if
v
is
_marker
:
if
default
is
_marker
:
return
None
else
:
return
default
return
v
def
__delitem__
(
self
,
k
):
self
.
_getCurrentBucket
()
index
=
self
.
_ring
.
_index
b
=
index
[
k
]
del
index
[
k
]
del
b
[
k
]
security
.
declareProtected
(
ACCESS_SESSIONDATA_PERM
,
'__len__'
)
def
__len__
(
self
):
self
.
_getCurrentBucket
()
return
len
(
self
.
_ring
.
_index
)
security
.
declareProtected
(
ACCESS_SESSIONDATA_PERM
,
'has_key'
)
def
has_key
(
self
,
k
):
self
.
_getCurrentBucket
()
index
=
self
.
_ring
.
_index
return
index
.
get
(
k
,
_notfound
)
is
not
_notfound
def
values
(
self
):
return
map
(
lambda
k
,
self
=
self
:
self
[
k
],
self
.
keys
())
def
items
(
self
):
return
map
(
lambda
k
,
self
=
self
:
(
k
,
self
[
k
]),
self
.
keys
())
def
keys
(
self
):
self
.
_getCurrentBucket
()
index
=
self
.
_ring
.
_index
return
map
(
lambda
x
:
x
,
index
.
keys
())
def
update
(
self
):
raise
NotImplementedError
def
clear
(
self
):
raise
NotImplementedError
def
copy
(
self
):
raise
NotImplementedError
security
.
declareProtected
(
ACCESS_SESSIONDATA_PERM
,
'getLen'
)
getLen
=
__len__
class
Ring
(
Persistent
):
""" Instances of this class will be frequently written to the ZODB,
so it's optimized as best possible for write-friendliness """
def
__init__
(
self
,
l
,
index
):
if
not
len
(
l
):
raise
"ring must have at least one element"
self
.
_data
=
l
self
.
_index
=
index
def
__repr__
(
self
):
return
repr
(
self
.
_data
)
def
__len__
(
self
):
return
len
(
self
.
_data
)
def
__getitem__
(
self
,
i
):
return
self
.
_data
[
i
]
def
turn
(
self
):
last
=
self
.
_data
.
pop
(
-
1
)
self
.
_data
.
insert
(
0
,
last
)
self
.
_p_changed
=
1
def
_p_independent
(
self
):
return
1
class
TransientObject
(
Persistent
,
Implicit
):
class
TransientObject
(
Persistent
,
Implicit
):
""" akin to Session Data Object """
""" akin to Session Data Object """
...
...
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