refact: method Identify and CURD method of storage

Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
ComixHe 2023-09-14 17:16:10 +08:00 committed by Comix
parent ebb5f613c4
commit 6448481cfc
9 changed files with 162 additions and 94 deletions

View File

@ -15,8 +15,9 @@
<arg type="h" name="pidfd" direction="in" /> <arg type="h" name="pidfd" direction="in" />
<arg type="s" name="id" direction="out" /> <arg type="s" name="id" direction="out" />
<arg type="a{oa{sv}}" name="application_instance_info" direction="out" /> <arg type="o" name="instance" direction="out"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="ObjectMap"/> <arg type="a{sa{sv}}" name="application_instance_info" direction="out" />
<annotation name="org.qtproject.QtDBus.QtTypeName.Out2" value="ObjectInterfaceMap"/>
<annotation <annotation
name="org.freedesktop.DBus.Description" name="org.freedesktop.DBus.Description"

View File

@ -58,16 +58,16 @@ ApplicationManager1Storage::ApplicationManager1Storage(const QString &storagePat
{ {
} }
void ApplicationManager1Storage::writeToFile() const noexcept bool ApplicationManager1Storage::writeToFile() const noexcept
{ {
if (!m_file) { if (!m_file) {
qCritical() << "file is nullptr"; qCritical() << "file is nullptr";
return; return false;
} }
if (!m_file->resize(0)) { if (!m_file->resize(0)) {
qCritical() << "failed to clear file:" << m_file->errorString(); qCritical() << "failed to clear file:" << m_file->errorString();
return; return false;
} }
auto content = QJsonDocument{m_data}.toJson(QJsonDocument::Compact); auto content = QJsonDocument{m_data}.toJson(QJsonDocument::Compact);
@ -77,28 +77,32 @@ void ApplicationManager1Storage::writeToFile() const noexcept
} }
if (!m_file->flush()) { if (!m_file->flush()) {
qCritical() << "io error."; qCritical() << "io error, write failed.";
} return false;
} }
void ApplicationManager1Storage::setVersion(uint8_t version) noexcept return true;
}
bool ApplicationManager1Storage::setVersion(uint8_t version) noexcept
{ {
m_data["version"] = version; m_data["version"] = version;
writeToFile(); return writeToFile();
} }
uint8_t ApplicationManager1Storage::version() const noexcept uint8_t ApplicationManager1Storage::version() const noexcept
{ {
return m_data["version"].toInt(0); return m_data["version"].toInt(-1);
} }
void ApplicationManager1Storage::createApplicationValue(const QString &appId, bool ApplicationManager1Storage::createApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey, const QString &valueKey,
const QVariant &value) noexcept const QVariant &value) noexcept
{ {
if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) { if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) {
return; qWarning() << "unexpected empty string";
return false;
} }
QJsonObject appObj; QJsonObject appObj;
@ -112,94 +116,137 @@ void ApplicationManager1Storage::createApplicationValue(const QString &appId,
} }
if (groupObj.contains(valueKey)) { if (groupObj.contains(valueKey)) {
return; qInfo() << "value" << valueKey << value << "is already exists.";
return true;
} }
groupObj.insert(valueKey, value.toJsonValue()); groupObj.insert(valueKey, value.toJsonValue());
appObj.insert(groupName, groupObj); appObj.insert(groupName, groupObj);
m_data.insert(appId, appObj); m_data.insert(appId, appObj);
writeToFile(); return writeToFile();
} }
void ApplicationManager1Storage::updateApplicationValue(const QString &appId, bool ApplicationManager1Storage::updateApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey, const QString &valueKey,
const QVariant &value) noexcept const QVariant &value) noexcept
{ {
if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) { if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) {
return; qWarning() << "unexpected empty string";
return false;
} }
if (!m_data.contains(appId)) { if (!m_data.contains(appId)) {
return; qInfo() << "app" << appId << "doesn't exists.";
return false;
} }
auto appObj = m_data[appId].toObject(); auto appObj = m_data[appId].toObject();
if (!appObj.contains(groupName)) { if (!appObj.contains(groupName)) {
return; qInfo() << "group" << groupName << "doesn't exists.";
return false;
} }
auto groupObj = appObj[groupName].toObject(); auto groupObj = appObj[groupName].toObject();
if (!groupObj.contains(valueKey)) { if (!groupObj.contains(valueKey)) {
return; qInfo() << "value" << valueKey << "doesn't exists.";
return false;
} }
groupObj.insert(valueKey, value.toJsonValue()); groupObj.insert(valueKey, value.toJsonValue());
appObj.insert(groupName, groupObj); appObj.insert(groupName, groupObj);
m_data.insert(appId, appObj); m_data.insert(appId, appObj);
writeToFile(); return writeToFile();
} }
QVariant ApplicationManager1Storage::readApplicationValue(const QString &appId, QVariant ApplicationManager1Storage::readApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey) const noexcept const QString &valueKey) const noexcept
{ {
return m_data[appId][groupName][valueKey].toVariant(); auto app = m_data.constFind(appId)->toObject();
if (app.isEmpty()) {
return {};
} }
void ApplicationManager1Storage::deleteApplicationValue(const QString &appId, auto group = app.constFind(groupName)->toObject();
if (group.isEmpty()) {
return {};
}
auto val = group.constFind(valueKey);
if (val->isNull()) {
return {};
}
return val->toVariant();
}
bool ApplicationManager1Storage::deleteApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey) noexcept const QString &valueKey) noexcept
{ {
if (appId.isEmpty()) { if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) {
auto empty = QJsonObject{}; qWarning() << "unexpected empty string";
m_data.swap(empty); return false;
return;
} }
auto app = m_data.find(appId).value(); auto app = m_data.find(appId).value();
if (app.isNull()) { if (app.isNull()) {
return; return true;
} }
auto appObj = app.toObject(); auto appObj = app.toObject();
if (groupName.isEmpty()) {
m_data.remove(appId);
return;
}
auto group = appObj.find(groupName).value(); auto group = appObj.find(groupName).value();
if (group.isNull()) { if (group.isNull()) {
return; return true;
} }
auto groupObj = group.toObject(); auto groupObj = group.toObject();
if (valueKey.isEmpty()) {
appObj.remove(groupName);
m_data.insert(appId, appObj);
return;
}
auto val = groupObj.find(valueKey).value(); auto val = groupObj.find(valueKey).value();
if (val.isNull()) { if (val.isNull()) {
return; return true;
} }
groupObj.remove(valueKey); groupObj.remove(valueKey);
appObj.insert(groupName, groupObj); appObj.insert(groupName, groupObj);
m_data.insert(appId, appObj); m_data.insert(appId, appObj);
writeToFile(); return writeToFile();
}
bool ApplicationManager1Storage::clearData() noexcept
{
QJsonObject obj;
m_data.swap(obj);
return setVersion(STORAGE_VERSION);
}
bool ApplicationManager1Storage::deleteApplication(const QString &appId) noexcept
{
if (appId.isEmpty()) {
qWarning() << "unexpected empty string.";
return false;
}
m_data.remove(appId);
return writeToFile();
}
bool ApplicationManager1Storage::deleteGroup(const QString &appId, const QString &groupName) noexcept
{
if (appId.isEmpty() or groupName.isEmpty()) {
qWarning() << "unexpected empty string.";
return false;
}
auto app = m_data.find(appId).value().toObject();
if (app.isEmpty()) {
return true;
}
app.remove(groupName);
m_data.insert(appId, app);
return writeToFile();
} }

