# HG changeset patch # User John Schneiderman # Date 1425930139 -3600 # Node ID 8ef24a759bf60cf938bfda2a9ceb32c078a5bfd6 # Parent 27b2e19955c3eed18bf13b75f14669bb759c90bd Replaced the generic file locker with a custom repository locker. diff -r 27b2e19955c3 -r 8ef24a759bf6 INSTALL --- a/INSTALL Thu Jan 08 18:58:03 2015 +0100 +++ b/INSTALL Mon Mar 09 20:42:19 2015 +0100 @@ -21,13 +21,11 @@ Needed for compiling ==================== 1) Python 2.7+ -2) FileLock from https://github.com/dmfrey/FileLock How To compile the program ============================ -1) Build and install FileLock to site-packages if not already present. -2) setup.py build -3) setup.py install +1) setup.py build +2) setup.py install Known Issues ============ diff -r 27b2e19955c3 -r 8ef24a759bf6 doc/ChangeLog --- a/doc/ChangeLog Thu Jan 08 18:58:03 2015 +0100 +++ b/doc/ChangeLog Mon Mar 09 20:42:19 2015 +0100 @@ -17,6 +17,8 @@ *** You should have received a copy of the GNU Affero General Public License*** *** along with this program. If not, see . *** ******************************************************************************** +2015-00-00 John Schneiderman 0.4.0 +- No longer dependant upon third-party general file locker for repositories. 2014-08-21 John Schneiderman 0.3.0 - Unregistering repositories will now only do so on an exact match of the storage name. diff -r 27b2e19955c3 -r 8ef24a759bf6 src/manager.py --- a/src/manager.py Thu Jan 08 18:58:03 2015 +0100 +++ b/src/manager.py Mon Mar 09 20:42:19 2015 +0100 @@ -45,12 +45,9 @@ import sys import os import shutil - import filelock as guard import stat - print "Acquiring manager lock ..." - lock = guard.FileLock('HWM') - with lock: + with RepositoryManagerLock(): print "Adding repository: %s" % repository.StorageName if __doesRepositoryStorageNameExist(repository): print >>sys.stderr, "The repository storage name '%s' already exists." % repository.StorageName @@ -100,12 +97,7 @@ @return When the registration is successful gives true, else-wise false. """ - import sys - import filelock as guard - - print "Acquiring manager lock ..." - lock = guard.FileLock('HWM') - with lock: + with RepositoryManagerLock(): print "Registering the repository: %s" % repository.StorageName if not __doesRepositoryStorageNameExist(repository): print >>sys.stderr, "The repository '%s' does not exists." % repository.StorageName @@ -140,11 +132,8 @@ """ import sys from manrepo import Repository - import filelock as guard - print "Acquiring manager lock ..." - lock = guard.FileLock('HWM') - with lock: + with RepositoryManagerLock(): print "Modifying repository: %s" % currentStorageName oldRepository = Repository(currentStorageName) @@ -216,12 +205,7 @@ @return When the deletion is successful gives true, else-wise false. """ - import sys - import filelock as guard - - print "Acquiring manager lock ..." - lock = guard.FileLock('HWM') - with lock: + with RepositoryManagerLock(): if not __doesRepositoryStorageNameExist(repository): print >>sys.stderr, "The repository %s was not found." % repository.StorageName return False diff -r 27b2e19955c3 -r 8ef24a759bf6 src/manrepolock.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/manrepolock.py Mon Mar 09 20:42:19 2015 +0100 @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +'''***************************************************************************** +*** This file is part of HgWeb Manager. *** +*** *** +*** Copyright (C) 2014 *** +*** CodeGNU Solutions *** +*** *** +*** This program is free software: you can redistribute it and/or modify it *** +*** under the terms of the GNU Affero General Public License as published *** +*** by the Free Software Foundation, either version 3 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 Affero General Public License for more details. *** +*** *** +*** You should have received a copy of the GNU Affero General Public License*** +*** along with this program. If not, see . *** +*****************************************************************************''' + +import errno +import os +import tempfile +import time + + +repositoryLockFile = os.path.join(tempfile.gettempdir(), 'HWM.lock') + + +class RepositoryManagerLock(object): + """ Handles the locking for the repository manager. """ + + def __init__(self): + """ Initialises the lock for use, but does not get one. """ + self.haveLock = False + + def __isLockedProcessRunning(self): + """ Determines if a process is already running + + @return When the process is running gives true, false else-wise. + """ + try: + with open(repositoryLockFile) as previousLock: + pid = int(previousLock.readline()) + os.kill(pid, 0) + return True + except OSError: + return False # Process is not running. + + def acquire(self): + """ Gets the repository lock. """ + while True: + try: + print 'Acquiring repository manager lock ...' + self.lock = os.open(repositoryLockFile, os.O_CREAT | os.O_EXCL | os.O_RDWR) + break + except OSError as e: + if e.errno != errno.EEXIST: + raise + + if not self.__isLockedProcessRunning(): + print 'A dead repository lock found, removing ...' + os.unlink(repositoryLockFile) + time.sleep(0.75) + self.haveLock = True + os.write(self.lock, str(os.getpid())) + + def release(self): + """ Frees the repository lock. """ + if self.haveLock: + print 'Releasing repository manager lock ...' + os.close(self.lock) + os.unlink(repositoryLockFile) + self.haveLock = False + + def __enter__(self): + if not self.haveLock: + self.acquire() + return self + + def __exit__(self, type, value, traceback): + if self.haveLock: + self.release() + + def __del__(self): + """ Ensures that when the object is gone, the lock is released. """ + self.release()