Update openstack/common/lockutils
The following commits are in this update: 79e6bc6 fix lockutils.lock() to make it thread-safe ace5120 Add main() to lockutils that creates temp dir for locks 537d8e2 Allow lockutils to get lock_path conf from envvar Change-Id: Id50b7c0ccbb417493320e19191a92675fcf126ff
This commit is contained in:
parent
8338bdc992
commit
2f44ed535f
@ -20,6 +20,10 @@ import contextlib
|
|||||||
import errno
|
import errno
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import weakref
|
import weakref
|
||||||
@ -39,6 +43,7 @@ util_opts = [
|
|||||||
cfg.BoolOpt('disable_process_locking', default=False,
|
cfg.BoolOpt('disable_process_locking', default=False,
|
||||||
help='Whether to disable inter-process locks'),
|
help='Whether to disable inter-process locks'),
|
||||||
cfg.StrOpt('lock_path',
|
cfg.StrOpt('lock_path',
|
||||||
|
default=os.environ.get("MARCONI_LOCK_PATH"),
|
||||||
help=('Directory to use for lock files.'))
|
help=('Directory to use for lock files.'))
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -131,6 +136,7 @@ else:
|
|||||||
InterProcessLock = _PosixLock
|
InterProcessLock = _PosixLock
|
||||||
|
|
||||||
_semaphores = weakref.WeakValueDictionary()
|
_semaphores = weakref.WeakValueDictionary()
|
||||||
|
_semaphores_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@ -153,14 +159,11 @@ def lock(name, lock_file_prefix=None, external=False, lock_path=None):
|
|||||||
special location for external lock files to live. If nothing is set, then
|
special location for external lock files to live. If nothing is set, then
|
||||||
CONF.lock_path is used as a default.
|
CONF.lock_path is used as a default.
|
||||||
"""
|
"""
|
||||||
# NOTE(soren): If we ever go natively threaded, this will be racy.
|
with _semaphores_lock:
|
||||||
# See http://stackoverflow.com/questions/5390569/dyn
|
try:
|
||||||
# amically-allocating-and-destroying-mutexes
|
sem = _semaphores[name]
|
||||||
sem = _semaphores.get(name, threading.Semaphore())
|
except KeyError:
|
||||||
if name not in _semaphores:
|
sem = threading.Semaphore()
|
||||||
# this check is not racy - we're already holding ref locally
|
|
||||||
# so GC won't remove the item and there was no IO switch
|
|
||||||
# (only valid in greenthreads)
|
|
||||||
_semaphores[name] = sem
|
_semaphores[name] = sem
|
||||||
|
|
||||||
with sem:
|
with sem:
|
||||||
@ -241,11 +244,12 @@ def synchronized(name, lock_file_prefix=None, external=False, lock_path=None):
|
|||||||
def wrap(f):
|
def wrap(f):
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
def inner(*args, **kwargs):
|
def inner(*args, **kwargs):
|
||||||
|
try:
|
||||||
with lock(name, lock_file_prefix, external, lock_path):
|
with lock(name, lock_file_prefix, external, lock_path):
|
||||||
LOG.debug(_('Got semaphore / lock "%(function)s"'),
|
LOG.debug(_('Got semaphore / lock "%(function)s"'),
|
||||||
{'function': f.__name__})
|
{'function': f.__name__})
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
|
finally:
|
||||||
LOG.debug(_('Semaphore / lock released "%(function)s"'),
|
LOG.debug(_('Semaphore / lock released "%(function)s"'),
|
||||||
{'function': f.__name__})
|
{'function': f.__name__})
|
||||||
return inner
|
return inner
|
||||||
@ -275,3 +279,27 @@ def synchronized_with_prefix(lock_file_prefix):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return functools.partial(synchronized, lock_file_prefix=lock_file_prefix)
|
return functools.partial(synchronized, lock_file_prefix=lock_file_prefix)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
"""Create a dir for locks and pass it to command from arguments
|
||||||
|
|
||||||
|
If you run this:
|
||||||
|
python -m openstack.common.lockutils python setup.py testr <etc>
|
||||||
|
|
||||||
|
a temporary directory will be created for all your locks and passed to all
|
||||||
|
your tests in an environment variable. The temporary dir will be deleted
|
||||||
|
afterwards and the return value will be preserved.
|
||||||
|
"""
|
||||||
|
|
||||||
|
lock_dir = tempfile.mkdtemp()
|
||||||
|
os.environ["MARCONI_LOCK_PATH"] = lock_dir
|
||||||
|
try:
|
||||||
|
ret_val = subprocess.call(argv[1:])
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(lock_dir, ignore_errors=True)
|
||||||
|
return ret_val
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main(sys.argv))
|
||||||
|
Loading…
Reference in New Issue
Block a user