feat: scan existing systemd unit
We should scan existing systemd unit when we start application manager. As application manager crash and restarted later, we can get the launched application instances back.
This commit is contained in:
parent
02317993c8
commit
6adc02375f
@ -44,21 +44,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
registerComplexDbusType();
|
registerComplexDbusType();
|
||||||
ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus};
|
ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus};
|
||||||
QList<DesktopFile> fileList{};
|
|
||||||
const auto &desktopFileDirs = getDesktopFileDirs();
|
|
||||||
|
|
||||||
applyIteratively(QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()), [&AMService](const QFileInfo &info) -> bool {
|
|
||||||
DesktopErrorCode err{DesktopErrorCode::NoError};
|
|
||||||
auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
|
|
||||||
if (!ret.has_value()) {
|
|
||||||
qWarning() << "failed to search File:" << err;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!AMService.addApplication(std::move(ret).value())) {
|
|
||||||
qWarning() << "add Application failed, skip...";
|
|
||||||
}
|
|
||||||
return false; // means to apply this function to the rest of the files
|
|
||||||
});
|
|
||||||
#ifdef PROFILING_MODE
|
#ifdef PROFILING_MODE
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
qCInfo(DDEAMProf) << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms";
|
qCInfo(DDEAMProf) << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms";
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "dbus/AMobjectmanager1adaptor.h"
|
#include "dbus/AMobjectmanager1adaptor.h"
|
||||||
#include "systemdsignaldispatcher.h"
|
#include "systemdsignaldispatcher.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QDBusMessage>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
ApplicationManager1Service::~ApplicationManager1Service() = default;
|
ApplicationManager1Service::~ApplicationManager1Service() = default;
|
||||||
@ -41,10 +42,21 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
|
|
||||||
auto &dispatcher = SystemdSignalDispatcher::instance();
|
auto &dispatcher = SystemdSignalDispatcher::instance();
|
||||||
|
|
||||||
|
connect(&dispatcher, &SystemdSignalDispatcher::SystemdUnitNew, this, &ApplicationManager1Service::addInstanceToApplication);
|
||||||
|
|
||||||
connect(&dispatcher,
|
connect(&dispatcher,
|
||||||
&SystemdSignalDispatcher::SystemdUnitNew,
|
&SystemdSignalDispatcher::SystemdUnitRemoved,
|
||||||
this,
|
this,
|
||||||
[this](const QString &unitName, const QDBusObjectPath &systemdUnitPath) {
|
&ApplicationManager1Service::removeInstanceFromApplication);
|
||||||
|
|
||||||
|
this->scanApplications();
|
||||||
|
this->scanInstances();
|
||||||
|
|
||||||
|
// TODO: send custom event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationManager1Service::addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath)
|
||||||
|
{
|
||||||
auto pair = processUnitName(unitName);
|
auto pair = processUnitName(unitName);
|
||||||
auto appId = pair.first;
|
auto appId = pair.first;
|
||||||
auto instanceId = pair.second;
|
auto instanceId = pair.second;
|
||||||
@ -68,13 +80,11 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
});
|
}
|
||||||
|
|
||||||
connect(&dispatcher,
|
void ApplicationManager1Service::removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath)
|
||||||
&SystemdSignalDispatcher::SystemdUnitRemoved,
|
{
|
||||||
this,
|
auto pair = processUnitName(unitName);
|
||||||
[this](const QString &serviceName, QDBusObjectPath systemdUnitPath) {
|
|
||||||
auto pair = processUnitName(serviceName);
|
|
||||||
auto appId = pair.first;
|
auto appId = pair.first;
|
||||||
auto instanceId = pair.second;
|
auto instanceId = pair.second;
|
||||||
if (appId.isEmpty()) {
|
if (appId.isEmpty()) {
|
||||||
@ -92,17 +102,54 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
|
|
||||||
const auto &appIns = (*appIt)->applicationInstances();
|
const auto &appIns = (*appIt)->applicationInstances();
|
||||||
|
|
||||||
auto instanceIt = std::find_if(
|
auto instanceIt =
|
||||||
appIns.cbegin(), appIns.cend(), [&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
|
std::find_if(appIns.cbegin(), appIns.cend(), [&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
|
||||||
return value->systemdUnitPath() == systemdUnitPath;
|
return value->systemdUnitPath() == systemdUnitPath;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (instanceIt != appIns.cend()) [[likely]] {
|
if (instanceIt != appIns.cend()) [[likely]] {
|
||||||
(*appIt)->removeOneInstance(instanceIt.key());
|
(*appIt)->removeOneInstance(instanceIt.key());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplicationManager1Service::scanApplications() noexcept
|
||||||
|
{
|
||||||
|
QList<DesktopFile> fileList{};
|
||||||
|
const auto &desktopFileDirs = getDesktopFileDirs();
|
||||||
|
|
||||||
|
applyIteratively(QList<QDir>(desktopFileDirs.cbegin(), desktopFileDirs.cend()), [this](const QFileInfo &info) -> bool {
|
||||||
|
DesktopErrorCode err{DesktopErrorCode::NoError};
|
||||||
|
auto ret = DesktopFile::searchDesktopFileByPath(info.absoluteFilePath(), err);
|
||||||
|
if (!ret.has_value()) {
|
||||||
|
qWarning() << "failed to search File:" << err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this->addApplication(std::move(ret).value())) {
|
||||||
|
qWarning() << "add Application failed, skip...";
|
||||||
|
}
|
||||||
|
return false; // means to apply this function to the rest of the files
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplicationManager1Service::scanInstances() noexcept
|
||||||
|
{
|
||||||
|
auto &conn = ApplicationManager1DBus::instance().globalDestBus();
|
||||||
|
auto call_message = QDBusMessage::createMethodCall(SystemdService, SystemdObjectPath, SystemdInterfaceName, "ListUnits");
|
||||||
|
auto result = conn.call(call_message);
|
||||||
|
if (result.type() == QDBusMessage::ErrorMessage) {
|
||||||
|
qCritical() << "failed to scan existing instances: call to ListUnits failed:" << result.errorMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto v = result.arguments().first();
|
||||||
|
QList<SystemdUnitDBusMessage> units;
|
||||||
|
v.value<QDBusArgument>() >> units;
|
||||||
|
for (const auto &unit : units) {
|
||||||
|
// FIXME(black_desk): Should check this unit is active or not.
|
||||||
|
this->addInstanceToApplication(unit.name, unit.objectPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
||||||
{
|
{
|
||||||
return m_applicationList.keys();
|
return m_applicationList.keys();
|
||||||
|
@ -53,6 +53,11 @@ private:
|
|||||||
std::unique_ptr<Identifier> m_identifier;
|
std::unique_ptr<Identifier> m_identifier;
|
||||||
QScopedPointer<JobManager1Service> m_jobManager{nullptr};
|
QScopedPointer<JobManager1Service> m_jobManager{nullptr};
|
||||||
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList;
|
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList;
|
||||||
|
|
||||||
|
void scanApplications() noexcept;
|
||||||
|
void scanInstances() noexcept;
|
||||||
|
void addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
||||||
|
void removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
32
src/global.h
32
src/global.h
@ -17,6 +17,7 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QDBusObjectPath>
|
#include <QDBusObjectPath>
|
||||||
|
#include <QDBusArgument>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
@ -35,6 +36,30 @@ Q_DECLARE_METATYPE(ObjectInterfaceMap)
|
|||||||
Q_DECLARE_METATYPE(ObjectMap)
|
Q_DECLARE_METATYPE(ObjectMap)
|
||||||
Q_DECLARE_METATYPE(PropMap)
|
Q_DECLARE_METATYPE(PropMap)
|
||||||
|
|
||||||
|
struct SystemdUnitDBusMessage
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QDBusObjectPath objectPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const QDBusArgument &operator>>(const QDBusArgument &argument, QList<SystemdUnitDBusMessage> &units)
|
||||||
|
{
|
||||||
|
argument.beginArray();
|
||||||
|
while (!argument.atEnd()) {
|
||||||
|
argument.beginStructure();
|
||||||
|
QString _str;
|
||||||
|
uint32_t _uint;
|
||||||
|
QDBusObjectPath _path;
|
||||||
|
SystemdUnitDBusMessage unit;
|
||||||
|
argument >> unit.name >> _str >> _str >> _str >> _str >> _str >> unit.objectPath >> _uint >> _str >> _path;
|
||||||
|
units.push_back(unit);
|
||||||
|
argument.endStructure();
|
||||||
|
}
|
||||||
|
argument.endArray();
|
||||||
|
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
inline QString getApplicationLauncherBinary()
|
inline QString getApplicationLauncherBinary()
|
||||||
{
|
{
|
||||||
static const QString bin = []() {
|
static const QString bin = []() {
|
||||||
@ -398,6 +423,7 @@ inline QStringList getAutoStartDirs()
|
|||||||
|
|
||||||
inline QPair<QString, QString> processUnitName(const QString &unitName)
|
inline QPair<QString, QString> processUnitName(const QString &unitName)
|
||||||
{
|
{
|
||||||
|
// FIXME: rewrite, using regexp.
|
||||||
QString instanceId;
|
QString instanceId;
|
||||||
QString applicationId;
|
QString applicationId;
|
||||||
|
|
||||||
@ -417,10 +443,14 @@ inline QPair<QString, QString> processUnitName(const QString &unitName)
|
|||||||
auto app = unitName.sliced(0, lastDotIndex);
|
auto app = unitName.sliced(0, lastDotIndex);
|
||||||
|
|
||||||
auto components = app.split('-');
|
auto components = app.split('-');
|
||||||
|
if (components.size() < 3) {
|
||||||
|
qDebug() << unitName << "is not a xdg application ignore";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
instanceId = components.takeLast();
|
instanceId = components.takeLast();
|
||||||
applicationId = components.takeLast();
|
applicationId = components.takeLast();
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "it's not service or scope:" << unitName << "ignore.";
|
qDebug() << "it's not service or scope:" << unitName << "ignore";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user