mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 01:14:15 +02:00
fix: disk loader not fiiling all requested cached data from the disk
This commit is contained in:
@@ -15,11 +15,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- "Application settings" button located in right lower corner
|
||||
- Package "Name" filter field (above the packages table)
|
||||
- Showing the number of packages being shown by the total found
|
||||
- "Show" button for large fields of the "Info" window
|
||||
|
||||
### Improvements:
|
||||
- Reading installed Snaps now takes around 95% less time
|
||||
- Reading installed Flatpaks now takes around 45% less time
|
||||
- Refreshing only the associated package type after a successful operation (install, uninstall, downgrade, ...)
|
||||
- When a package is installed, it will be the first element of the table after refreshing
|
||||
- Progress bar status can now be controlled by the software manager while an operation is being executed
|
||||
- Flatpak: showing runtime branches as versions when they are not available
|
||||
|
||||
@@ -32,6 +34,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
### Fixes:
|
||||
- cached Flatpak app current version
|
||||
- disk loader not filling all requested cached data from the disk
|
||||
|
||||
### Code
|
||||
- Code was internally modularized as: "api" (conceptual classes used to create custom software managers), "gems" (software managers), "commons" (common classes shared between the UI and "gems")
|
||||
|
||||
@@ -30,7 +30,7 @@ context = ApplicationContext(i18n=i18n,
|
||||
download_icons=args.download_icons,
|
||||
app_root_dir=ROOT_DIR,
|
||||
cache_factory=cache_factory,
|
||||
disk_loader_factory=DefaultDiskCacheLoaderFactory(disk_cache_enabled=args.disk_cache),
|
||||
disk_loader_factory=DefaultDiskCacheLoaderFactory(disk_cache_enabled=args.disk_cache, logger=logger),
|
||||
logger=logger)
|
||||
user_config = config.read()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import time
|
||||
from argparse import Namespace
|
||||
from threading import Thread
|
||||
from typing import List, Set, Type
|
||||
@@ -20,6 +21,8 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
self.thread_prepare = None
|
||||
self.i18n = context.i18n
|
||||
self.disk_loader_factory = context.disk_loader_factory
|
||||
self.logger = context.logger
|
||||
self._already_prepared = []
|
||||
|
||||
def reset_cache(self):
|
||||
if self._available_map is not None:
|
||||
@@ -66,6 +69,7 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
res.new.extend(apps_found.new)
|
||||
|
||||
def search(self, word: str, disk_loader: DiskCacheLoader = None, limit: int = -1) -> SearchResult:
|
||||
ti = time.time()
|
||||
self._wait_to_be_ready()
|
||||
|
||||
res = SearchResult([], [], 0)
|
||||
@@ -85,13 +89,15 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
t.join()
|
||||
|
||||
if disk_loader:
|
||||
disk_loader.stop = True
|
||||
disk_loader.stop_working()
|
||||
disk_loader.join()
|
||||
|
||||
res.installed = self._sort(res.installed, norm_word)
|
||||
res.new = self._sort(res.new, norm_word)
|
||||
res.total = len(res.installed) + len(res.new)
|
||||
|
||||
tf = time.time()
|
||||
self.logger.info('Took {0:.2f} seconds'.format(tf - ti))
|
||||
return res
|
||||
|
||||
def _wait_to_be_ready(self):
|
||||
@@ -106,6 +112,7 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
return True
|
||||
|
||||
def read_installed(self, disk_loader: DiskCacheLoader = None, limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None) -> SearchResult:
|
||||
ti = time.time()
|
||||
self._wait_to_be_ready()
|
||||
|
||||
res = SearchResult([], None, 0)
|
||||
@@ -138,9 +145,11 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
res.total += man_res.total
|
||||
|
||||
if disk_loader:
|
||||
disk_loader.stop = True
|
||||
disk_loader.stop_working()
|
||||
disk_loader.join()
|
||||
|
||||
tf = time.time()
|
||||
self.logger.info('Took {0:.2f} seconds'.format(tf - ti))
|
||||
return res
|
||||
|
||||
def downgrade(self, app: SoftwarePackage, root_password: str, handler: ProcessWatcher) -> bool:
|
||||
@@ -221,8 +230,9 @@ class GenericSoftwareManager(SoftwareManager):
|
||||
def _prepare(self):
|
||||
if self.managers:
|
||||
for man in self.managers:
|
||||
if self._can_work(man):
|
||||
if man not in self._already_prepared and self._can_work(man):
|
||||
man.prepare()
|
||||
self._already_prepared.append(man)
|
||||
|
||||
def prepare(self):
|
||||
self.thread_prepare = Thread(target=self._prepare)
|
||||
|
||||
@@ -100,13 +100,13 @@ class ArchManager(SoftwareManager):
|
||||
|
||||
if pkgsinfo:
|
||||
for pkgdata in pkgsinfo:
|
||||
app = self.mapper.map_api_data(pkgdata, not_signed)
|
||||
app.downgrade_enabled = downgrade_enabled
|
||||
pkg = self.mapper.map_api_data(pkgdata, not_signed)
|
||||
pkg.downgrade_enabled = downgrade_enabled
|
||||
if disk_loader:
|
||||
disk_loader.fill(app)
|
||||
app.status = PackageStatus.READY
|
||||
disk_loader.fill(pkg)
|
||||
pkg.status = PackageStatus.READY
|
||||
|
||||
apps.append(app)
|
||||
apps.append(pkg)
|
||||
|
||||
def _fill_mirror_pkgs(self, mirrors: dict, apps: list):
|
||||
# TODO
|
||||
@@ -203,8 +203,8 @@ class ArchManager(SoftwareManager):
|
||||
watcher.change_progress(50)
|
||||
|
||||
if info.get('required by'):
|
||||
pkname = '"{}"'.format(pkg.name)
|
||||
msg = '{}:\n\n{}\n\n{}'.format(self.i18n['arch.uninstall.required_by'].format(pkname), info['required by'], self.i18n['arch.uninstall.required_by.advice'].format(pkname))
|
||||
pkname = bold(pkg.name)
|
||||
msg = '{}:<br/><br/>{}<br/><br/>{}'.format(self.i18n['arch.uninstall.required_by'].format(pkname), bold(info['required by']), self.i18n['arch.uninstall.required_by.advice'].format(pkname))
|
||||
watcher.show_message(title=self.i18n['error'], body=msg, type_=MessageType.WARNING)
|
||||
return False
|
||||
|
||||
@@ -537,7 +537,6 @@ class ArchManager(SoftwareManager):
|
||||
|
||||
def prepare(self):
|
||||
self.dcache_updater.start()
|
||||
|
||||
self.aur_index_updater.start()
|
||||
|
||||
def list_updates(self) -> List[PackageUpdate]:
|
||||
|
||||
@@ -22,7 +22,6 @@ class AURIndexUpdater(Thread):
|
||||
self.man = man
|
||||
|
||||
def run(self):
|
||||
|
||||
while True:
|
||||
self.logger.info('Pre-indexing AUR packages in memory')
|
||||
res = self.http_client.get(URL_INDEX)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from threading import Thread, Lock
|
||||
from typing import Type, Dict
|
||||
|
||||
@@ -10,13 +12,15 @@ from bauh.api.abstract.model import SoftwarePackage
|
||||
|
||||
class AsyncDiskCacheLoader(Thread, DiskCacheLoader):
|
||||
|
||||
def __init__(self, enabled: bool, cache_map: Dict[Type[SoftwarePackage], MemoryCache]):
|
||||
def __init__(self, enabled: bool, cache_map: Dict[Type[SoftwarePackage], MemoryCache], logger: logging.Logger):
|
||||
super(AsyncDiskCacheLoader, self).__init__(daemon=True)
|
||||
self.apps = []
|
||||
self.stop = False
|
||||
self.pkgs = []
|
||||
self._work = True
|
||||
self.lock = Lock()
|
||||
self.cache_map = cache_map
|
||||
self.enabled = enabled
|
||||
self.logger = logger
|
||||
self.processed = 0
|
||||
|
||||
def fill(self, pkg: SoftwarePackage):
|
||||
"""
|
||||
@@ -24,25 +28,28 @@ class AsyncDiskCacheLoader(Thread, DiskCacheLoader):
|
||||
:param pkg:
|
||||
:return:
|
||||
"""
|
||||
if self.enabled:
|
||||
if pkg and pkg.supports_disk_cache():
|
||||
self.lock.acquire()
|
||||
self.apps.append(pkg)
|
||||
self.lock.release()
|
||||
if self.enabled and pkg and pkg.supports_disk_cache():
|
||||
self.pkgs.append(pkg)
|
||||
|
||||
def stop_working(self):
|
||||
self._work = False
|
||||
|
||||
def run(self):
|
||||
if self.enabled:
|
||||
last = 0
|
||||
|
||||
while True:
|
||||
if self.apps:
|
||||
self.lock.acquire()
|
||||
app = self.apps[0]
|
||||
del self.apps[0]
|
||||
self.lock.release()
|
||||
self._fill_cached_data(app)
|
||||
elif self.stop:
|
||||
time.sleep(0.00001)
|
||||
if len(self.pkgs) > self.processed:
|
||||
pkg = self.pkgs[last]
|
||||
|
||||
self._fill_cached_data(pkg)
|
||||
self.processed += 1
|
||||
last += 1
|
||||
elif not self._work:
|
||||
break
|
||||
|
||||
def _fill_cached_data(self, pkg: SoftwarePackage):
|
||||
def _fill_cached_data(self, pkg: SoftwarePackage) -> bool:
|
||||
if self.enabled:
|
||||
if os.path.exists(pkg.get_disk_data_path()):
|
||||
with open(pkg.get_disk_data_path()) as f:
|
||||
@@ -54,12 +61,16 @@ class AsyncDiskCacheLoader(Thread, DiskCacheLoader):
|
||||
if cache:
|
||||
cache.add_non_existing(pkg.id, cached_data)
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class DefaultDiskCacheLoaderFactory(DiskCacheLoaderFactory):
|
||||
|
||||
def __init__(self, disk_cache_enabled: bool):
|
||||
def __init__(self, disk_cache_enabled: bool, logger: logging.Logger):
|
||||
super(DefaultDiskCacheLoaderFactory, self).__init__()
|
||||
self.disk_cache_enabled = disk_cache_enabled
|
||||
self.logger = logger
|
||||
self.cache_map = {}
|
||||
|
||||
def map(self, pkg_type: Type[SoftwarePackage], cache: MemoryCache):
|
||||
@@ -68,4 +79,4 @@ class DefaultDiskCacheLoaderFactory(DiskCacheLoaderFactory):
|
||||
self.cache_map[pkg_type] = cache
|
||||
|
||||
def new(self) -> AsyncDiskCacheLoader:
|
||||
return AsyncDiskCacheLoader(enabled=self.disk_cache_enabled, cache_map=self.cache_map)
|
||||
return AsyncDiskCacheLoader(enabled=self.disk_cache_enabled, cache_map=self.cache_map, logger=self.logger)
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import List, Type, Set
|
||||
from PyQt5.QtCore import QEvent, Qt, QSize, pyqtSignal
|
||||
from PyQt5.QtGui import QIcon, QWindowStateChangeEvent, QPixmap, QCursor
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QCheckBox, QHeaderView, QToolBar, \
|
||||
QLabel, QPlainTextEdit, QLineEdit, QProgressBar, QPushButton, QComboBox, QMenu, QAction
|
||||
QLabel, QPlainTextEdit, QLineEdit, QProgressBar, QPushButton, QComboBox, QMenu, QAction, QApplication
|
||||
|
||||
from bauh.api.abstract.cache import MemoryCache
|
||||
from bauh.api.abstract.context import ApplicationContext
|
||||
@@ -231,7 +231,8 @@ class ManageWindow(QWidget):
|
||||
self.toolbar_bottom.addWidget(new_spacer())
|
||||
|
||||
self.progress_bar = QProgressBar()
|
||||
self.progress_bar.setMaximumHeight(7)
|
||||
self.progress_bar.setMaximumHeight(10 if QApplication.instance().style().objectName().lower() == 'windows' else 4)
|
||||
|
||||
self.progress_bar.setTextVisible(False)
|
||||
self.ref_progress_bar = self.toolbar_bottom.addWidget(self.progress_bar)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user