Commit 1f2a7cce authored by Chris McDonough's avatar Chris McDonough

Merge from 2.7 branch:

- Add "instance-local" "period" to TransientObjectContainer.  This allows
  users to dial a knob which may (or may not) reduce the number of conflicts
  that happen during heavy sessioning usage by reducing the frequency at
  which buckets potentially expire at the cost of expiration time
  accuracy.  Previously, this setting was hardcoded to 20 (seconds) at
  module scope.

- Add 'session-resolution-seconds' to zope.conf.in/zopeschema.xml to
  control instance-local period for /temp_folder/session_data.

- Update TOC UI, interface, and help files to deal with instance-local
  period.

- Update OFS/Application to deal with instance-local period for default
  /temp/session_data TOC.

- Use __setstate__ for TOC upgrade instead of a dedicated _upgrade method
  (it was too hard to figure out where to call _upgrade from and when to
  call it).

- Perform a few formatting changes that should make it easier to merge the 2.7
  branch with the HEAD going forward.  I beseech those who make formatting
  changes to a branch or the HEAD make them to the other at that time
  as well, especially with the SVN/CVS split it's very painful to do merging
  when there are non-substantive differences between HEAD/maint.  When I was
  a child, I never thought I would need to use the word "beseech", however, it
  has indeed happened.
