![]() |
|
|
Generated: 8 Jan 2009 |
00001 ########################################################## 00002 ## stolen and (slighty) adapted from: 00003 ## http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65203 00004 ## 00005 00006 import os, sys 00007 00008 if os.name == 'nt': 00009 import msvcrt 00010 elif os.name == 'posix': 00011 import fcntl 00012 LOCK_EX = fcntl.F_WRLCK 00013 LOCK_SH = fcntl.F_RDLCK 00014 LOCK_NB = fcntl.F_UNLCK 00015 else: 00016 raise RuntimeError("Locker only defined for nt and posix platforms") 00017 00018 if os.name == 'nt': 00019 def lock(file): 00020 """ 00021 Lock first 10 bytes of a file. 00022 """ 00023 pos = file.tell() # remember current position 00024 file.seek(0) 00025 # By default, python tries about 10 times, then throws an exception. 00026 # We want to wait forever. 00027 acquired = False 00028 while not acquired: 00029 try: 00030 msvcrt.locking(file.fileno(),msvcrt.LK_LOCK,10) 00031 acquired = True 00032 except IOError, x: 00033 if x.errno != 36: # 36, AKA 'Resource deadlock avoided', is normal 00034 raise 00035 file.seek(pos) # reset position 00036 00037 def unlock(file): 00038 """ 00039 Unlock first 10 bytes of a file. 00040 """ 00041 pos = file.tell() # remember current position 00042 file.seek(0) 00043 msvcrt.locking(file.fileno(),msvcrt.LK_UNLCK,10) 00044 file.seek(pos) # reset position 00045 00046 elif os.name =='posix': 00047 import socket,errno,time 00048 00049 def _tmpFileName(fileName): 00050 return "%s.%s.%d" % ( fileName, socket.gethostname(), os.getpid() ) 00051 def _lckFileName(fileName): 00052 return "%s.lock" % fileName 00053 00054 def _linkCount( lockFileName ): 00055 try: 00056 return os.stat(lockFileName).st_nlink 00057 except OSError, e: 00058 if e.errno != errno.ENOENT: 00059 raise 00060 return -1 00061 def _read(fileName): 00062 try: 00063 fp = open(fileName) 00064 try: readFileName = fp.read() 00065 finally: fp.close() 00066 return readFileName 00067 except EnvironmentError, e: 00068 if e.errno != errno.ENOENT: 00069 raise 00070 return None 00071 00072 def _sleep(): time.sleep(8) 00073 00074 def lock(file): 00075 fileName = file.name 00076 tmpFileName = _tmpFileName(fileName) 00077 fp = open( tmpFileName, "w" ) 00078 fp.write( tmpFileName ) 00079 fp.close() 00080 00081 lockFileName = _lckFileName( fileName ) 00082 while True: 00083 if _linkCount(lockFileName) != -1: _sleep() 00084 try: 00085 os.link( tmpFileName, lockFileName ) 00086 # we acquired the lock 00087 return 00088 except OSError, e: 00089 if e.errno == errno.ENOENT: 00090 pass 00091 elif e.errno != errno.EEXIST: 00092 os.unlink(tmpFileName) 00093 raise 00094 elif _linkCount( lockFileName ) != 2: 00095 pass 00096 elif _read(lockFileName) == tmpFileName: 00097 raise 00098 else: 00099 # someone else owns that lock 00100 pass 00101 ## didn't get the lock !! 00102 ## say something ? 00103 #print _id_()," failed to acquire the lock ..." 00104 _sleep() 00105 pass 00106 return 00107 00108 def unlock(file): 00109 fileName = file.name 00110 tmpFileName = _tmpFileName(fileName) 00111 lockFileName = _lckFileName( fileName ) 00112 00113 try: 00114 os.unlink( lockFileName ) 00115 except OSError, e: 00116 if e.errno != errno.ENOENT: 00117 raise 00118 # remove the tmp file 00119 try: 00120 os.unlink( tmpFileName ) 00121 except OSError, e: 00122 if e.errno != errno.ENOENT: 00123 raise 00124 return 00125 00126