View File

@ -20,25 +20,28 @@ public:
ApplicationManager1Storage &operator=(ApplicationManager1Storage &&) = default; ApplicationManager1Storage &operator=(ApplicationManager1Storage &&) = default;
~ApplicationManager1Storage() = default; ~ApplicationManager1Storage() = default;
void createApplicationValue(const QString &appId, bool createApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey, const QString &valueKey,
const QVariant &value) noexcept; const QVariant &value) noexcept;
void updateApplicationValue(const QString &appId, bool updateApplicationValue(const QString &appId,
const QString &groupName, const QString &groupName,
const QString &valueKey, const QString &valueKey,
const QVariant &value) noexcept; const QVariant &value) noexcept;
[[nodiscard]] QVariant [[nodiscard]] QVariant
readApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) const noexcept; readApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) const noexcept;
void deleteApplicationValue(const QString &appId = "", const QString &groupName = "", const QString &valueKey = "") noexcept; bool deleteApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) noexcept;
bool clearData() noexcept;
bool deleteApplication(const QString &appId) noexcept;
bool deleteGroup(const QString &appId, const QString &groupName) noexcept;
void setVersion(uint8_t version) noexcept; bool setVersion(uint8_t version) noexcept;
[[nodiscard]] uint8_t version() const noexcept; [[nodiscard]] uint8_t version() const noexcept;
static std::shared_ptr<ApplicationManager1Storage> createApplicationManager1Storage(const QString &storageDir) noexcept; static std::shared_ptr<ApplicationManager1Storage> createApplicationManager1Storage(const QString &storageDir) noexcept;
private: private:
void writeToFile() const noexcept; [[nodiscard]] bool writeToFile() const noexcept;
explicit ApplicationManager1Storage(const QString &storagePath); explicit ApplicationManager1Storage(const QString &storagePath);
std::unique_ptr<QFile> m_file; std::unique_ptr<QFile> m_file;
QJsonObject m_data; QJsonObject m_data;

