From b730873383f9b6205f0993fe5507a69da7e2bc47 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Thu, 22 Aug 2024 12:48:47 +0500 Subject: [PATCH] UI: AppInfoManager: Simplify old apps purging --- src/ui/appinfo/appinfomanager.cpp | 74 ++++++++++++++++--------------- src/ui/appinfo/appinfomanager.h | 13 +++--- src/ui/appinfo/migrations/1.sql | 10 ++--- src/ui/rpc/appinfomanagerrpc.h | 3 -- 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/ui/appinfo/appinfomanager.cpp b/src/ui/appinfo/appinfomanager.cpp index 7acbd65a..9d80aab9 100644 --- a/src/ui/appinfo/appinfomanager.cpp +++ b/src/ui/appinfo/appinfomanager.cpp @@ -16,18 +16,15 @@ namespace { const QLoggingCategory LC("appInfo"); -constexpr int DATABASE_USER_VERSION = 6; +constexpr int DATABASE_USER_VERSION = 7; -constexpr int APP_CACHE_MAX_COUNT = 2000; +constexpr int APP_CACHE_MAX_COUNT = 3000; +constexpr int APP_PURGE_INTERVAL = 3000; // 3 seconds const char *const sqlSelectAppInfo = "SELECT alt_path, file_descr, company_name," " product_name, product_ver, file_mod_time, icon_id" " FROM app WHERE path = ?1;"; -const char *const sqlUpdateAppAccessTime = "UPDATE app" - " SET access_time = datetime('now')" - " WHERE path = ?1;"; - const char *const sqlSelectIconImage = "SELECT image FROM icon WHERE icon_id = ?1;"; const char *const sqlSelectIconIdByHash = "SELECT icon_id FROM icon WHERE hash = ?1;"; @@ -40,15 +37,14 @@ const char *const sqlUpdateIconRefCount = "UPDATE icon" " WHERE icon_id = ?1;"; const char *const sqlInsertAppInfo = "INSERT INTO app(path, alt_path, file_descr, company_name," - " product_name, product_ver, file_mod_time," - " icon_id, access_time)" - " VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, datetime('now'));"; + " product_name, product_ver, file_mod_time, icon_id)" + " VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);"; const char *const sqlSelectAppCount = "SELECT count(*) FROM app;"; -const char *const sqlSelectAppOlds = "SELECT path, icon_id" +const char *const sqlSelectOldApps = "SELECT path, icon_id" " FROM app" - " ORDER BY access_time DESC" + " ORDER BY app_id" " LIMIT ?1;"; const char *const sqlDeleteIconIfNotUsed = "DELETE FROM icon" @@ -59,9 +55,13 @@ const char *const sqlDeleteApp = "DELETE FROM app WHERE path = ?1;"; } AppInfoManager::AppInfoManager(const QString &filePath, QObject *parent, quint32 openFlags) : - WorkerManager(parent), m_sqliteDb(new SqliteDb(filePath, openFlags)) + WorkerManager(parent), + m_appsPurgeTimer(APP_PURGE_INTERVAL), + m_sqliteDb(new SqliteDb(filePath, openFlags)) { setMaxWorkersCount(1); + + connect(&m_appsPurgeTimer, &QTimer::timeout, this, &AppInfoManager::purgeApps); } void AppInfoManager::setUp() @@ -127,17 +127,9 @@ bool AppInfoManager::loadInfoFromDb(const QString &appPath, AppInfo &appInfo) appInfo.fileModTime = stmt.columnDateTime(5); appInfo.iconId = stmt.columnInt64(6); - // Update last access time - updateAppAccessTime(appPath); - return true; } -void AppInfoManager::updateAppAccessTime(const QString &appPath) -{ - DbQuery(sqliteDb()).sql(sqlUpdateAppAccessTime).vars({ appPath }).executeOk(); -} - bool AppInfoManager::setupDb() { if (!sqliteDb()->open()) { @@ -196,14 +188,25 @@ void AppInfoManager::saveAppInfo( DbQuery(sqliteDb(), &ok).sql(sqlInsertAppInfo).vars(vars).executeOk(); } -void AppInfoManager::deleteExcessAppInfos() +void AppInfoManager::emitAppsPurge() { + QMetaObject::invokeMethod(&m_appsPurgeTimer, &TriggerTimer::startTrigger, Qt::QueuedConnection); +} + +void AppInfoManager::purgeApps() +{ + QMutexLocker locker(&m_mutex); + + sqliteDb()->beginWriteTransaction(); + const int appCount = DbQuery(sqliteDb()).sql(sqlSelectAppCount).execute().toInt(); const int excessCount = appCount - APP_CACHE_MAX_COUNT; if (excessCount > 0) { deleteOldApps(excessCount); } + + sqliteDb()->commitTransaction(); } QImage AppInfoManager::loadIconFromDb(qint64 iconId) @@ -240,8 +243,8 @@ bool AppInfoManager::saveToDb(const QString &appPath, AppInfo &appInfo, const QI if (ok) { appInfo.iconId = iconId.toLongLong(); - // Delete excess info - deleteExcessAppInfos(); + // Delete excess infos later + emitAppsPurge(); } return ok; @@ -258,9 +261,16 @@ void AppInfoManager::deleteAppInfo(const QString &appPath, const AppInfo &appInf iconIds.insert(appInfo.iconId, 1); } - QMutexLocker locker(&m_mutex); + // Delete app info & icon + { + QMutexLocker locker(&m_mutex); - deleteAppsAndIcons(appPaths, iconIds); + sqliteDb()->beginWriteTransaction(); + + deleteAppsAndIcons(appPaths, iconIds); + + sqliteDb()->commitTransaction(); + } } void AppInfoManager::deleteOldApps(int limitCount) @@ -281,12 +291,10 @@ void AppInfoManager::getOldAppsAndIcons( QStringList &appPaths, QHash &iconIds, int limitCount) const { SqliteStmt stmt; - if (!stmt.prepare(sqliteDb()->db(), sqlSelectAppOlds, SqliteStmt::PreparePersistent)) + if (!stmt.prepare(sqliteDb()->db(), sqlSelectOldApps, SqliteStmt::PreparePersistent)) return; - if (limitCount != 0) { - stmt.bindInt(1, limitCount); - } + stmt.bindInt(1, limitCount); while (stmt.step() == SqliteStmt::StepRow) { const QString appPath = stmt.columnText(0); @@ -298,13 +306,11 @@ void AppInfoManager::getOldAppsAndIcons( } } -bool AppInfoManager::deleteAppsAndIcons( +void AppInfoManager::deleteAppsAndIcons( const QStringList &appPaths, const QHash &iconIds) { bool ok = false; - sqliteDb()->beginWriteTransaction(); - // Delete old icons deleteIcons(iconIds, ok); @@ -312,10 +318,6 @@ bool AppInfoManager::deleteAppsAndIcons( if (ok) { deleteApps(appPaths, ok); } - - sqliteDb()->endTransaction(ok); - - return ok; } void AppInfoManager::deleteIcons(const QHash &iconIds, bool &ok) diff --git a/src/ui/appinfo/appinfomanager.h b/src/ui/appinfo/appinfomanager.h index f8084651..345fc29a 100644 --- a/src/ui/appinfo/appinfomanager.h +++ b/src/ui/appinfo/appinfomanager.h @@ -2,11 +2,13 @@ #define APPINFOMANAGER_H #include +#include #include #include #include +#include #include #include "appinfo.h" @@ -33,7 +35,7 @@ public: bool saveToDb(const QString &appPath, AppInfo &appInfo, const QImage &appIcon); void deleteAppInfo(const QString &appPath, const AppInfo &appInfo); - void deleteOldApps(int limitCount = 0); + void deleteOldApps(int limitCount); signals: void lookupInfoFinished(const QString &appPath, const AppInfo &appInfo); @@ -48,8 +50,6 @@ public slots: protected: WorkerObject *createWorker() override; - virtual void updateAppAccessTime(const QString &appPath); - private: bool setupDb(); @@ -57,11 +57,12 @@ private: void saveAppInfo( const QString &appPath, const AppInfo &appInfo, const QVariant &iconId, bool &ok); - void deleteExcessAppInfos(); + void emitAppsPurge(); + void purgeApps(); void getOldAppsAndIcons( QStringList &appPaths, QHash &iconIds, int limitCount) const; - bool deleteAppsAndIcons(const QStringList &appPaths, const QHash &iconIds); + void deleteAppsAndIcons(const QStringList &appPaths, const QHash &iconIds); void deleteIcons(const QHash &iconIds, bool &ok); void deleteIcon(qint64 iconId, int deleteCount, bool &ok); @@ -70,6 +71,8 @@ private: void deleteApp(const QString &appPath, bool &ok); private: + TriggerTimer m_appsPurgeTimer; + SqliteDbPtr m_sqliteDb; QMutex m_mutex; }; diff --git a/src/ui/appinfo/migrations/1.sql b/src/ui/appinfo/migrations/1.sql index 099f86af..15af6849 100644 --- a/src/ui/appinfo/migrations/1.sql +++ b/src/ui/appinfo/migrations/1.sql @@ -1,16 +1,16 @@ CREATE TABLE app( - path TEXT PRIMARY KEY, + app_id INTEGER PRIMARY KEY, + path TEXT NOT NULL, alt_path TEXT, file_descr TEXT, company_name TEXT, product_name TEXT, product_ver TEXT, file_mod_time INTEGER, - icon_id INTEGER, - access_time DATETIME -) WITHOUT ROWID; + icon_id INTEGER +); -CREATE INDEX app_access_time_idx ON app(access_time); +CREATE UNIQUE INDEX app_path_uk ON app(path); CREATE TABLE icon( icon_id INTEGER PRIMARY KEY, diff --git a/src/ui/rpc/appinfomanagerrpc.h b/src/ui/rpc/appinfomanagerrpc.h index 9fce517a..6296f05d 100644 --- a/src/ui/rpc/appinfomanagerrpc.h +++ b/src/ui/rpc/appinfomanagerrpc.h @@ -21,9 +21,6 @@ public: public slots: void lookupAppInfo(const QString &appPath) override; - -protected: - void updateAppAccessTime(const QString & /*appPath*/) override { } }; #endif // APPINFOMANAGERRPC_H