| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 2010

# 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, time
    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
    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 import logging
    00127 ## Lock a file.
    00128 #  The file for the lock is created if it doesn't exists and it the "temporary"
    00129 #  argument is set to True it will also be deleted when the lock is not needed.
    00130 #  The unlocking is done in the destructor (RAII pattern).
    00131 class LockFile(object):
    00132     def __init__(self, name, temporary = False):
    00133         self.name = name
    00134         self.temporary = temporary
    00135         self.file = None
    00136         self.log = logging.getLogger("LockFile")
    00137         self.log.info("%s - Locking on %s", time.strftime("%Y-%m-%d_%H:%M:%S"), self.name)
    00138         if not os.path.exists(name):
    00139             mode = "w"
    00140         else:
    00141             self.temporary = False # I do not want to delete a file I didn't create
    00142             mode = "r+"
    00143         try:
    00144             self.file = open(self.name, mode)
    00145             lock(self.file)
    00146         except:
    00147             self.log.warning("Cannot acquire lock on %s", self.name)
    00148     def __del__(self):
    00149         if self.file:
    00150             unlock(self.file)
    00151             self.file.close()
    00152             if self.temporary:
    00153                 try:
    00154                     os.remove(self.name)
    00155                 except:
    00156                     pass
    00157             self.log.info("%s - Lock on %s released", time.strftime("%Y-%m-%d_%H:%M:%S"), self.name)
    00158