parent 0871e361
############################################################################ ##############################################################################
# #
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# #
...@@ -375,9 +375,15 @@ class AppInitializer: ...@@ -375,9 +375,15 @@ class AppInitializer:
delnotify = getattr(config, 'session_delete_notify_script_path', delnotify = getattr(config, 'session_delete_notify_script_path',
None) None)
default_limit = 1000 default_limit = 1000
default_period_secs = 20
default_timeout_mins = 20
limit = (getattr(config, 'maximum_number_of_session_objects', None) limit = (getattr(config, 'maximum_number_of_session_objects', None)
or default_limit) or default_limit)
timeout_spec = getattr(config, 'session_timeout_minutes', None) timeout_spec = getattr(config, 'session_timeout_minutes',
default_timeout_mins)
period_spec = getattr(config, 'session_resolution_seconds',
default_period_secs)
if addnotify and app.unrestrictedTraverse(addnotify, None) is None: if addnotify and app.unrestrictedTraverse(addnotify, None) is None:
LOG('Zope Default Object Creation', WARNING, LOG('Zope Default Object Creation', WARNING,
...@@ -395,7 +401,8 @@ class AppInitializer: ...@@ -395,7 +401,8 @@ class AppInitializer:
'session_data', 'Session Data Container', 'session_data', 'Session Data Container',
addNotification = addnotify, addNotification = addnotify,
delNotification = delnotify, delNotification = delnotify,
limit=limit) limit=limit,
period_secs=period_spec)
if timeout_spec is not None: if timeout_spec is not None:
toc = TransientObjectContainer('session_data', toc = TransientObjectContainer('session_data',
...@@ -403,7 +410,8 @@ class AppInitializer: ...@@ -403,7 +410,8 @@ class AppInitializer:
timeout_mins = timeout_spec, timeout_mins = timeout_spec,
addNotification = addnotify, addNotification = addnotify,
delNotification = delnotify, delNotification = delnotify,
limit=limit) limit=limit,
period_secs = period_spec)
tf._setObject('session_data', toc) tf._setObject('session_data', toc)
tf_reserved = getattr(tf, '_reserved_names', ()) tf_reserved = getattr(tf, '_reserved_names', ())
......
...@@ -62,7 +62,7 @@ the Zope physical path to the method to be invoked to receive the notification ...@@ -62,7 +62,7 @@ the Zope physical path to the method to be invoked to receive the notification
<TR> <TR>
<TD ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT" VALIGN="TOP">
<div class="form-label"> <div class="form-label">
Data object timeout in minutes Data object timeout (in minutes)
</div> </div>
<div class="form-help"> <div class="form-help">
("0" means no expiration) ("0" means no expiration)
...@@ -73,6 +73,20 @@ the Zope physical path to the method to be invoked to receive the notification ...@@ -73,6 +73,20 @@ the Zope physical path to the method to be invoked to receive the notification
</TD> </TD>
</TR> </TR>
<TR>
<TD ALIGN="LEFT" VALIGN="TOP">
<div class="form-label">
Timeout resolution (in seconds)
</div>
<div class="form-help">
(accept the default if you're not sure)
</div>
</TD>
<TD ALIGN="LEFT" VALIGN="TOP">
<INPUT TYPE="TEXT" NAME="period_secs:int" SIZE="10" value="20">
</TD>
</TR>
<TR> <TR>
<TD ALIGN="LEFT" VALIGN="TOP"> <TD ALIGN="LEFT" VALIGN="TOP">
<div class="form-label"> <div class="form-label">
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
help_topic='Transience-change.stx' help_topic='Transience-change.stx'
)"> )">
<form action="manage_changeTransientObjectContainer" method="post"> <form action="manage_changeTransientObjectContainer" method="post">
<p class="form-help"> <p class="form-help">
...@@ -13,7 +12,9 @@ Transient Object Containers are used to store transient data. ...@@ -13,7 +12,9 @@ Transient Object Containers are used to store transient data.
Transient data will persist, but only for a user-specified period of time Transient data will persist, but only for a user-specified period of time
(the "data object timeout") after which it will be flushed. (the "data object timeout") after which it will be flushed.
</p> </p>
<dtml-call nudge><!-- turn the buckets if necessary --> <dtml-call nudge><!-- turn the buckets if necessary -->
<p class="form-label"> <p class="form-label">
<font color="green"> <font color="green">
<dtml-let l=getLen> <dtml-let l=getLen>
...@@ -43,7 +44,7 @@ Transient data will persist, but only for a user-specified period of time ...@@ -43,7 +44,7 @@ Transient data will persist, but only for a user-specified period of time
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
Data object timeout value in minutes Data object timeout value (in minutes)
</div> </div>
<div class="form-help"> <div class="form-help">
("0" means no expiration) ("0" means no expiration)
...@@ -55,6 +56,26 @@ Transient data will persist, but only for a user-specified period of time ...@@ -55,6 +56,26 @@ Transient data will persist, but only for a user-specified period of time
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Timeout resolution (in seconds)
</div>
<div class="form-help">
Defines what the "resolution" of item timeout is. Setting this higher
allows the transience machinery to do fewer "writes" at the expense of
causing items to time out later than the "Data object timeout value" by
a factor of (at most) this many seconds. This number must divide evenly
into the number of timeout seconds ("Data object timeout value" * 60)
and cannot be set higher than the timeout value in seconds.
</div>
</td>
<td align="left" valign="top">
<input type="text" name="period_secs:int" size=10
value=&dtml-getPeriodSeconds;>
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
...@@ -100,6 +121,22 @@ Transient data will persist, but only for a user-specified period of time ...@@ -100,6 +121,22 @@ Transient data will persist, but only for a user-specified period of time
</td> </td>
</tr> </tr>
<dtml-let l=getLen>
<dtml-if l>
<tr>
<td colspan=2>
<br/>
<p class="form-label">
<font color="red">WARNING!</font>
All data objects existing in this transient object container
will be deleted when the data object timeout or expiration resolution
is changed.
</p>
</tr>
</td>
</dtml-if>
</dtml-let>
<tr> <tr>
<td></td> <td></td>
<td> <td>
...@@ -109,12 +146,5 @@ Transient data will persist, but only for a user-specified period of time ...@@ -109,12 +146,5 @@ Transient data will persist, but only for a user-specified period of time
</table> </table>
</form> </form>
<p class="form-label">
<font color="red">WARNING!</font>
The data objects existing in this transient object container
will be deleted when the data object timeout is changed.
</p>
<dtml-var manage_page_footer> <dtml-var manage_page_footer>
...@@ -23,13 +23,23 @@ TransientObjectContainer - Add ...@@ -23,13 +23,23 @@ TransientObjectContainer - Add
The title of the object. The title of the object.
- **Data object timeout in minutes** - **Data object timeout (in minutes)**
The minimum number of minutes that objects in the container will The minimum number of minutes that objects in the container will
persist for. Objects in the container are passively deleted, so persist for. Objects in the container are passively deleted, so
they may not be deleted exactly after this number of minutes elapses. they may not be deleted exactly after this number of minutes elapses.
A setting of "0" indicates that objects should not expire. A setting of "0" indicates that objects should not expire.
- **Timeout resolution (in seconds)**
Defines what the "resolution" of item timeout is. Setting this
higher allows the transience machinery to do fewer "writes" at
the expense of causing items to time out later than the "Data
object timeout value" by a factor of (at most) this many
seconds. This number must divide evenly into the number of
timeout seconds ("Data object timeout value" * 60) and cannot
be set higher than the timeout value in seconds.
- **Maximum number of subobjects ** - **Maximum number of subobjects **
The maximum number of subobjects that this container may The maximum number of subobjects that this container may
......
...@@ -23,7 +23,7 @@ TransientObjectContainer - Manage ...@@ -23,7 +23,7 @@ TransientObjectContainer - Manage
The title of the object. The title of the object.
- **Data object timeout in minutes** - **Data object timeout (in minutes)**
The minimum number of minutes that objects in the container will The minimum number of minutes that objects in the container will
persist for. Objects in the container are passively deleted, so persist for. Objects in the container are passively deleted, so
...@@ -34,6 +34,16 @@ TransientObjectContainer - Manage ...@@ -34,6 +34,16 @@ TransientObjectContainer - Manage
If the timeout value is "0", objects will not time out. If the timeout value is "0", objects will not time out.
- **Timeout resolution (in seconds)**
Defines what the "resolution" of item timeout is. Setting this
higher allows the transience machinery to do fewer "writes" at
the expense of causing items to time out later than the "Data
object timeout value" by a factor of (at most) this many
seconds. This number must divide evenly into the number of
timeout seconds ("Data object timeout value" * 60) and cannot
be set higher than the timeout value in seconds.
- **Maximum number of subobjects ** - **Maximum number of subobjects **
The maximum number of subobjects that this container may The maximum number of subobjects that this container may
...@@ -92,11 +102,6 @@ TransientObjectContainer - Manage ...@@ -92,11 +102,6 @@ TransientObjectContainer - Manage
from zLOG import LOG from zLOG import LOG
LOG(100, 'test', 'id: %s' % item.getId()) LOG(100, 'test', 'id: %s' % item.getId())
Environment Variables
You can control some transient object settings with environment
variables. See 'doc/ENVIORNMENT.txt' for more informatin.
See Also See Also
- "Transience API":TransienceInterfaces.py - "Transience API":TransienceInterfaces.py
......
...@@ -80,10 +80,12 @@ class TransientObjectContainer: ...@@ -80,10 +80,12 @@ class TransientObjectContainer:
Permission -- 'Create Transient Objects' Permission -- 'Create Transient Objects'
""" """
def setTimeoutMinutes(self, timeout_mins): def setTimeoutMinutes(self, timeout_mins, period=20):
""" """
Set the number of minutes of inactivity allowable for subobjects Set the number of minutes of inactivity allowable for subobjects
before they expire. before they expire (timeout_mins) as well as the 'timeout resolution'
in seconds (period). 'timeout_mins' * 60 must be evenly divisible
by the period. Period must be less than 'timeout_mins' * 60.
Permission -- 'Manage Transient Object Container' Permission -- 'Manage Transient Object Container'
""" """
...@@ -96,6 +98,13 @@ class TransientObjectContainer: ...@@ -96,6 +98,13 @@ class TransientObjectContainer:
Permission -- 'View management screens' Permission -- 'View management screens'
""" """
def getPeriodSeconds(self):
"""
Return the 'timeout resolution' in seconds.
Permission -- 'View management screens'
"""
def getAddNotificationTarget(self): def getAddNotificationTarget(self):
""" """
Returns the current 'after add' function, or None. Returns the current 'after add' function, or None.
......
...@@ -34,7 +34,9 @@ class TestBase(TestCase): ...@@ -34,7 +34,9 @@ class TestBase(TestCase):
self.errmargin = .20 self.errmargin = .20
self.timeout = 120 self.timeout = 120
self.t = TransientObjectContainer('sdc', timeout_mins=self.timeout/60) self.period = 20
self.t = TransientObjectContainer('sdc', timeout_mins=self.timeout/60,
period_secs=self.period)
def tearDown(self): def tearDown(self):
self.t = None self.t = None
...@@ -267,7 +269,7 @@ class TestTransientObjectContainer(TestBase): ...@@ -267,7 +269,7 @@ class TestTransientObjectContainer(TestBase):
self.assertEqual(len(self.t.keys()), 0) self.assertEqual(len(self.t.keys()), 0)
# 2 minutes # 2 minutes
self.t._setTimeout(self.timeout/60*2) self.t._setTimeout(self.timeout/60*2, self.period)
self.t._reset() self.t._reset()
for x in range(10, 110): for x in range(10, 110):
self.t[x] = x self.t[x] = x
...@@ -279,7 +281,7 @@ class TestTransientObjectContainer(TestBase): ...@@ -279,7 +281,7 @@ class TestTransientObjectContainer(TestBase):
self.assertEqual(len(self.t.keys()), 0) self.assertEqual(len(self.t.keys()), 0)
# 3 minutes # 3 minutes
self.t._setTimeout(self.timeout/60*3) self.t._setTimeout(self.timeout/60*3, self.period)
self.t._reset() self.t._reset()
for x in range(10, 110): for x in range(10, 110):
self.t[x] = x self.t[x] = x
...@@ -318,7 +320,8 @@ class TestTransientObjectContainer(TestBase): ...@@ -318,7 +320,8 @@ class TestTransientObjectContainer(TestBase):
def testLen(self): def testLen(self):
# This test must not time out else it will fail. # This test must not time out else it will fail.
self.t._setTimeout(self.timeout) # make timeout extremely unlikely # make timeout extremely unlikely by setting it very high
self.t._setTimeout(self.timeout, self.period)
added = {} added = {}
r = range(10, 1010) r = range(10, 1010)
for x in r: for x in r:
...@@ -340,8 +343,9 @@ class TestTransientObjectContainer(TestBase): ...@@ -340,8 +343,9 @@ class TestTransientObjectContainer(TestBase):
def testGetTimeoutMinutesWorks(self): def testGetTimeoutMinutesWorks(self):
self.assertEqual(self.t.getTimeoutMinutes(), self.timeout / 60) self.assertEqual(self.t.getTimeoutMinutes(), self.timeout / 60)
self.t._setTimeout(10) self.t._setTimeout(10, 30)
self.assertEqual(self.t.getTimeoutMinutes(), 10) self.assertEqual(self.t.getTimeoutMinutes(), 10)
self.assertEqual(self.t.getPeriodSeconds(), 30)
def test_new(self): def test_new(self):
t = self.t.new('foobieblech') t = self.t.new('foobieblech')
...@@ -369,7 +373,7 @@ class TestTransientObjectContainer(TestBase): ...@@ -369,7 +373,7 @@ class TestTransientObjectContainer(TestBase):
self.assertRaises(MaxTransientObjectsExceeded, self._maxOut) self.assertRaises(MaxTransientObjectsExceeded, self._maxOut)
def testZeroTimeoutMeansPersistForever(self): def testZeroTimeoutMeansPersistForever(self):
self.t._setTimeout(0) self.t._setTimeout(0, self.period)
self.t._reset() self.t._reset()
for x in range(10, 110): for x in range(10, 110):
self.t[x] = x self.t[x] = x
......
...@@ -627,6 +627,16 @@ ...@@ -627,6 +627,16 @@
<metadefault>20</metadefault> <metadefault>20</metadefault>
</key> </key>
<key name="session-resolution-seconds" datatype="integer"
default="20">
<description>
An integer value representing the number of seconds to be used as the
"timeout resolution" of the '/temp_folder/session_data' transient
object container in Zope's object database.
</description>
<metadefault>20</metadefault>
</key>
<key name="suppress-all-access-rules" datatype="boolean" <key name="suppress-all-access-rules" datatype="boolean"
default="off" handler="suppress_all_access_rules"> default="off" handler="suppress_all_access_rules">
<description> <description>
......
...@@ -548,6 +548,20 @@ instancehome $INSTANCE ...@@ -548,6 +548,20 @@ instancehome $INSTANCE
# session-timeout-minutes 30 # session-timeout-minutes 30
# Directive: session-resolution-seconds
#
# Description:
# An integer value representing the number of seconds to be used as the
# "timeout resolution" of the '/temp_folder/session_data' transient
# object container.
#
# Default: 20
#
# Example:
#
# session-resolution-seconds 60
# Directive: suppress-all-access-rules # Directive: suppress-all-access-rules
# #
# Description: # Description:
......
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