mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-31 02:01:16 +00:00
utils/misc: Add file locking context manager
Enable automation locking and unlocking of a file path provided. Used to prevent synchronisation issues between multiple wa processes.
This commit is contained in:
parent
0f9c20dc69
commit
d56f0fbe20
@ -30,9 +30,11 @@ import string
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from contextlib import contextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from functools import reduce # pylint: disable=redefined-builtin
|
from functools import reduce # pylint: disable=redefined-builtin
|
||||||
from operator import mul
|
from operator import mul
|
||||||
|
from time import sleep
|
||||||
if sys.version_info[0] == 3:
|
if sys.version_info[0] == 3:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
else:
|
else:
|
||||||
@ -54,6 +56,8 @@ from devlib.utils.misc import (ABI_MAP, check_output, walk_modules,
|
|||||||
|
|
||||||
check_output_logger = logging.getLogger('check_output')
|
check_output_logger = logging.getLogger('check_output')
|
||||||
|
|
||||||
|
file_lock_logger = logging.getLogger('file_lock')
|
||||||
|
|
||||||
|
|
||||||
# Defined here rather than in wa.exceptions due to module load dependencies
|
# Defined here rather than in wa.exceptions due to module load dependencies
|
||||||
def diff_tokens(before_token, after_token):
|
def diff_tokens(before_token, after_token):
|
||||||
@ -640,3 +644,43 @@ def format_ordered_dict(od):
|
|||||||
"""
|
"""
|
||||||
return '{{{}}}'.format(', '.join('{}={}'.format(k, v)
|
return '{{{}}}'.format(', '.join('{}={}'.format(k, v)
|
||||||
for k, v in od.items()))
|
for k, v in od.items()))
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def lock_file(path, timeout=30):
|
||||||
|
"""
|
||||||
|
Enable automatic locking and unlocking of a file path given. Used to
|
||||||
|
prevent synchronisation issues between multiple wa processes.
|
||||||
|
Uses a default timeout of 30 seconds which should be overridden for files
|
||||||
|
that are expect to be unavailable for longer periods of time.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Import here to avoid circular imports
|
||||||
|
# pylint: disable=wrong-import-position,cyclic-import
|
||||||
|
from wa.framework.exception import ResourceError
|
||||||
|
|
||||||
|
locked = False
|
||||||
|
l_file = '{}.lock'.format(path) if not path.endswith('.lock') else path
|
||||||
|
file_lock_logger.debug('Acquiring lock on "{}"'.format(l_file))
|
||||||
|
try:
|
||||||
|
while timeout:
|
||||||
|
try:
|
||||||
|
open(l_file, 'x').close()
|
||||||
|
locked = True
|
||||||
|
file_lock_logger.debug('Lock acquired on "{}"'.format(l_file))
|
||||||
|
break
|
||||||
|
except FileExistsError:
|
||||||
|
msg = 'Failed to acquire lock on "{}" Retrying...'
|
||||||
|
file_lock_logger.debug(msg.format(l_file))
|
||||||
|
sleep(1)
|
||||||
|
timeout -= 1
|
||||||
|
else:
|
||||||
|
msg = 'Failed to acquire lock file "{}" within the timeout. \n' \
|
||||||
|
'If there are no other running WA processes please delete ' \
|
||||||
|
'this file and retry.'
|
||||||
|
raise ResourceError(msg.format(os.path.abspath(l_file)))
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
if locked and os.path.exists(l_file):
|
||||||
|
os.remove(l_file)
|
||||||
|
file_lock_logger.debug('Lock released "{}"'.format(l_file))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user