View File

@ -47,7 +47,7 @@ constexpr auto systemdOption = u8"systemd";
constexpr auto splitOption = u8"split"; constexpr auto splitOption = u8"split";
constexpr auto AppExecOption = u8"appExec"; constexpr auto AppExecOption = u8"appExec";
constexpr auto STORAGE_VERSION = 1; constexpr auto STORAGE_VERSION = 0;
constexpr auto ApplicationPropertiesGroup = u8"Application Properties"; constexpr auto ApplicationPropertiesGroup = u8"Application Properties";
constexpr auto LastLaunchedTime = u8"LastLaunchedTime"; constexpr auto LastLaunchedTime = u8"LastLaunchedTime";

View File

@ -124,16 +124,7 @@ void ApplicationManager1Service::addInstanceToApplication(const QString &unitNam
return; return;
} }
if (sender() != nullptr) { // activate by signal (*appIt)->updateAfterLaunch(sender() != nullptr); // activate by signal
auto timestamp = QDateTime::currentMSecsSinceEpoch();
if (auto ptr = m_storage.lock(); ptr) {
ptr->updateApplicationValue((*appIt)->m_desktopSource.desktopId(),
ApplicationPropertiesGroup,
LastLaunchedTime,
QVariant::fromValue(timestamp));
}
}
const auto &applicationPath = (*appIt)->applicationPath().path(); const auto &applicationPath = (*appIt)->applicationPath().path();
@ -278,17 +269,6 @@ bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) n
} }
m_applicationList.insert(application->applicationPath(), application); m_applicationList.insert(application->applicationPath(), application);
if (auto storagePtr = m_storage.lock(); storagePtr) {
auto appId = ptr->id();
auto value = storagePtr->readApplicationValue(appId, ApplicationPropertiesGroup, LastLaunchedTime);
if (value.isNull()) {
storagePtr->createApplicationValue(
appId, ApplicationPropertiesGroup, LastLaunchedTime, QVariant::fromValue<qint64>(0));
} else {
ptr->m_lastLaunch = value.toInt();
}
}
emit listChanged(); emit listChanged();
emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr)); emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr));
@ -300,7 +280,7 @@ void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &app
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) { if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) {
emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data())); emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data()));
if (auto ptr = m_storage.lock(); ptr) { if (auto ptr = m_storage.lock(); ptr) {
ptr->deleteApplicationValue((*it)->id()); ptr->deleteApplication((*it)->id());
} }
unregisterObjectFromDBus(application.path()); unregisterObjectFromDBus(application.path());
m_applicationList.remove(application); m_applicationList.remove(application);
@ -317,7 +297,8 @@ void ApplicationManager1Service::removeAllApplication() noexcept
} }
QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidfd, QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidfd,
ObjectMap &application_instance_info) const noexcept QDBusObjectPath &instance,
ObjectInterfaceMap &application_instance_info) const noexcept
{ {
if (!pidfd.isValid()) { if (!pidfd.isValid()) {
qWarning() << "pidfd isn't a valid unix file descriptor"; qWarning() << "pidfd isn't a valid unix file descriptor";
@ -369,17 +350,16 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf
return {}; return {};
} }
auto instance = (*app)->findInstance(ret.InstanceId); auto instancePath = (*app)->findInstance(ret.InstanceId);
if (auto path = instance.path(); path.isEmpty()) { if (auto path = instancePath.path(); path.isEmpty()) {
qWarning() << "can't find instance:" << path; qWarning() << "can't find instance:" << path;
return {}; return {};
} }
instance = instancePath;
auto instanceObj = (*app)->m_Instances.constFind(instance); auto instanceObj = (*app)->m_Instances.constFind(instance);
auto map = getChildInterfacesAndPropertiesFromObject(instanceObj->get()); application_instance_info = getChildInterfacesAndPropertiesFromObject(instanceObj->get());
application_instance_info.insert(instance, map);
return ret.ApplicationId; return ret.ApplicationId;
} }
@ -407,6 +387,7 @@ void ApplicationManager1Service::updateApplication(const QSharedPointer<Applicat
if (destApp->m_entry != newEntry) { if (destApp->m_entry != newEntry) {
destApp->resetEntry(newEntry); destApp->resetEntry(newEntry);
destApp->m_desktopSource = std::move(desktopFile); destApp->m_desktopSource = std::move(desktopFile);
destApp->detachAllInstance();
} }
} }

