mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-18 20:11:20 +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 sys
|
||||
import traceback
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime, timedelta
|
||||
from functools import reduce # pylint: disable=redefined-builtin
|
||||
from operator import mul
|
||||
from time import sleep
|
||||
if sys.version_info[0] == 3:
|
||||
from io import StringIO
|
||||
else:
|
||||
@ -54,6 +56,8 @@ from devlib.utils.misc import (ABI_MAP, check_output, walk_modules,
|
||||
|
||||
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
|
||||
def diff_tokens(before_token, after_token):
|
||||
@ -640,3 +644,43 @@ def format_ordered_dict(od):
|
||||
"""
|
||||
return '{{{}}}'.format(', '.join('{}={}'.format(k, v)
|
||||
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