diff options
Diffstat (limited to 'pycadf/openstack/common/lockutils.py')
-rw-r--r-- | pycadf/openstack/common/lockutils.py | 92 |
1 files changed, 20 insertions, 72 deletions
diff --git a/pycadf/openstack/common/lockutils.py b/pycadf/openstack/common/lockutils.py index 7bbb1d2..9814891 100644 --- a/pycadf/openstack/common/lockutils.py +++ b/pycadf/openstack/common/lockutils.py @@ -15,8 +15,8 @@ import contextlib import errno -import fcntl import functools +import logging import os import shutil import subprocess @@ -29,8 +29,7 @@ import weakref from oslo.config import cfg from pycadf.openstack.common import fileutils -from pycadf.openstack.common.gettextutils import _, _LE, _LI -from pycadf.openstack.common import log as logging +from pycadf.openstack.common._i18n import _, _LE, _LI LOG = logging.getLogger(__name__) @@ -102,10 +101,8 @@ class _FileLock(object): raise threading.ThreadError(_("Unable to acquire lock on" " `%(filename)s` due to" " %(exception)s") % - { - 'filename': self.fname, - 'exception': e, - }) + {'filename': self.fname, + 'exception': e}) def __enter__(self): self.acquire() @@ -149,56 +146,12 @@ class _FcntlLock(_FileLock): fcntl.lockf(self.lockfile, fcntl.LOCK_UN) -class _PosixLock(object): - def __init__(self, name): - # Hash the name because it's not valid to have POSIX semaphore - # names with things like / in them. Then use base64 to encode - # the digest() instead taking the hexdigest() because the - # result is shorter and most systems can't have shm sempahore - # names longer than 31 characters. - h = hashlib.sha1() - h.update(name.encode('ascii')) - self.name = str((b'/' + base64.urlsafe_b64encode( - h.digest())).decode('ascii')) - - def acquire(self, timeout=None): - self.semaphore = posix_ipc.Semaphore(self.name, - flags=posix_ipc.O_CREAT, - initial_value=1) - self.semaphore.acquire(timeout) - return self - - def __enter__(self): - self.acquire() - return self - - def release(self): - self.semaphore.release() - self.semaphore.close() - - def __exit__(self, exc_type, exc_val, exc_tb): - self.release() - - def exists(self): - try: - semaphore = posix_ipc.Semaphore(self.name) - except posix_ipc.ExistentialError: - return False - else: - semaphore.close() - return True - - if os.name == 'nt': import msvcrt InterProcessLock = _WindowsLock - FileLock = _WindowsLock else: - import base64 - import hashlib - import posix_ipc - InterProcessLock = _PosixLock - FileLock = _FcntlLock + import fcntl + InterProcessLock = _FcntlLock _semaphores = weakref.WeakValueDictionary() _semaphores_lock = threading.Lock() @@ -215,11 +168,7 @@ def _get_lock_path(name, lock_file_prefix, lock_path=None): local_lock_path = lock_path or CONF.lock_path if not local_lock_path: - # NOTE(bnemec): Create a fake lock path for posix locks so we don't - # unnecessarily raise the RequiredOptError below. - if InterProcessLock is not _PosixLock: - raise cfg.RequiredOptError('lock_path') - local_lock_path = 'posixlock:/' + raise cfg.RequiredOptError('lock_path') return os.path.join(local_lock_path, name) @@ -230,16 +179,11 @@ def external_lock(name, lock_file_prefix=None, lock_path=None): lock_file_path = _get_lock_path(name, lock_file_prefix, lock_path) - # NOTE(bnemec): If an explicit lock_path was passed to us then it - # means the caller is relying on file-based locking behavior, so - # we can't use posix locks for those calls. - if lock_path: - return FileLock(lock_file_path) return InterProcessLock(lock_file_path) def remove_external_lock_file(name, lock_file_prefix=None): - """Remove a external lock file when it's not used anymore + """Remove an external lock file when it's not used anymore This will be helpful when we have a lot of lock files """ with internal_lock(name): @@ -255,11 +199,12 @@ def internal_lock(name): with _semaphores_lock: try: sem = _semaphores[name] + LOG.debug('Using existing semaphore "%s"', name) except KeyError: sem = threading.Semaphore() _semaphores[name] = sem + LOG.debug('Created new semaphore "%s"', name) - LOG.debug('Got semaphore "%(lock)s"', {'lock': name}) return sem @@ -281,13 +226,16 @@ def lock(name, lock_file_prefix=None, external=False, lock_path=None): """ int_lock = internal_lock(name) with int_lock: - if external and not CONF.disable_process_locking: - ext_lock = external_lock(name, lock_file_prefix, lock_path) - with ext_lock: - yield ext_lock - else: - yield int_lock - LOG.debug('Released semaphore "%(lock)s"', {'lock': name}) + LOG.debug('Acquired semaphore "%(lock)s"', {'lock': name}) + try: + if external and not CONF.disable_process_locking: + ext_lock = external_lock(name, lock_file_prefix, lock_path) + with ext_lock: + yield ext_lock + else: + yield int_lock + finally: + LOG.debug('Releasing semaphore "%(lock)s"', {'lock': name}) def synchronized(name, lock_file_prefix=None, external=False, lock_path=None): |