#!/usr/bin/python -t # -*- mode: Python; indent-tabs-mode: nil; -*- # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Michael Schwendt import errno, fcntl, os, struct, sys class LockFileLocked(Exception): """Exception thrown if a conflicting lock is found in non-blocking mode""" pass class SimplePosixLock: """An exclusive lock on a file via fcntl()""" def __init__(self, name, blocking=False): self._fname = name self._lock = struct.pack('hhqqhh', fcntl.F_WRLCK, os.SEEK_SET, 0, 0, 0, 0) self._unlock = struct.pack('hhqqhh', fcntl.F_UNLCK, os.SEEK_SET, 0, 0, 0, 0) if blocking: self._l_cmd = fcntl.F_SETLKW else: self._l_cmd = fcntl.F_SETLK def lock(self): try: self._file = open(self._fname,'w') rv = fcntl.fcntl(self._file.fileno(), self._l_cmd, self._lock) except IOError, (err, strerr): if ( err == errno.EAGAIN ): raise LockFileLocked else: raise def unlock(self): rv = fcntl.fcntl(self._file.fileno(), self._l_cmd, self._unlock) self._file.close() class SimpleFlock: """An exclusive lock on a file via flock()""" def __init__(self, name, blocking=False): self._fname = name self._mode = fcntl.LOCK_EX if not blocking: self._mode |= fcntl.LOCK_NB def lock(self): try: self._file = open(self._fname,'w') rc = fcntl.flock(self._file, self._mode) except IOError, (err, strerr): if ( err == errno.EAGAIN ): raise LockFileLocked else: raise def unlock(self): fcntl.flock(self._file, fcntl.LOCK_UN) self._file.close() class LockFile: def __init__(self, name, blocking=False, type='flock'): if type == 'flock': self._base = SimpleFlock(name,blocking) elif type == 'posix': self._base = SimplePosixLock(name,blocking) else: sys.stderr.write("Invalid LockFile type!\n") self._base = SimpleFlock(name,blocking) def lock(self): self._base.lock() def unlock(self): self._base.unlock()