mirror of
				https://github.com/ARM-software/workload-automation.git
				synced 2025-10-31 15:12:25 +00:00 
			
		
		
		
	Implement caching of ApkInfo
Allow caching of ApkInfo to prevent the requirement of re-parsing of APK files.
This commit is contained in:
		| @@ -19,8 +19,7 @@ from datetime import datetime | ||||
|  | ||||
| from devlib.utils.android import ApkInfo as _ApkInfo | ||||
|  | ||||
| from wa import settings | ||||
| from wa.framework.exception import ConfigError | ||||
| from wa.framework.configuration import settings | ||||
| from wa.utils.serializer import read_pod, write_pod, Podable | ||||
| from wa.utils.types import enum | ||||
| from wa.utils.misc import lock_file | ||||
| @@ -30,7 +29,10 @@ LogcatLogLevel = enum(['verbose', 'debug', 'info', 'warn', 'error', 'assert'], s | ||||
|  | ||||
| log_level_map = ''.join(n[0].upper() for n in LogcatLogLevel.names) | ||||
|  | ||||
| logger = logging.getLogger('logcat') | ||||
| logcat_logger = logging.getLogger('logcat') | ||||
| apk_info_cache_logger = logging.getLogger('apk_info_cache') | ||||
|  | ||||
| apk_info_cache = None | ||||
|  | ||||
|  | ||||
| class LogcatEvent(object): | ||||
| @@ -81,14 +83,15 @@ class LogcatParser(object): | ||||
|             tag = (parts.pop(0) if parts else '').strip() | ||||
|         except Exception as e:  # pylint: disable=broad-except | ||||
|             message = 'Invalid metadata for line:\n\t{}\n\tgot: "{}"' | ||||
|             logger.warning(message.format(line, e)) | ||||
|             logcat_logger.warning(message.format(line, e)) | ||||
|             return None | ||||
|  | ||||
|         return LogcatEvent(timestamp, pid, tid, level, tag, message) | ||||
|  | ||||
|  | ||||
| # pylint: disable=protected-access,attribute-defined-outside-init | ||||
| class ApkInfo(_ApkInfo, Podable): | ||||
|     # Implement ApkInfo as a Podable class. | ||||
|     '''Implement ApkInfo as a Podable class.''' | ||||
|  | ||||
|     _pod_serialization_version = 1 | ||||
|  | ||||
| @@ -132,3 +135,66 @@ class ApkInfo(_ApkInfo, Podable): | ||||
|         pod['_pod_version'] = pod.get('_pod_version', 1) | ||||
|         return pod | ||||
|  | ||||
|  | ||||
| class ApkInfoCache: | ||||
|  | ||||
|     @staticmethod | ||||
|     def _check_env(): | ||||
|         if not os.path.exists(settings.cache_directory): | ||||
|             os.makedirs(settings.cache_directory) | ||||
|  | ||||
|     def __init__(self, path=settings.apk_info_cache_file): | ||||
|         self._check_env() | ||||
|         self.path = path | ||||
|         self.last_modified = None | ||||
|         self.cache = {} | ||||
|         self._update_cache() | ||||
|  | ||||
|     def store(self, apk_info, apk_id, overwrite=True): | ||||
|         self._update_cache() | ||||
|         if apk_id in self.cache and not overwrite: | ||||
|             raise ValueError('ApkInfo for {} is already in cache.'.format(apk_info.path)) | ||||
|         self.cache[apk_id] = apk_info.to_pod() | ||||
|         with lock_file(self.path): | ||||
|             write_pod(self.cache, self.path) | ||||
|             self.last_modified = os.stat(self.path) | ||||
|  | ||||
|     def get_info(self, key): | ||||
|         self._update_cache() | ||||
|         pod = self.cache.get(key) | ||||
|  | ||||
|         info = ApkInfo.from_pod(pod) if pod else None | ||||
|         return info | ||||
|  | ||||
|     def _update_cache(self): | ||||
|         if not os.path.exists(self.path): | ||||
|             return | ||||
|         if self.last_modified != os.stat(self.path): | ||||
|             apk_info_cache_logger.debug('Updating cache {}'.format(self.path)) | ||||
|             with lock_file(self.path): | ||||
|                 self.cache = read_pod(self.path) | ||||
|                 self.last_modified = os.stat(self.path) | ||||
|  | ||||
|  | ||||
| def get_cacheable_apk_info(path): | ||||
|     # pylint: disable=global-statement | ||||
|     global apk_info_cache | ||||
|     if not path: | ||||
|         return | ||||
|     stat = os.stat(path) | ||||
|     modified = stat.st_mtime | ||||
|     apk_id = '{}-{}'.format(path, modified) | ||||
|     info = apk_info_cache.get_info(apk_id) | ||||
|  | ||||
|     if info: | ||||
|         msg = 'Using ApkInfo ({}) from cache'.format(info.package) | ||||
|     else: | ||||
|         with lock_file(path): | ||||
|             info = ApkInfo(path) | ||||
|         apk_info_cache.store(info, apk_id, overwrite=True) | ||||
|         msg = 'Storing ApkInfo ({}) in cache'.format(info.package) | ||||
|     apk_info_cache_logger.debug(msg) | ||||
|     return info | ||||
|  | ||||
|  | ||||
| apk_info_cache = ApkInfoCache() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user