From 2c5f2f9a9a527e5b2b75917bb541fee23f2ff4d6 Mon Sep 17 00:00:00 2001 From: Vinicius Moreira Date: Wed, 16 Oct 2019 13:06:02 -0300 Subject: [PATCH] [flatpak] fix: runtimes update-checking for version 1.5.x | [cache] fix: thread lock --- CHANGELOG.md | 4 +++- bauh/app.py | 6 ++++-- bauh/gems/flatpak/flatpak.py | 5 ++++- bauh/view/util/cache.py | 41 ++++++++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51072d66..afae1a65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,9 +21,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - History panel can now me maximized, minimized and allows to copy column content. - It is possible to use custom tray icons via the environment variables: **BAUH_TRAY_DEFAULT_ICON_PATH** and ** **BAUH_TRAY_UPDATES_ICON_PATH** ( displayed when there are updates ) - Minor UI improvements -- CacheCleaner removed due to random crashes associated with Python threading lock ### Fixes +- cache thread lock that was hanging the application +- Flatpak: + - Runtimes update-checking for version 1.5.X - Snap: - retrieving installed applications information for Ubuntu based distros diff --git a/bauh/app.py b/bauh/app.py index c6d90b1a..4a332791 100755 --- a/bauh/app.py +++ b/bauh/app.py @@ -13,7 +13,7 @@ from bauh.view.core.downloader import AdaptableFileDownloader from bauh.view.qt.systray import TrayIcon from bauh.view.qt.window import ManageWindow from bauh.view.util import util, logs, resource -from bauh.view.util.cache import DefaultMemoryCacheFactory +from bauh.view.util.cache import DefaultMemoryCacheFactory, CacheCleaner from bauh.view.util.disk import DefaultDiskCacheLoaderFactory @@ -27,7 +27,8 @@ def main(): i18n_key, i18n = util.get_locale_keys(args.locale) - cache_factory = DefaultMemoryCacheFactory(expiration_time=args.cache_exp) + cache_cleaner = CacheCleaner() + cache_factory = DefaultMemoryCacheFactory(expiration_time=args.cache_exp, cleaner=cache_cleaner) icon_cache = cache_factory.new(args.icon_exp) http_client = HttpClient(logger) @@ -90,6 +91,7 @@ def main(): manage_window.refresh_apps() manage_window.show() + cache_cleaner.start() sys.exit(app.exec_()) diff --git a/bauh/gems/flatpak/flatpak.py b/bauh/gems/flatpak/flatpak.py index 13f6ca04..328adb78 100755 --- a/bauh/gems/flatpak/flatpak.py +++ b/bauh/gems/flatpak/flatpak.py @@ -163,7 +163,10 @@ def list_updates_as_str(version: str): updates = new_subprocess([BASE_CMD, 'update']).stdout out = StringIO() - for o in new_subprocess(['grep', '-E', r'[0-9]+.\s+(\w+|\.)+\s+\w+\s+(\w|\.)+', '-o', '--color=never'], stdin=updates).stdout: + + reg = r'[0-9]+\.\s+(\w+|\.)+\s+(\w|\.)+' if version >= '1.5.0' else r'[0-9]+\.\s+(\w+|\.)+\s+\w+\s+(\w|\.)+' + + for o in new_subprocess(['grep', '-E', reg, '-o', '--color=never'], stdin=updates).stdout: if o: out.write('/'.join(o.decode().strip().split('\t')[2:]) + '\n') diff --git a/bauh/view/util/cache.py b/bauh/view/util/cache.py index 45fb393b..df01734f 100644 --- a/bauh/view/util/cache.py +++ b/bauh/view/util/cache.py @@ -1,7 +1,6 @@ import datetime import time -from multiprocessing import Lock -from threading import Thread +from threading import Lock, Thread from bauh.api.abstract.cache import MemoryCache, MemoryCacheFactory @@ -33,14 +32,14 @@ class DefaultMemoryCache(MemoryCache): def add_non_existing(self, key: str, val: object): if key and self. is_enabled(): self.lock.acquire() - cur_val = self.get(key) + cur_val = self.get(key, lock=False) if cur_val is None: self._add(key, val) self.lock.release() - def get(self, key: str): + def get(self, key: str, lock: bool = True): if key and self.is_enabled(): val = self._cache.get(key) @@ -48,9 +47,14 @@ class DefaultMemoryCache(MemoryCache): expiration = val.get('expires_at') if expiration and expiration <= datetime.datetime.utcnow(): - self.lock.acquire() + if lock: + self.lock.acquire() + del self._cache[key] - self.lock.release() + + if lock: + self.lock.release() + return None return val['val'] @@ -71,15 +75,38 @@ class DefaultMemoryCache(MemoryCache): self.get(key) +class CacheCleaner(Thread): + + def __init__(self, check_interval: int = 15): + super(CacheCleaner, self).__init__(daemon=True) + self.caches = [] + self.check_interval = check_interval + + def register(self, cache: MemoryCache): + if cache.is_enabled(): + self.caches.append(cache) + + def run(self): + if self.caches: + while True: + for cache in self.caches: + cache.clean_expired() + + time.sleep(self.check_interval) + + class DefaultMemoryCacheFactory(MemoryCacheFactory): - def __init__(self, expiration_time: int): + def __init__(self, expiration_time: int, cleaner: CacheCleaner): """ :param expiration_time: default expiration time for all instantiated caches + :param cleaner """ super(DefaultMemoryCacheFactory, self).__init__() self.expiration_time = expiration_time + self.cleaner = cleaner def new(self, expiration: int = None) -> MemoryCache: instance = DefaultMemoryCache(expiration if expiration is not None else self.expiration_time) + self.cleaner.register(instance) return instance