1#------------------------------------------------------------------------ 2# 3# Copyright (C) 2000 Autonomous Zone Industries 4# 5# License: This is free software. You may use this software for any 6# purpose including modification/redistribution, so long as 7# this header remains intact and that you do not claim any 8# rights of ownership or authorship of this software. This 9# software has been tested, but no warranty is expressed or 10# implied. 11# 12# Author: Gregory P. Smith <greg@krypto.org> 13# 14# Note: I don't know how useful this is in reality since when a 15# DBLockDeadlockError happens the current transaction is supposed to be 16# aborted. If it doesn't then when the operation is attempted again 17# the deadlock is still happening... 18# --Robin 19# 20#------------------------------------------------------------------------ 21 22 23# 24# import the time.sleep function in a namespace safe way to allow 25# "from berkeleydb.dbutils import *" 26# 27from time import sleep as _sleep 28 29import sys 30from . import db 31 32# always sleep at least N seconds between retrys 33_deadlock_MinSleepTime = 1.0/128 34# never sleep more than N seconds between retrys 35_deadlock_MaxSleepTime = 3.14159 36 37# Assign a file object to this for a "sleeping" message to be written to it 38# each retry 39_deadlock_VerboseFile = None 40 41 42def DeadlockWrap(function, *_args, **_kwargs): 43 """DeadlockWrap(function, *_args, **_kwargs) - automatically retries 44 function in case of a database deadlock. 45 46 This is a function intended to be used to wrap database calls such 47 that they perform retrys with exponentially backing off sleeps in 48 between when a DBLockDeadlockError exception is raised. 49 50 A 'max_retries' parameter may optionally be passed to prevent it 51 from retrying forever (in which case the exception will be reraised). 52 53 d = DB(...) 54 d.open(...) 55 DeadlockWrap(d.put, b'foo', data=b'bar') # set key b'foo' to b'bar' 56 """ 57 sleeptime = _deadlock_MinSleepTime 58 max_retries = _kwargs.get('max_retries', -1) 59 if 'max_retries' in _kwargs: 60 del _kwargs['max_retries'] 61 while True: 62 try: 63 return function(*_args, **_kwargs) 64 except db.DBLockDeadlockError: 65 if _deadlock_VerboseFile: 66 _deadlock_VerboseFile.write( 67 'dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime) 68 _sleep(sleeptime) 69 # exponential backoff in the sleep time 70 sleeptime *= 2 71 if sleeptime > _deadlock_MaxSleepTime: 72 sleeptime = _deadlock_MaxSleepTime 73 max_retries -= 1 74 if max_retries == -1: 75 raise 76 77 78#------------------------------------------------------------------------ 79