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()
|
||||
|
||||
|
||||
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):
|
||||
with internal_lock(name):
|
||||
LOG.debug(_('Attempting to grab external lock "%(lock)s"'),
|
||||
{'lock': name})
|
||||
|
||||
# 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')
|
||||
|
||||
lock_file_path = os.path.join(CONF.lock_path, name)
|
||||
lock_file_path = _get_lock_path(name, lock_file_prefix)
|
||||
|
||||
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):
|
||||
with _semaphores_lock:
|
||||
try:
|
||||
|
||||
@@ -314,6 +314,21 @@ class LockTestCase(test.BaseTestCase):
|
||||
|
||||
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):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user