| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# locker.py

Go to the documentation of this file.

    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