refactor: use QHash instead of QMap

- use QHash to improve access performance
- key use appId instead of objectpath
This commit is contained in:
ck 2024-06-05 12:01:30 +08:00 committed by mike
parent 2cc1515229
commit 60414b5271
4 changed files with 71 additions and 75 deletions

View File

@ -77,21 +77,19 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
return; return;
} }
auto appIt = std::find_if(m_applicationList.cbegin(), auto app = m_applicationList.value(appId);
m_applicationList.cend(),
[&appId](const QSharedPointer<ApplicationService> &app) { return app->id() == appId; });
if (appIt == m_applicationList.cend()) { if (!app) {
return; return;
} }
// 服务在 AM 之后启动那么 instance size 是 0 newJob 时尝试添加一次 // 服务在 AM 之后启动那么 instance size 是 0 newJob 时尝试添加一次
// 比如 dde-file-manager.service 如果启动的比 AM 晚,那么在 scanInstances 时不会 addInstanceToApplication // 比如 dde-file-manager.service 如果启动的比 AM 晚,那么在 scanInstances 时不会 addInstanceToApplication
if ((*appIt)->instances().size() > 0) { if (app->instances().size() > 0) {
return; return;
} }
qDebug() << "add Instance " << unitName << "on JobNew"; qDebug() << "add Instance " << unitName << "on JobNew, " << app->instances().size();
addInstanceToApplication(unitName, systemdUnitPath); addInstanceToApplication(unitName, systemdUnitPath);
}); });
@ -225,20 +223,18 @@ void ApplicationManager1Service::addInstanceToApplication(const QString &unitNam
instanceId = QUuid::createUuid().toString(QUuid::Id128); instanceId = QUuid::createUuid().toString(QUuid::Id128);
} }
auto appIt = std::find_if(m_applicationList.cbegin(), auto app = m_applicationList.value(appId);
m_applicationList.cend(),
[&appId](const QSharedPointer<ApplicationService> &app) { return app->id() == appId; });
if (appIt == m_applicationList.cend()) { if (!app) {
qWarning() << "couldn't find app" << appId << "in application manager."; qWarning() << "couldn't find app" << appId << "in application manager.";
return; return;
} }
(*appIt)->updateAfterLaunch(sender() != nullptr); // activate by signal app->updateAfterLaunch(sender() != nullptr); // activate by signal
const auto &applicationPath = (*appIt)->applicationPath().path(); const auto &applicationPath = app->applicationPath().path();
if (!(*appIt)->addOneInstance(instanceId, applicationPath, systemdUnitPath.path(), launcher)) { if (!app->addOneInstance(instanceId, applicationPath, systemdUnitPath.path(), launcher)) {
qCritical() << "add Instance failed:" << applicationPath << unitName << systemdUnitPath.path(); qCritical() << "add Instance failed:" << applicationPath << unitName << systemdUnitPath.path();
} }
} }
@ -254,16 +250,14 @@ void ApplicationManager1Service::removeInstanceFromApplication(const QString &un
return; return;
} }
auto appIt = std::find_if(m_applicationList.cbegin(), auto app = m_applicationList.value(appId);
m_applicationList.cend(),
[&appId](const QSharedPointer<ApplicationService> &app) { return app->id() == appId; });
if (appIt == m_applicationList.cend()) { if (!app) {
qWarning() << "couldn't find app" << appId << "in application manager."; qWarning() << "couldn't find app" << appId << "in application manager.";
return; return;
} }
const auto &appIns = (*appIt)->applicationInstances(); const auto &appIns = app->applicationInstances();
auto instanceIt = auto instanceIt =
std::find_if(appIns.cbegin(), appIns.cend(), [&systemdUnitPath](const QSharedPointer<InstanceService> &value) { std::find_if(appIns.cbegin(), appIns.cend(), [&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
@ -271,7 +265,7 @@ void ApplicationManager1Service::removeInstanceFromApplication(const QString &un
}); });
if (instanceIt != appIns.cend()) { if (instanceIt != appIns.cend()) {
(*appIt)->removeOneInstance(instanceIt.key()); app->removeOneInstance(instanceIt.key());
return; return;
} }
@ -440,16 +434,13 @@ QHash<QSharedPointer<ApplicationService>, QString> ApplicationManager1Service::s
continue; continue;
} }
if (auto appIt = std::find_if(m_applicationList.cbegin(), if (auto existApp = m_applicationList.value(desktopFile.desktopId()); existApp) {
m_applicationList.cend(),
[&desktopFile](const auto &app) { return desktopFile.desktopId() == app->id(); });
appIt != m_applicationList.cend()) {
if (autostartFlag) { if (autostartFlag) {
auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString(); auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
qInfo() << "launch exist autostart application " << (*appIt)->id() << " by " << realExec; qInfo() << "launch exist autostart application " << existApp->id() << " by " << realExec;
ret.insert(*appIt, realExec); ret.insert(existApp, realExec);
} }
(*appIt)->setAutostartSource({std::move(originalSource), std::move(tmp)}); existApp->setAutostartSource({std::move(originalSource), std::move(tmp)});
continue; continue;
} }
@ -499,13 +490,16 @@ void ApplicationManager1Service::loadHooks() noexcept
QList<QDBusObjectPath> ApplicationManager1Service::list() const QList<QDBusObjectPath> ApplicationManager1Service::list() const
{ {
return m_applicationList.keys(); QList<QDBusObjectPath> paths;
for (const auto &appId : m_applicationList.keys())
paths << QDBusObjectPath{getObjectPathFromAppId(appId)};
return paths;
} }
QSharedPointer<ApplicationService> ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) noexcept QSharedPointer<ApplicationService> ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) noexcept
{ {
auto objectPath = QDBusObjectPath{getObjectPathFromAppId(desktopFileSource.desktopId())}; if (auto app = m_applicationList.constFind(desktopFileSource.desktopId()); app != m_applicationList.cend()) {
if (auto app = m_applicationList.constFind(objectPath); app != m_applicationList.cend()) {
qInfo() << "this application already exists." << "current desktop source:" << desktopFileSource.sourcePath() qInfo() << "this application already exists." << "current desktop source:" << desktopFileSource.sourcePath()
<< "exists app source:" << app->data()->desktopFileSource().sourcePath(); << "exists app source:" << app->data()->desktopFileSource().sourcePath();
return *app; return *app;
@ -528,7 +522,7 @@ QSharedPointer<ApplicationService> ApplicationManager1Service::addApplication(De
if (!registerObjectToDBus(ptr, application->applicationPath().path(), ApplicationInterface)) { if (!registerObjectToDBus(ptr, application->applicationPath().path(), ApplicationInterface)) {
return nullptr; return nullptr;
} }
m_applicationList.insert(application->applicationPath(), application); m_applicationList.insert(application->id(), application);
emit listChanged(); emit listChanged();
emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr)); emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr));
@ -536,18 +530,18 @@ QSharedPointer<ApplicationService> ApplicationManager1Service::addApplication(De
return application; return application;
} }
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application) noexcept void ApplicationManager1Service::removeOneApplication(const QString &appId) noexcept
{ {
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) { auto objectPath = QDBusObjectPath{getObjectPathFromAppId(appId)};
emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data())); if (auto it = m_applicationList.find(appId); it != m_applicationList.cend()) {
emit InterfacesRemoved(objectPath, getChildInterfacesFromObject(it->data()));
if (auto ptr = m_storage.lock(); ptr) { if (auto ptr = m_storage.lock(); ptr) {
auto appId = (*it)->id();
if (!ptr->deleteApplication(appId)) { if (!ptr->deleteApplication(appId)) {
qCritical() << "failed to delete all properties of" << appId; qCritical() << "failed to delete all properties of" << appId;
} }
} }
unregisterObjectFromDBus(application.path()); unregisterObjectFromDBus(objectPath.path());
m_applicationList.remove(application); m_applicationList.remove(appId);
emit listChanged(); emit listChanged();
} }
@ -555,8 +549,8 @@ void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &app
void ApplicationManager1Service::removeAllApplication() noexcept void ApplicationManager1Service::removeAllApplication() noexcept
{ {
for (const auto &app : m_applicationList.keys()) { for (const auto &appId : m_applicationList.keys()) {
removeOneApplication(app); removeOneApplication(appId);
} }
} }
@ -583,22 +577,19 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
return {}; return {};
} }
auto app = std::find_if(m_applicationList.cbegin(), m_applicationList.cend(), [&ret](const auto &appPtr) { if (!m_applicationList.contains(ret.ApplicationId)) {
return appPtr->id() == ret.ApplicationId;
});
if (app == m_applicationList.cend()) {
safe_sendErrorReply(QDBusError::Failed, "can't find application:" % ret.ApplicationId); safe_sendErrorReply(QDBusError::Failed, "can't find application:" % ret.ApplicationId);
return {}; return {};
} }
auto app = m_applicationList.value(ret.ApplicationId);
QDBusObjectPath instancePath; QDBusObjectPath instancePath;
const auto &instances = (*app)->instances(); const auto &instances = app->instances();
if (ret.InstanceId.isEmpty() && instances.size() == 1) { if (ret.InstanceId.isEmpty() && instances.size() == 1) {
// Maybe a dbus systemd service // Maybe a dbus systemd service
instancePath = instances.constFirst(); instancePath = instances.constFirst();
} else { } else {
instancePath = (*app)->findInstance(ret.InstanceId); instancePath = app->findInstance(ret.InstanceId);
} }
if (instancePath.path().isEmpty()) { if (instancePath.path().isEmpty()) {
safe_sendErrorReply(QDBusError::Failed, "can't find instance:" % ret.InstanceId); safe_sendErrorReply(QDBusError::Failed, "can't find instance:" % ret.InstanceId);
@ -606,7 +597,7 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
} }
instance = instancePath; instance = instancePath;
auto instanceObj = (*app)->m_Instances.constFind(instance); auto instanceObj = app->m_Instances.constFind(instance);
application_instance_info = getChildInterfacesAndPropertiesFromObject(instanceObj->get()); application_instance_info = getChildInterfacesAndPropertiesFromObject(instanceObj->get());
return ret.ApplicationId; return ret.ApplicationId;
@ -615,7 +606,7 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
void ApplicationManager1Service::updateApplication(const QSharedPointer<ApplicationService> &destApp, void ApplicationManager1Service::updateApplication(const QSharedPointer<ApplicationService> &destApp,
DesktopFile desktopFile) noexcept DesktopFile desktopFile) noexcept
{ {
if (auto app = m_applicationList.find(destApp->applicationPath()); app == m_applicationList.cend()) { if (!m_applicationList.contains(destApp->id())) {
return; return;
} }
@ -659,11 +650,11 @@ void ApplicationManager1Service::doReloadApplications()
auto desktopFileDirs = getDesktopFileDirs(); auto desktopFileDirs = getDesktopFileDirs();
desktopFileDirs.append(getAutoStartDirs()); // detect autostart apps add/remove/update desktopFileDirs.append(getAutoStartDirs()); // detect autostart apps add/remove/update
auto apps = m_applicationList.keys(); auto appIds = m_applicationList.keys();
applyIteratively( applyIteratively(
QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()), QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()),
[this, &apps](const QFileInfo &info) -> bool { [this, &appIds](const QFileInfo &info) -> bool {
ParserError err{ParserError::NoError}; ParserError err{ParserError::NoError};
auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err); auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
if (!ret.has_value()) { if (!ret.has_value()) {
@ -672,24 +663,16 @@ void ApplicationManager1Service::doReloadApplications()
auto file = std::move(ret).value(); auto file = std::move(ret).value();
auto destApp = QSharedPointer<ApplicationService> app = m_applicationList.value(file.desktopId());
std::find_if(m_applicationList.cbegin(),
m_applicationList.cend(),
[&file](const QSharedPointer<ApplicationService> &app) { return file.desktopId() == app->id(); });
if (err != ParserError::NoError) { if (app and appIds.contains(app->id())) {
qWarning() << "error occurred:" << err << " skip this application.";
return false;
}
if (destApp != m_applicationList.cend() and apps.contains(destApp.key())) {
// Can emit correct remove signal when uninstalling applications // Can emit correct remove signal when uninstalling applications
if (ApplicationFilter::tryExecCheck(*(destApp->data()->m_entry))) { if (ApplicationFilter::tryExecCheck(*(app.data()->m_entry))) {
qDebug() << info.absolutePath() << "Checked TryExec failed and will be removed"; qDebug() << info.absolutePath() << "Checked TryExec failed and will be removed";
return false; return false;
} }
apps.removeOne(destApp.key()); appIds.removeOne(app->id());
updateApplication(destApp.value(), std::move(file)); updateApplication(app, std::move(file));
return false; return false;
} }
@ -700,8 +683,8 @@ void ApplicationManager1Service::doReloadApplications()
{"*.desktop"}, {"*.desktop"},
QDir::Name | QDir::DirsLast); QDir::Name | QDir::DirsLast);
for (const auto &key : apps) { for (const auto &appId : appIds) {
removeOneApplication(key); removeOneApplication(appId);
} }
m_mimeManager->reset(); m_mimeManager->reset();
@ -715,15 +698,13 @@ ObjectMap ApplicationManager1Service::GetManagedObjects() const
return dumpDBusObject(m_applicationList); return dumpDBusObject(m_applicationList);
} }
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> QHash<QDBusObjectPath, QSharedPointer<ApplicationService>>
ApplicationManager1Service::findApplicationsByIds(const QStringList &appIds) const noexcept ApplicationManager1Service::findApplicationsByIds(const QStringList &appIds) const noexcept
{ {
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> ret; QHash<QDBusObjectPath, QSharedPointer<ApplicationService>> ret;
for (auto it = m_applicationList.constKeyValueBegin(); it != m_applicationList.constKeyValueEnd(); ++it) { for (const auto appId : appIds) {
const auto &ptr = it->second; if (auto app = m_applicationList.value(appId); app)
if (appIds.contains(ptr->id())) { ret.insert(QDBusObjectPath{getObjectPathFromAppId(appId)}, app);
ret.insert(it->first, it->second);
}
} }
return ret; return ret;

View File

@ -12,6 +12,7 @@
#include <QScopedPointer> #include <QScopedPointer>
#include <memory> #include <memory>
#include <QMap> #include <QMap>
#include <QHash>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
#include <QTimer> #include <QTimer>
#include "applicationmanagerstorage.h" #include "applicationmanagerstorage.h"
@ -39,9 +40,9 @@ public:
void initService(QDBusConnection &connection) noexcept; void initService(QDBusConnection &connection) noexcept;
QSharedPointer<ApplicationService> addApplication(DesktopFile desktopFileSource) noexcept; QSharedPointer<ApplicationService> addApplication(DesktopFile desktopFileSource) noexcept;
void removeOneApplication(const QDBusObjectPath &application) noexcept; void removeOneApplication(const QString &appId) noexcept;
void removeAllApplication() noexcept; void removeAllApplication() noexcept;
[[nodiscard]] QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> [[nodiscard]] QHash<QDBusObjectPath, QSharedPointer<ApplicationService>>
findApplicationsByIds(const QStringList &appIds) const noexcept; findApplicationsByIds(const QStringList &appIds) const noexcept;
void updateApplication(const QSharedPointer<ApplicationService> &destApp, DesktopFile desktopFile) noexcept; void updateApplication(const QSharedPointer<ApplicationService> &destApp, DesktopFile desktopFile) noexcept;
@ -77,7 +78,7 @@ private:
QStringList m_systemdPathEnv; QStringList m_systemdPathEnv;
QFileSystemWatcher m_watcher; QFileSystemWatcher m_watcher;
QTimer m_reloadTimer; QTimer m_reloadTimer;
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList; QHash<QString, QSharedPointer<ApplicationService>> m_applicationList;
void scanMimeInfos() noexcept; void scanMimeInfos() noexcept;
void scanApplications() noexcept; void scanApplications() noexcept;

View File

@ -554,6 +554,20 @@ ObjectMap dumpDBusObject(const QMap<QDBusObjectPath, QSharedPointer<T>> &map)
return objs; return objs;
} }
template <typename T>
ObjectMap dumpDBusObject(const QHash<QString, QSharedPointer<T>> &map)
{
ObjectMap objs;
for (auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it) {
const auto &[key, value] = *it;
auto interAndProps = getChildInterfacesAndPropertiesFromObject(value.data());
objs.insert(QDBusObjectPath{getObjectPathFromAppId(key)}, interAndProps);
}
return objs;
}
struct FileTimeInfo struct FileTimeInfo
{ {
qint64 mtime; qint64 mtime;

View File

@ -44,7 +44,7 @@ bool SystemdSignalDispatcher::connectToSignals() noexcept
"JobNew", "JobNew",
this, this,
SLOT(onJobNew(uint32_t, QDBusObjectPath, QString)))) { SLOT(onJobNew(uint32_t, QDBusObjectPath, QString)))) {
qCritical() << "can't connect to UnitNew signal of systemd service."; qCritical() << "can't connect to JobNew signal of systemd service.";
return false; return false;
} }