Merge with bsddb3 2002.11.23.10.42.36
diff --git a/Lib/bsddb/dbutils.py b/Lib/bsddb/dbutils.py
index fe08407..d21069f 100644
--- a/Lib/bsddb/dbutils.py
+++ b/Lib/bsddb/dbutils.py
@@ -1,11 +1,5 @@
 #------------------------------------------------------------------------
 #
-# In my performance tests, using this (as in dbtest.py test4) is
-# slightly slower than simply compiling _db.c with MYDB_THREAD
-# undefined to prevent multithreading support in the C module.
-# Using NoDeadlockDb also prevent deadlocks from mutliple processes
-# accessing the same database.
-#
 # Copyright (C) 2000 Autonomous Zone Industries
 #
 # License:      This is free software.  You may use this software for any
@@ -18,7 +12,7 @@
 # Author: Gregory P. Smith <greg@electricrain.com>
 #
 # Note: I don't know how useful this is in reality since when a
-#       DBDeadlockError happens the current transaction is supposed to be
+#       DBLockDeadlockError happens the current transaction is supposed to be
 #       aborted.  If it doesn't then when the operation is attempted again
 #       the deadlock is still happening...
 #       --Robin
@@ -34,35 +28,47 @@
 _sleep = sleep
 del sleep
 
-import _db
+import _bsddb
 
-_deadlock_MinSleepTime = 1.0/64  # always sleep at least N seconds between retrys
-_deadlock_MaxSleepTime = 1.0     # never sleep more than N seconds between retrys
+_deadlock_MinSleepTime = 1.0/64   # always sleep at least N seconds between retrys
+_deadlock_MaxSleepTime = 3.14159  # never sleep more than N seconds between retrys
 
+_deadlock_VerboseFile = None      # Assign a file object to this for a "sleeping"
+                                  # message to be written to it each retry
 
 def DeadlockWrap(function, *_args, **_kwargs):
     """DeadlockWrap(function, *_args, **_kwargs) - automatically retries
     function in case of a database deadlock.
 
-    This is a DeadlockWrapper method which DB calls can be made using to
-    preform infinite retrys with sleeps in between when a DBLockDeadlockError
-    exception is raised in a database call:
+    This is a function intended to be used to wrap database calls such
+    that they perform retrys with exponentially backing off sleeps in
+    between when a DBLockDeadlockError exception is raised.
+
+    A 'max_retries' parameter may optionally be passed to prevent it
+    from retrying forever (in which case the exception will be reraised).
 
         d = DB(...)
         d.open(...)
         DeadlockWrap(d.put, "foo", data="bar")  # set key "foo" to "bar"
     """
     sleeptime = _deadlock_MinSleepTime
-    while (1) :
+    max_retries = _kwargs.get('max_retries', -1)
+    if _kwargs.has_key('max_retries'):
+        del _kwargs['max_retries']
+    while 1:
         try:
             return apply(function, _args, _kwargs)
         except _db.DBLockDeadlockError:
-            print 'DeadlockWrap sleeping ', sleeptime
+            if _deadlock_VerboseFile:
+                _deadlock_VerboseFile.write('dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime)
             _sleep(sleeptime)
             # exponential backoff in the sleep time
             sleeptime = sleeptime * 2
             if sleeptime > _deadlock_MaxSleepTime :
                 sleeptime = _deadlock_MaxSleepTime
+            max_retries = max_retries - 1
+            if max_retries == -1:
+                raise
 
 
 #------------------------------------------------------------------------