Commits

Thomas Waldmann committed a759603

remove unused locking code (e.g. ReadLock/WriteLock/ExclusiveLock/...)

Comments (0)

Files changed (2)

MoinMoin/util/_tests/test_lock.py

-# Copyright: 2005 by Florian Festi
-# Copyright: 2007 by MoinMoin:ThomasWaldmann
-# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
-
-"""
-    MoinMoin - MoinMoin.module_tested Tests
-"""
-
-
-import tempfile, os, time, shutil
-
-import pytest
-
-from MoinMoin.util.lock import ExclusiveLock, WriteLock, ReadLock
-
-
-class TestExclusiveLock(object):
-
-    def setup_method(self, method):
-        self.test_dir = tempfile.mkdtemp('', 'lock_')
-        self.test_dir_mtime_goal = time.time()
-        self.test_dir_mtime_reported = os.stat(self.test_dir).st_mtime
-        self.lock_dir = os.path.join(self.test_dir, "lock")
-
-    def teardown_method(self, method):
-        shutil.rmtree(self.test_dir)
-
-    def testBrokenTimeAPI(self):
-        """ util.lock: os.stat().mtime consistency with time.time()
-
-            the timestamp os.stat reports as st_mtime on a fresh file should
-            be the same (or at least almost the same) as the time time.time()
-            reported at this time.
-            Differences of n*3600s are usually operating system bugs / limitations,
-            Win32 (as of Win XP SP2 + hotfixes 2006-04-30) is broken if you set
-            TZ to a different value than the rest of the system uses.
-            E.g. if you set "TZ=GMT1EDT" (and the rest of the system is setup
-            on german/berlin timezone), it will report 7200s difference in the
-            summer.
-        """
-        diff = self.test_dir_mtime_reported - self.test_dir_mtime_goal # diff should be 0 or near 0
-        assert abs(diff) <= 2
-
-    def testTimeout(self):
-        """ util.lock: ExclusiveLock: raise ValueError for timeout < 2.0 """
-        pytest.raises(ValueError, ExclusiveLock, self.lock_dir, timeout=1.0)
-
-    def testAcquire(self):
-        """ util.lock: ExclusiveLock: acquire """
-        lock = ExclusiveLock(self.lock_dir)
-        assert lock.acquire(0.1)
-
-    def testRelease(self):
-        """ util.lock: ExclusiveLock: release
-
-        After releasing a lock, new one could be acquired.
-        """
-        lock = ExclusiveLock(self.lock_dir)
-        if not lock.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        lock.release()
-        assert lock.acquire(0.1)
-
-    def testIsLocked(self):
-        """ util.lock: ExclusiveLock: isLocked """
-        lock = ExclusiveLock(self.lock_dir)
-        if not lock.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        assert lock.isLocked()
-        lock.release()
-        assert not lock.isLocked()
-
-    def testExists(self):
-        """ util.lock: ExclusiveLock: exists """
-        lock = ExclusiveLock(self.lock_dir)
-        if not lock.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        assert lock.exists()
-
-    def testIsExpired(self):
-        """ util.lock: ExclusiveLock: isExpired """
-        timeout = 2.0
-        extra = 0.1 # extra delay to avoid occasional failure on windows
-        lock = ExclusiveLock(self.lock_dir, timeout=timeout)
-        if not lock.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        assert not lock.isExpired()
-        time.sleep(timeout + extra)
-        assert lock.isExpired()
-
-    def testExpire(self):
-        """ util.lock: ExclusiveLock: expire """
-        timeout = 2.0
-        extra = 0.1 # extra delay to avoid occasional failure on windows
-        lock = ExclusiveLock(self.lock_dir, timeout=timeout)
-        if not lock.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        assert not lock.expire()
-        time.sleep(timeout + extra)
-        assert lock.expire()
-
-    def testExclusive(self):
-        """ util.lock: ExclusiveLock: lock is exclusive """
-        first = ExclusiveLock(self.lock_dir)
-        second = ExclusiveLock(self.lock_dir)
-        if not first.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        assert not second.acquire(0.1)
-
-    def testAcquireAfterTimeout(self):
-        """ util.lock: ExclusiveLock: acquire after timeout
-
-        Lock with one lock, try to acquire another after timeout.
-        """
-        timeout = 3.0 # minimal timeout is 2.0
-        first = ExclusiveLock(self.lock_dir, timeout)
-        second = ExclusiveLock(self.lock_dir, timeout)
-        if not first.acquire(0.1):
-            pytest.skip("can't acquire lock")
-        if second.acquire(0.1):
-            pytest.skip("first lock is not exclusive")
-        # Second lock should be acquired after timeout
-        assert second.acquire(timeout + 0.2)
-
-    def unlock(self, lock, delay):
-        time.sleep(delay)
-        lock.release()
-
-class TestWriteLock(object):
-    def setup_method(self, method):
-        self.test_dir = tempfile.mkdtemp('', 'lock_')
-        self.lock_dir = os.path.join(self.test_dir, "writelock")
-
-    def teardown_method(self, method):
-        shutil.rmtree(self.test_dir)
-
-    def test_writelock_acquire(self):
-        """ util.lock: WriteLock: acquire """
-        lock = WriteLock(self.lock_dir)
-        assert lock.acquire(0.1)
-        with pytest.raises(RuntimeError):
-            assert lock.acquire(0.1)
-
-    def test_haveReadLocks(self):
-        """check if there is a ReadLock """
-        timeout = 2.0
-        write_lock = WriteLock(self.lock_dir, timeout)
-        read_lock = ReadLock(self.lock_dir)
-        # acquired ReadLock
-        assert read_lock.acquire(0.1)
-        result_before = write_lock._haveReadLocks()
-        assert result_before
-        # try to acquire WriteLock
-        assert write_lock.acquire()
-        result_after = write_lock._haveReadLocks()
-        assert not result_after
-
-class TestReadLock(object):
-    def setup_method(self, method):
-        self.test_dir = tempfile.mkdtemp('', 'lock_')
-        self.lock_dir = os.path.join(self.test_dir, "readlock")
-
-    def teardown_method(self, method):
-        shutil.rmtree(self.test_dir)
-
-    def test_readlock_acquire(self):
-        """ util.lock: ReadLock: acquire """
-        lock = ReadLock(self.lock_dir)
-        assert lock.acquire(0.1)
-        with pytest.raises(RuntimeError):
-            assert lock.acquire(0.1)
-
-coverage_modules = ['MoinMoin.util.lock']