View File

@ -44,7 +44,9 @@ public:
JobManager1Service &jobManager() noexcept { return *m_jobManager; } JobManager1Service &jobManager() noexcept { return *m_jobManager; }
public Q_SLOTS: public Q_SLOTS:
QString Identify(const QDBusUnixFileDescriptor &pidfd, ObjectMap &application_instance_info) const noexcept; QString Identify(const QDBusUnixFileDescriptor &pidfd,
QDBusObjectPath &instance,
ObjectInterfaceMap &application_instance_info) const noexcept;
void ReloadApplications(); void ReloadApplications();
[[nodiscard]] ObjectMap GetManagedObjects() const; [[nodiscard]] ObjectMap GetManagedObjects() const;

View File

@ -29,14 +29,28 @@ ApplicationService::ApplicationService(DesktopFile source,
, m_storage(std::move(storage)) , m_storage(std::move(storage))
, m_desktopSource(std::move(source)) , m_desktopSource(std::move(source))
{ {
auto storagePtr = m_storage.lock();
if (!storagePtr) {
m_lastLaunch = -1;
return;
}
auto appId = id();
auto value = storagePtr->readApplicationValue(appId, ApplicationPropertiesGroup, LastLaunchedTime);
if (value.isNull()) {
if (!storagePtr->createApplicationValue(
appId, ApplicationPropertiesGroup, LastLaunchedTime, QVariant::fromValue<qint64>(0))) {
m_lastLaunch = -1;
}
return;
}
m_lastLaunch = value.toInt();
} }
ApplicationService::~ApplicationService() ApplicationService::~ApplicationService()
{ {
for (auto &instance : m_Instances.values()) { detachAllInstance();
orphanedInstances->append(instance);
instance->m_orphaned = true;
}
} }
QSharedPointer<ApplicationService> ApplicationService::createApplicationService( QSharedPointer<ApplicationService> ApplicationService::createApplicationService(
@ -93,12 +107,6 @@ QSharedPointer<ApplicationService> ApplicationService::createApplicationService(
return nullptr; return nullptr;
} }
auto ptr = app->m_storage.lock();
if (!ptr) {
qWarning() << "runtime storage doesn't exists.";
return app;
}
return app; return app;
} }
@ -501,6 +509,16 @@ void ApplicationService::removeAllInstance() noexcept
} }
} }
void ApplicationService::detachAllInstance() noexcept
{
for (auto &instance : m_Instances.values()) {
orphanedInstances->append(instance);
instance->m_orphaned = true;
}
m_Instances.clear();
}
QDBusObjectPath ApplicationService::findInstance(const QString &instanceId) const QDBusObjectPath ApplicationService::findInstance(const QString &instanceId) const
{ {
for (auto it = m_Instances.constKeyValueBegin(); it != m_Instances.constKeyValueEnd(); ++it) { for (auto it = m_Instances.constKeyValueBegin(); it != m_Instances.constKeyValueEnd(); ++it) {
@ -715,6 +733,20 @@ QVariant ApplicationService::findEntryValue(const QString &group,
return ret; return ret;
} }
void ApplicationService::updateAfterLaunch(bool isLaunch) noexcept
{
if (!isLaunch) {
return;
}
auto timestamp = QDateTime::currentMSecsSinceEpoch();
if (auto ptr = m_storage.lock(); ptr) {
ptr->updateApplicationValue(
m_desktopSource.desktopId(), ApplicationPropertiesGroup, ::LastLaunchedTime, QVariant::fromValue(timestamp));
}
}
QString getDeepinWineScaleFactor(const QString &appId) noexcept QString getDeepinWineScaleFactor(const QString &appId) noexcept
{ {
qCritical() << "Don't using env to control the window scale factor, this function" qCritical() << "Don't using env to control the window scale factor, this function"

View File

@ -100,6 +100,7 @@ public:
return m_Instances; return m_Instances;
} }
void resetEntry(DesktopEntry *newEntry) noexcept; void resetEntry(DesktopEntry *newEntry) noexcept;
void detachAllInstance() noexcept;
public Q_SLOTS: public Q_SLOTS:
QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options); QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options);
@ -131,6 +132,7 @@ private:
const QString &valueKey, const QString &valueKey,
EntryValueType type, EntryValueType type,
const QLocale &locale = getUserLocale()) const noexcept; const QLocale &locale = getUserLocale()) const noexcept;
void updateAfterLaunch(bool isLaunch) noexcept;
static bool shouldBeShown(const std::unique_ptr<DesktopEntry> &entry) noexcept; static bool shouldBeShown(const std::unique_ptr<DesktopEntry> &entry) noexcept;
static bool autostartCheck(const QString &linkPath) noexcept; static bool autostartCheck(const QString &linkPath) noexcept;
}; };

