Add remove external lock files API in lockutils
when external lock are used, there will be a lock files which is used for external file lock, it will not be removed and remain forever. it will be a problem when tens of thousands of this kind of actions. Add a API to allow other component to remove lock file internal lock will be acquired before further action Change-Id: I4d996b91bcc55becb0ebf4ec77ac80546f433ae9 Closes-Bug: 1256306
This commit is contained in:
@@ -143,26 +143,43 @@ _semaphores = weakref.WeakValueDictionary()
|
|||||||
_semaphores_lock = threading.Lock()
|
_semaphores_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
||||||
|
def _get_lock_path(name, lock_file_prefix):
|
||||||
|
# NOTE(mikal): the lock name cannot contain directory
|
||||||
|
# separators
|
||||||
|
name = name.replace(os.sep, '_')
|
||||||
|
if lock_file_prefix:
|
||||||
|
sep = '' if lock_file_prefix.endswith('-') else '-'
|
||||||
|
name = '%s%s%s' % (lock_file_prefix, sep, name)
|
||||||
|
|
||||||
|
if not CONF.lock_path:
|
||||||
|
raise cfg.RequiredOptError('lock_path')
|
||||||
|
|
||||||
|
return os.path.join(CONF.lock_path, name)
|
||||||
|
|
||||||
|
|
||||||
def external_lock(name, lock_file_prefix=None):
|
def external_lock(name, lock_file_prefix=None):
|
||||||
with internal_lock(name):
|
with internal_lock(name):
|
||||||
LOG.debug(_('Attempting to grab external lock "%(lock)s"'),
|
LOG.debug(_('Attempting to grab external lock "%(lock)s"'),
|
||||||
{'lock': name})
|
{'lock': name})
|
||||||
|
|
||||||
# NOTE(mikal): the lock name cannot contain directory
|
lock_file_path = _get_lock_path(name, lock_file_prefix)
|
||||||
# separators
|
|
||||||
name = name.replace(os.sep, '_')
|
|
||||||
if lock_file_prefix:
|
|
||||||
sep = '' if lock_file_prefix.endswith('-') else '-'
|
|
||||||
name = '%s%s%s' % (lock_file_prefix, sep, name)
|
|
||||||
|
|
||||||
if not CONF.lock_path:
|
|
||||||
raise cfg.RequiredOptError('lock_path')
|
|
||||||
|
|
||||||
lock_file_path = os.path.join(CONF.lock_path, name)
|
|
||||||
|
|
||||||
return InterProcessLock(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
|
||||||
|
This will be helpful when we have a lot of lock files
|
||||||
|
"""
|
||||||
|
with internal_lock(name):
|
||||||
|
lock_file_path = _get_lock_path(name, lock_file_prefix)
|
||||||
|
try:
|
||||||
|
os.remove(lock_file_path)
|
||||||
|
except OSError:
|
||||||
|
LOG.info(_('Failed to remove file %(file)s'),
|
||||||
|
{'file': lock_file_path})
|
||||||
|
|
||||||
|
|
||||||
def internal_lock(name):
|
def internal_lock(name):
|
||||||
with _semaphores_lock:
|
with _semaphores_lock:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -314,6 +314,21 @@ class LockTestCase(test.BaseTestCase):
|
|||||||
|
|
||||||
self.assertRaises(cfg.RequiredOptError, foo)
|
self.assertRaises(cfg.RequiredOptError, foo)
|
||||||
|
|
||||||
|
def test_remove_lock_external_file(self):
|
||||||
|
lock_name = 'mylock'
|
||||||
|
lock_pfix = 'mypfix-remove-lock-test-'
|
||||||
|
|
||||||
|
lock_dir = tempfile.mkdtemp()
|
||||||
|
self.config(lock_path=lock_dir)
|
||||||
|
|
||||||
|
lockutils.remove_external_lock_file(lock_name, lock_pfix)
|
||||||
|
|
||||||
|
for ent in os.listdir(lock_dir):
|
||||||
|
self.assertRaises(OSError, ent.startswith, lock_pfix)
|
||||||
|
|
||||||
|
if os.path.exists(lock_dir):
|
||||||
|
shutil.rmtree(lock_dir, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
class LockutilsModuleTestCase(test.BaseTestCase):
|
class LockutilsModuleTestCase(test.BaseTestCase):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user