From: richard Date: Sun, 19 Jan 2003 23:14:42 +0000 (+0000) Subject: latest version of portalocker fixed for win98 and winnt, thanks James Kew X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=27c47795adf49c2fa3e4a93c0b6b3010dd9cd801;p=roundup.git latest version of portalocker fixed for win98 and winnt, thanks James Kew git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1464 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/roundup/backends/portalocker.py b/roundup/backends/portalocker.py index fc0005b..219ae24 100644 --- a/roundup/backends/portalocker.py +++ b/roundup/backends/portalocker.py @@ -2,7 +2,7 @@ # Requires python 1.5.2 or better. # ID line added by richard for Roundup file tracking -# $Id: portalocker.py,v 1.2 2002-10-03 06:56:29 richard Exp $ +# $Id: portalocker.py,v 1.3 2003-01-19 23:14:42 richard Exp $ """ Cross-platform (posix/nt) API for flock-style file locking. @@ -43,51 +43,99 @@ Version: Id: portalocker.py,v 1.3 2001/05/29 18:47:55 Administrator Exp import os if os.name == 'nt': - import win32con - import win32file - import pywintypes - LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK - LOCK_SH = 0 # the default - LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY - # is there any reason not to reuse the following structure? - __overlapped = pywintypes.OVERLAPPED() + import win32con + import win32file + import pywintypes + LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK + LOCK_SH = 0 # the default + LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY + # is there any reason not to reuse the following structure? + __overlapped = pywintypes.OVERLAPPED() elif os.name == 'posix': - import fcntl - LOCK_EX = fcntl.LOCK_EX - LOCK_SH = fcntl.LOCK_SH - LOCK_NB = fcntl.LOCK_NB + import fcntl + LOCK_EX = fcntl.LOCK_EX + LOCK_SH = fcntl.LOCK_SH + LOCK_NB = fcntl.LOCK_NB else: - raise RuntimeError("PortaLocker only defined for nt and posix platforms") + raise RuntimeError("PortaLocker only defined for nt and posix platforms") if os.name == 'nt': - def lock(file, flags): - hfile = win32file._get_osfhandle(file.fileno()) - win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped) - - def unlock(file): - hfile = win32file._get_osfhandle(file.fileno()) - win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped) + def lock(file, flags): + hfile = win32file._get_osfhandle(file.fileno()) + # LockFileEx is not supported on all Win32 platforms (Win95, Win98, WinME). + # If it's not supported, win32file will raise an exception. + # Try LockFileEx first, as it has more functionality and handles + # blocking locks more efficiently. + try: + win32file.LockFileEx(hfile, flags, 0, 0xffff0000, __overlapped) + except win32file.error, e: + import winerror + # Propagate upwards all exceptions other than not-implemented. + if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED: + raise e + + # LockFileEx is not supported. Use LockFile. + # LockFile does not support shared locking -- always exclusive. + # Care: the low/high length params are reversed compared to LockFileEx. + if not flags & LOCK_EX: + import warnings + warnings.warn("PortaLocker does not support shared locking on Win9x", RuntimeWarning) + # LockFile only supports immediate-fail locking. + if flags & LOCK_NB: + win32file.LockFile(hfile, 0, 0, 0xffff0000, 0) + else: + # Emulate a blocking lock with a polling loop. + import time + while 1: + # Attempt a lock. + try: + win32file.LockFile(hfile, 0, 0, 0xffff0000, 0) + break + except win32file.error, e: + # Propagate upwards all exceptions other than lock violation. + if e[0] != winerror.ERROR_LOCK_VIOLATION: + raise e + # Sleep and poll again. + time.sleep(0.1) + # TODO: should this return the result of the lock? + + def unlock(file): + hfile = win32file._get_osfhandle(file.fileno()) + # UnlockFileEx is not supported on all Win32 platforms (Win95, Win98, WinME). + # If it's not supported, win32file will raise an api_error exception. + try: + win32file.UnlockFileEx(hfile, 0, 0xffff0000, __overlapped) + except win32file.error, e: + import winerror + # Propagate upwards all exceptions other than not-implemented. + if e[0] != winerror.ERROR_CALL_NOT_IMPLEMENTED: + raise e + + # UnlockFileEx is not supported. Use UnlockFile. + # Care: the low/high length params are reversed compared to UnLockFileEx. + win32file.UnlockFile(hfile, 0, 0, 0xffff0000, 0) elif os.name =='posix': - def lock(file, flags): - fcntl.flock(file.fileno(), flags) + def lock(file, flags): + fcntl.flock(file.fileno(), flags) + # TODO: should this return the result of the lock? - def unlock(file): - fcntl.flock(file.fileno(), fcntl.LOCK_UN) + def unlock(file): + fcntl.flock(file.fileno(), fcntl.LOCK_UN) if __name__ == '__main__': - from time import time, strftime, localtime - import sys - import portalocker + from time import time, strftime, localtime + import sys + import portalocker - log = open('log.txt', "a+") - portalocker.lock(log, portalocker.LOCK_EX) + log = open('log.txt', "a+") + portalocker.lock(log, portalocker.LOCK_EX) - timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time())) - log.write( timestamp ) + timestamp = strftime("%m/%d/%Y %H:%M:%S\n", localtime(time())) + log.write( timestamp ) - print "Wrote lines. Hit enter to release lock." - dummy = sys.stdin.readline() + print "Wrote lines. Hit enter to release lock." + dummy = sys.stdin.readline() - log.close() + log.close()