[Zope-Checkins] CVS: Zope/lib/python/Products/Sessions/stresstests - stresstestMultiThread.py:1.3
Chris McDonough
chrism@zope.com
Thu, 20 Jun 2002 21:52:02 -0400
Update of /cvs-repository/Zope/lib/python/Products/Sessions/stresstests
In directory cvs.zope.org:/tmp/cvs-serv20290/stresstests
Modified Files:
stresstestMultiThread.py
Log Message:
New TransientObjectContainer implementation.
Changes:
- More stable under high usage, especially in the face of
situations under which there are many ZODB conflict
errors. The previous implementation had stability problems
when many conflict errors were encountered; especially
conflicts that were generated as a result of a simultaneous
change to a subobject of the TOC (such as in the case of a Zope
application which makes heavy use of both frames and
sessions).
- More conflict-resistant. Instead of ignoring the likelihood
that multiple threads will attempt to perform the same actions
simultaneously in methods of the TOC (which often causes
conflicts), the new implementation attempts to avoid conflicts
by employing a chance-based housekeeping model. In this model,
one thread is "elected" by chance to do the kinds of tasks that
cause the most conflicts.
- Now uses a "timeslice" based model instead of a "ring" based
model. This also helps cut down on conflicts and makes
the code slighly less obfuscated (not much, though! ;-)
- Quite a few more comments in the code.
- Changes to the sessioning stresstest (which exposed the
bug that made me reimplement the TOC in the first place).
- Updates to unit tests.
- A "HowTransienceWorks.stx" document which attempts to
explain how the code works. It's not stellar, but
it's a start.
- Changes to the TransientObject class that the TOC
hands out (typically as a "session data object"), in order
to make invalidation less Rube-Goldberg-ish.
The structure of the TOC object has changed enough that in order to
maintain b/w compatibility, an in-place upgrade of "old" instances
is implied by running them with this code. "Upgraded" instances
are not backwards-incompatible, however, so folks can hopefully
move back and forth between Zope versions without much hassle.
=== Zope/lib/python/Products/Sessions/stresstests/stresstestMultiThread.py 1.2 => 1.3 ===
TransientObjectContainer, TransientObject
from Products.TemporaryFolder.TemporaryFolder import MountedTemporaryFolder
-from ZODB.POSException import InvalidObjectReference, ConflictError
+from Products.TemporaryFolder.LowConflictConnection import LowConflictConnection
+from ZODB.Connection import Connection
+from ZODB.POSException import InvalidObjectReference, ConflictError, ReadConflictError, BTreesConflictError
from DateTime import DateTime
from unittest import TestCase, TestSuite, TextTestRunner, makeSuite
import time, threading, random
@@ -32,6 +34,7 @@
from ZODB.DemoStorage import DemoStorage
from OFS.Application import Application
import sys
+from zLOG import log_time
sys.setcheckinterval(200)
tf_name = 'temp_folder'
@@ -65,7 +68,7 @@
bidmgr = BrowserIdManager(idmgr_name)
tf = MountedTemporaryFolder(tf_name, title="Temporary Folder")
toc = TransientObjectContainer(toc_name, title='Temporary '
- 'Transient Object Container', timeout_mins=20)
+ 'Transient Object Container', timeout_mins=1)
session_data_manager=SessionDataManager(id='session_data_manager',
path='/'+tf_name+'/'+toc_name, title='Session Data Manager')
@@ -89,7 +92,7 @@
get_transaction().commit()
class TestMultiThread(TestCase):
- def testNonOverlappingBrowserIds(self):
+ def testOverlappingBrowserIds(self):
readers = []
writers = []
readiters = 20
@@ -115,10 +118,7 @@
while threading.activeCount() > 1:
time.sleep(1)
- for thread in readers:
- assert thread.out == [], thread.out
-
- def testOverlappingBrowserIds(self):
+ def testNonOverlappingBrowserIds(self):
readers = []
writers = []
readiters = 20
@@ -144,9 +144,6 @@
while threading.activeCount() > 1:
time.sleep(1)
- for thread in readers:
- assert thread.out == [], thread.out
-
class BaseReaderWriter(threading.Thread):
def __init__(self, db, iters, sdm_name):
self.conn = db.open()
@@ -166,13 +163,23 @@
try:
self.run1()
return
+ except ReadConflictError:
+ print "read conflict"
+ except BTreesConflictError:
+ print "btrees conflict"
except ConflictError:
- i = i + 1
- #print "conflict %d" % i
- if i > 3: raise
+ print "general conflict"
+ except:
+ get_transaction().abort()
+ print log_time()
+ raise
+ i = i + 1
+ get_transaction().abort()
+ time.sleep(random.randrange(5) * .1)
finally:
self.conn.close()
del self.app
+ print i
class ReaderThread(BaseReaderWriter):
def run1(self):