View File

@ -97,12 +97,12 @@ TEST_F(TestApplicationManager, identifyService)
auto pidfd = pidfd_open(fakePid, 0); auto pidfd = pidfd_open(fakePid, 0);
ASSERT_TRUE(pidfd > 0) << std::strerror(errno); ASSERT_TRUE(pidfd > 0) << std::strerror(errno);
ObjectMap instanceInfo; ObjectInterfaceMap instanceInfo;
auto appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, instanceInfo); QDBusObjectPath path;
auto appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, path, instanceInfo);
EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString());
auto instance = instanceInfo.constFind(InstancePath); if (path.path().isEmpty()) {
if (instance == instanceInfo.cend()) {
GTEST_SKIP_("couldn't find instance and skip."); GTEST_SKIP_("couldn't find instance and skip.");
} }
@ -111,7 +111,7 @@ TEST_F(TestApplicationManager, identifyService)
{QString{"SystemdUnitPath"}, QDBusObjectPath{"/"}}, {QString{"SystemdUnitPath"}, QDBusObjectPath{"/"}},
{QString{"Launcher"}, QString{"DDE"}}, {QString{"Launcher"}, QString{"DDE"}},
{QString{"Orphaned"}, false}}}}; {QString{"Orphaned"}, false}}}};
EXPECT_EQ(instance.value(), map); EXPECT_EQ(instanceInfo, map);
close(pidfd); close(pidfd);
@ -148,16 +148,16 @@ TEST_F(TestApplicationManager, identifyService)
ASSERT_TRUE(pidfd > 0) << std::strerror(errno); ASSERT_TRUE(pidfd > 0) << std::strerror(errno);
instanceInfo.clear(); instanceInfo.clear();
path.setPath("/");
appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, instanceInfo); appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, path, instanceInfo);
EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString());
instance = instanceInfo.constFind(InstancePath); if (path.path().isEmpty()) {
if (instance == instanceInfo.cend()) {
GTEST_SKIP_("couldn't find instance and skip."); GTEST_SKIP_("couldn't find instance and skip.");
} }
EXPECT_EQ(instance.value(), map); EXPECT_EQ(instanceInfo, map);
close(pidfd); close(pidfd);