mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 07:04:17 +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:
		| @@ -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)) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user