Mercurial > p > roundup > code
diff roundup/backends/portalocker.py @ 1387:e975db910d9f
latest version of portalocker fixed for win98 and winnt, thanks James Kew
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Sun, 19 Jan 2003 23:14:42 +0000 |
| parents | 8dd4f736370b |
| children | 1159963f769c |
line wrap: on
line diff
--- a/roundup/backends/portalocker.py Sun Jan 19 16:15:38 2003 +0000 +++ b/roundup/backends/portalocker.py Sun Jan 19 23:14:42 2003 +0000 @@ -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 @@ 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()