MoinMoin/util/lock.py

-# Copyright: 2005 Florian Festi, Nir Soffer
-# Copyright: 2008 MoinMoin:ThomasWaldmann
-# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
-
-"""
-    MoinMoin - locking functions
-"""
-
-
-import os, sys, tempfile, time, errno
-
-from MoinMoin import log
-logging = log.getLogger(__name__)
-
-from MoinMoin.util import filesys
-
-class Timer:
-    """ Simple count down timer
-
-    Useful for code that needs to complete a task within some timeout.
-    """
-    defaultSleep = 0.25
-    maxSleep = 0.25
-
-    def __init__(self, timeout):
-        self.setTimeout(timeout)
-        self._start = None
-        self._stop = None
-
-    def setTimeout(self, timeout):
-        self.timeout = timeout
-        if timeout is None:
-            self._sleep = self.defaultSleep
-        else:
-            self._sleep = min(timeout / 10.0, self.maxSleep)
-
-    def start(self):
-        """ Start the countdown """
-        if self.timeout is None:
-            return
-        now = time.time()
-        self._start = now
-        self._stop = now + self.timeout
-
-    def haveTime(self):
-        """ Check if timeout has not passed """
-        if self.timeout is None:
-            return True
-        return time.time() <= self._stop
-
-    def sleep(self):
-        """ Sleep without sleeping over timeout """
-        if self._stop is not None:
-            timeLeft = max(self._stop - time.time(), 0)
-            sleep = min(self._sleep, timeLeft)
-        else:
-            sleep = self._sleep
-        time.sleep(sleep)
-
-    def elapsed(self):
-        return time.time() - self._start
-
-
-class ExclusiveLock:
-    """ Exclusive lock
-
-    Uses a directory as portable lock method. On all platforms,
-    creating a directory will fail if the directory exists.
-
-    Only one exclusive lock per resource is allowed. This lock is not
-    used directly by clients, but used by both ReadLock and WriteLock.
-
-    If created with a timeout, the lock will expire timeout seconds
-    after it has been acquired. Without a timeout, it will never expire.
-    """
-    fileName = '' # The directory is the lockDir
-    timerClass = Timer
-
-    def __init__(self, dir, timeout=None):
-        """ Init a write lock
-
-        :param dir: the lock directory. Since this lock uses a empty
-            filename, the dir is the lockDir.
-        :param timeout: while trying to acquire, the lock will expire
-            other exclusive locks older than timeout.
-            WARNING: because of file system timing limitations, timeouts
-            must be at least 2 seconds.
-        """
-        self.dir = dir
-        if timeout is not None and timeout < 2.0:
-            raise ValueError('timeout must be at least 2 seconds')
-        self.timeout = timeout
-        if self.fileName:
-            self.lockDir = os.path.join(dir, self.fileName)
-            self._makeDir()
-        else:
-            self.lockDir = dir
-        self._locked = False
-
-    def acquire(self, timeout=None):
-        """ Try to acquire a lock.
-
-        Try to create the lock directory. If it fails because another
-        lock exists, try to expire the other lock. Repeat after little
-        sleep until timeout passed.
-
-        Return True if a lock was acquired; False otherwise.
-        """
-        timer = self.timerClass(timeout)
-        timer.start()
-        while timer.haveTime():
-            try:
-                filesys.mkdir(self.lockDir)
-                self._locked = True
-                logging.debug('acquired exclusive lock: {0}'.format(self.lockDir, ))
-                return True
-            except OSError as err:
-                if err.errno != errno.EEXIST:
-                    raise
-                if self.expire():
-                    continue # Try immediately to acquire
-                timer.sleep()
-        logging.debug('failed to acquire exclusive lock: {0}'.format(self.lockDir, ))
-        return False
-
-    def release(self):
-        """ Release the lock """
-        if not self._locked:
-            raise RuntimeError('lock already released: {0}'.format(self.lockDir))
-        self._removeLockDir()
-        self._locked = False
-        logging.debug('released lock: {0}'.format(self.lockDir))
-
-    def isLocked(self):
-        return self._locked
-
-    def exists(self):
-        return os.path.exists(self.lockDir)
-
-    def isExpired(self):
-        """ Return True if too old or missing; False otherwise
-
-        TODO: Since stat returns times using whole seconds, this is
-        quite broken. Maybe use OS specific calls like Carbon.File on
-        Mac OS X?
-        """
-        if self.timeout is None:
-            return not self.exists()
-        try:
-            lock_age = time.time() - filesys.stat(self.lockDir).st_mtime
-            return lock_age > self.timeout
-        except OSError as err:
-            if err.errno == errno.ENOENT:
-                # No such lock file, therefore "expired"
-                return True
-            raise
-
-    def expire(self):
-        """ Return True if the lock is expired or missing; False otherwise. """
-        if self.isExpired():
-            self._removeLockDir()
-            logging.debug("expired lock: {0}".format(self.lockDir))
-            return True
-        return False
-
-    # Private -------------------------------------------------------
-
-    def _makeDir(self):
-        """ Make sure directory exists """
-        try:
-            filesys.mkdir(self.dir)
-            logging.debug('created directory: {0}'.format(self.dir))
-        except OSError as err:
-            if err.errno != errno.EEXIST:
-                raise
-
-    def _removeLockDir(self):
-        """ Remove lockDir ignoring 'No such file or directory' errors """
-        try:
-            filesys.rmdir(self.lockDir)
-            logging.debug('removed directory: {0}'.format(self.dir))
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
-
-
-class WriteLock(ExclusiveLock):
-    """ Exclusive Read/Write Lock
-
-    When a resource is locked with this lock, clients can't read
-    or write the resource.
-
-    This super-exclusive lock can't be acquired if there are any other
-    locks, either WriteLock or ReadLocks. When trying to acquire, this
-    lock will try to expire all existing ReadLocks.
-    """
-    fileName = 'write_lock'
-
-    def __init__(self, dir, timeout=None, readlocktimeout=None):
-        """ Init a write lock
-
-        :param dir: the lock directory. Every resource should have one
-            lock directory, which may contain read or write locks.
-        :param timeout: while trying to acquire, the lock will expire
-            other unreleased write locks older than timeout.
-        :param readlocktimeout: while trying to acquire, the lock will
-            expire other read locks older than readlocktimeout.
-        """
-        ExclusiveLock.__init__(self, dir, timeout)
-        if readlocktimeout is None:
-            self.readlocktimeout = timeout
-        else:
-            self.readlocktimeout = readlocktimeout
-
-    def acquire(self, timeout=None):
-        """ Acquire an exclusive write lock
-
-        Try to acquire an exclusive lock, then try to expire existing
-        read locks. If timeout has not passed, the lock is acquired.
-        Otherwise, the exclusive lock is released and the lock is not
-        acquired.
-
-        Return True if lock acquired, False otherwise.
-        """
-        if self._locked:
-            raise RuntimeError("lock already locked")
-        result = False
-        timer = self.timerClass(timeout)
-        timer.start()
-        if ExclusiveLock.acquire(self, timeout):
-            try:
-                while timer.haveTime():
-                    self._expireReadLocks()
-                    if not self._haveReadLocks():
-                        result = timer.haveTime()
-                        break
-                    timer.sleep()
-            finally:
-                if result:
-                    logging.debug('acquired write lock: {0}'.format(self.lockDir))
-                    return True
-                else:
-                    self.release()
-        return False
-
-    # Private -------------------------------------------------------
-
-    def _expireReadLocks(self):
-        """ Expire old read locks """
-        readLockFileName = ReadLock.fileName
-        for name in os.listdir(self.dir):
-            if not name.startswith(readLockFileName):
-                continue
-            LockDir = os.path.join(self.dir, name)
-            ExclusiveLock(LockDir, self.readlocktimeout).expire()
-
-    def _haveReadLocks(self):
-        """ Return True if read locks exists; False otherwise """
-        readLockFileName = ReadLock.fileName
-        for name in os.listdir(self.dir):
-            if name.startswith(readLockFileName):
-                return True
-        return False
-
-class ReadLock(ExclusiveLock):
-    """ Read lock
-
-    The purpose of this lock is to mark the resource as read only.
-    Multiple ReadLocks can be acquired for same resource, but no
-    WriteLock can be acquired until all ReadLocks are released.
-
-    Allows only one lock per instance.
-    """
-    fileName = 'read_lock_'
-
-    def __init__(self, dir, timeout=None):
-        """ Init a read lock
-
-        :param dir: the lock directory. Every resource should have one
-            lock directory, which may contain read or write locks.
-        :param timeout: while trying to acquire, the lock will expire
-            other unreleased write locks older than timeout.
-        """
-        ExclusiveLock.__init__(self, dir, timeout)
-        writeLockDir = os.path.join(self.dir, WriteLock.fileName)
-        self.writeLock = ExclusiveLock(writeLockDir, timeout)
-
-    def acquire(self, timeout=None):
-        """ Try to acquire a 'read' lock
-
-        To prevent race conditions, acquire first an exclusive lock,
-        then acquire a read lock. Finally release the exclusive lock so
-        other can have read lock, too.
-        """
-        if self._locked:
-            raise RuntimeError("lock already locked")
-        if self.writeLock.acquire(timeout):
-            try:
-                self.lockDir = tempfile.mkdtemp('', self.fileName, self.dir)
-                self._locked = True
-                logging.debug('acquired read lock: {0}'.format(self.lockDir))
-                return True
-            finally:
-                self.writeLock.release()
-        return False
-
-
-class LazyReadLock(ReadLock):
-    """ Lazy Read lock
-
-    See ReadLock, but we do an optimization here:
-    If (and ONLY if) the resource protected by this lock is updated in a POSIX
-    style "write new content to tmpfile, rename tmpfile -> origfile", then reading
-    from an open origfile handle will give either the old content (when opened
-    before the rename happens) or the new content (when opened after the rename
-    happened), but never cause any trouble. This means that we don't have to lock
-    at all in that case.
-
-    Of course this doesn't work for us on the win32 platform:
-
-    * using MoveFileEx requires opening the file with some FILE_SHARE_DELETE
-      mode - we currently don't do that
-
-    We currently solve by using the non-lazy locking code in ReadLock class.
-    """
-    def __init__(self, dir, timeout=None):
-        if sys.platform == 'win32':
-            ReadLock.__init__(self, dir, timeout)
-        else: # POSIX
-            self._locked = False
-
-    def acquire(self, timeout=None):
-        if sys.platform == 'win32':
-            return ReadLock.acquire(self, timeout)
-        else: # POSIX
-            self._locked = True
-            return True
-
-    def release(self):
-        if sys.platform == 'win32':
-            return ReadLock.release(self)
-        else:  # POSIX
-            self._locked = False
-
-    def exists(self):
-        if sys.platform == 'win32':
-            return ReadLock.exists(self)
-        else: # POSIX
-            return True
-
-    def isExpired(self):
-        if sys.platform == 'win32':
-            return ReadLock.isExpired(self)
-        else: # POSIX
-            return True
-
-    def expire(self):
-        if sys.platform == 'win32':
-            return ReadLock.expire(self)
-        else: # POSIX
-            return True
-
-class LazyWriteLock(WriteLock):
-    """ Lazy Write lock
-
-    See WriteLock and LazyReadLock docs.
-    """
-    def __init__(self, dir, timeout=None):
-        if sys.platform == 'win32':
-            WriteLock.__init__(self, dir, timeout)
-        else: # POSIX
-            self._locked = False
-
-    def acquire(self, timeout=None):
-        if sys.platform == 'win32':
-            return WriteLock.acquire(self, timeout)
-        else: # POSIX
-            self._locked = True
-            return True
-
-    def release(self):
-        if sys.platform == 'win32':
-            return WriteLock.release(self)
-        else:  # POSIX
-            self._locked = False
-
-    def exists(self):
-        if sys.platform == 'win32':
-            return WriteLock.exists(self)
-        else: # POSIX
-            return True
-
-    def isExpired(self):
-        if sys.platform == 'win32':
-            return WriteLock.isExpired(self)
-        else: # POSIX
-            return True
-
-    def expire(self):
-        if sys.platform == 'win32':
-            return WriteLock.expire(self)
-        else: # POSIX
-            return True
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.