Commit 5242bf27 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Port AgentManager away from deprecated serviceOwnerChanged signal

Test Plan: Akonadi and all agents start and operate as expected

Reviewers: #kde_pim, vkrause

Reviewed By: #kde_pim, vkrause

Subscribers: kde-pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D26274
parent 9c33b1b4
......@@ -104,12 +104,57 @@ AgentManager::AgentManager(bool verbose, QObject *parent)
{
new AgentManagerAdaptor(this);
new AgentManagerInternalAdaptor(this);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/AgentManager"), this);
connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged,
this, &AgentManager::serviceOwnerChanged);
auto bus = QDBusConnection::sessionBus();
bus.registerObject(QStringLiteral("/AgentManager"), this);
mWatcher.setConnection(bus);
mWatcher.setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration);
mWatcher.addWatchedService(QStringLiteral("org.freedesktop.Akonadi*"));
connect(&mWatcher, &QDBusServiceWatcher::serviceRegistered,
this, [this](const QString &name) {
qCDebug(AKONADICONTROL_LOG) << "Service" << name<< "registered";
if (checkServerIsOperational(name)) {
continueStartup(); // Server is operational, start agents
return;
}
const auto service = Akonadi::DBus::parseAgentServiceName(name);
if (service.has_value()) {
switch (service->agentType) {
case Akonadi::DBus::Agent:
registerAgentService(*service);
break;
case Akonadi::DBus::Resource:
registerResourceService(*service);
break;
case Akonadi::DBus::Preprocessor:
registerPreprocessorService(*service);
break;
case Akonadi::DBus::Unknown:
break;
}
}
});
connect(&mWatcher, &QDBusServiceWatcher::serviceUnregistered,
this, [this](const QString &name) {
qCDebug(AKONADICONTROL_LOG) << "Service" << name << "unregistered from bus";
const auto service = Akonadi::DBus::parseAgentServiceName(name);
if (service.has_value()) {
switch (service->agentType) {
case Akonadi::DBus::Agent:
case Akonadi::DBus::Resource:
case Akonadi::DBus::Unknown:
// We don't care those got lost
break;
case Akonadi::DBus::Preprocessor:
unregisterPreprocessorService(*service);
break;
}
}
});
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) {
if (bus.interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) {
qFatal("akonadiserver already running!");
}
......@@ -637,134 +682,116 @@ void AgentManager::save()
file.endGroup();
}
void AgentManager::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
void AgentManager::registerAgentService(const Akonadi::DBus::AgentService &service)
{
Q_UNUSED(oldOwner);
// This is called by the D-Bus server when a service comes up, goes down or changes ownership for some reason
// and this is where we "hook up" our different Agent interfaces.
qCDebug(AKONADICONTROL_LOG) << "Service" << name << "owner changed from" << oldOwner << "to" << newOwner;
if ((name == Akonadi::DBus::serviceName(Akonadi::DBus::Server) || name == Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer)) && !newOwner.isEmpty()) {
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))
&& (!mAgentServer || QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer)))) {
// server is operational, start agents
continueStartup();
}
if (!mAgentInstances.contains(service.identifier)) {
return;
}
const auto service = Akonadi::DBus::parseAgentServiceName(name);
if (!service.has_value()) {
const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier);
const bool restarting = instance->hasAgentInterface();
if (!instance->obtainAgentInterface()) {
return;
}
switch (service->agentType) {
case Akonadi::DBus::Agent: {
// An agent service went up or down
if (newOwner.isEmpty()) {
return; // It went down: we don't care here.
}
if (!mAgentInstances.contains(service->identifier)) {
return;
}
const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier);
const bool restarting = instance->hasAgentInterface();
if (!instance->obtainAgentInterface()) {
return;
}
Q_ASSERT(mAgents.contains(instance->agentType()));
const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource);
if (!restarting && (!isResource || instance->hasResourceInterface())) {
Q_EMIT agentInstanceAdded(service->identifier);
}
Q_ASSERT(mAgents.contains(instance->agentType()));
const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource);
break;
if (!restarting && (!isResource || instance->hasResourceInterface())) {
Q_EMIT agentInstanceAdded(service.identifier);
}
case Akonadi::DBus::Resource: {
// A resource service went up or down
if (newOwner.isEmpty()) {
return; // It went down: we don't care here.
}
if (!mAgentInstances.contains(service->identifier)) {
return;
}
const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier);
const bool restarting = instance->hasResourceInterface();
if (!instance->obtainResourceInterface()) {
return;
}
}
if (!restarting && instance->hasAgentInterface()) {
Q_EMIT agentInstanceAdded(service->identifier);
}
void AgentManager::registerResourceService(const Akonadi::DBus::AgentService &service)
{
if (!mAgentInstances.contains(service.identifier)) {
return;
}
break;
const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier);
const bool restarting = instance->hasResourceInterface();
if (!instance->obtainResourceInterface()) {
return;
}
case Akonadi::DBus::Preprocessor: {
// A preprocessor service went up or down
// If the preprocessor is going up then the org.freedesktop.Akonadi.Agent.* interface
// should be already up (as it's registered before the preprocessor one).
// So if we don't know about the preprocessor as agent instance
// then it's not our preprocessor.
if (!restarting && instance->hasAgentInterface()) {
Q_EMIT agentInstanceAdded(service.identifier);
}
}
// If the preprocessor is going down then either the agent interface already
// went down (and it has been already unregistered on the manager side)
// or it's still registered as agent and WE have to unregister it.
// The order of interface deletions depends on Qt but we handle both cases.
void AgentManager::registerPreprocessorService(const Akonadi::DBus::AgentService &service)
{
// If the preprocessor is going up then the org.freedesktop.Akonadi.Agent.* interface
// should be already up (as it's registered before the preprocessor one).
// So if we don't know about the preprocessor as agent instance
// then it's not our preprocessor.
// Check if we "know" about it.
qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service->identifier << " is going up or down...";
qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service.identifier << " is going up or down...";
if (!mAgentInstances.contains(service->identifier)) {
qCDebug(AKONADICONTROL_LOG) << "But it isn't registered as agent... not mine (anymore?)";
return; // not our agent (?)
}
// Check if we "know" about it.
if (!mAgentInstances.contains(service.identifier)) {
qCDebug(AKONADICONTROL_LOG) << "But it isn't registered as agent... not mine (anymore?)";
return; // not our agent (?)
}
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
if (!preProcessorManager.isValid()) {
qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message();
} else {
if (newOwner.isEmpty()) {
// The preprocessor went down. Unregister it on server side.
if (!preProcessorManager.isValid()) {
qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message();
return;
}
preProcessorManager.unregisterInstance(service->identifier);
if (!mAgentInstances.value(service.identifier)->obtainPreprocessorInterface()) {
// Hm.. couldn't hook up its preprocessor interface..
// Make sure we don't have it in the preprocessor chain
qCWarning(AKONADICONTROL_LOG) << "Couldn't obtain preprocessor interface for instance" << service.identifier;
preProcessorManager.unregisterInstance(service.identifier);
return;
}
} else {
qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service.identifier;
// The preprocessor went up. Register it on server side.
// Add to the preprocessor chain
preProcessorManager.registerInstance(service.identifier);
}
if (!mAgentInstances.value(service->identifier)->obtainPreprocessorInterface()) {
// Hm.. couldn't hook up its preprocessor interface..
// Make sure we don't have it in the preprocessor chain
qCWarning(AKONADICONTROL_LOG) << "Couldn't obtain preprocessor interface for instance" << service->identifier;
void AgentManager::unregisterPreprocessorService(const Akonadi::DBus::AgentService &service)
{
// If the preprocessor is going down then either the agent interface already
// went down (and it has been already unregistered on the manager side)
// or it's still registered as agent and WE have to unregister it.
// The order of interface deletions depends on Qt but we handle both cases.
preProcessorManager.unregisterInstance(service->identifier);
return;
}
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service->identifier;
if (!preProcessorManager.isValid()) {
qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message();
return;
}
// The preprocessor went down. Unregister it on server side.
preProcessorManager.unregisterInstance(service.identifier);
}
// Add to the preprocessor chain
preProcessorManager.registerInstance(service->identifier);
}
bool AgentManager::checkServerIsOperational(const QString &service) const
{
const auto dbusInterface = QDBusConnection::sessionBus().interface();
const auto serverService = Akonadi::DBus::serviceName(Akonadi::DBus::Server);
const auto agentServerService = Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer);
if (service == serverService || service == agentServerService) {
if (dbusInterface->isServiceRegistered(serverService) && (!mAgentServer || dbusInterface->isServiceRegistered(agentServerService))) {
return true;
}
break;
}
default:
break;
}
return false;
}
bool AgentManager::checkInstance(const QString &identifier) const
......
......@@ -23,9 +23,11 @@
#include <QHash>
#include <QStringList>
#include <QDBusServiceWatcher>
#include "agenttype.h"
#include "agentinstance.h"
#include <private/dbus_p.h>
class QDir;
......@@ -323,7 +325,6 @@ Q_SIGNALS:
private Q_SLOTS:
void updatePluginInfos();
void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
void agentExeChanged(const QString &fileName);
private:
......@@ -356,6 +357,7 @@ private:
void readPluginInfos(const QDir &directory);
AgentInstance::Ptr createAgentInstance(const AgentType &type);
bool checkServerIsOperational(const QString &serviceName) const;
bool checkAgentInterfaces(const QString &identifier, const QString &method) const;
bool checkInstance(const QString &identifier) const;
bool checkResourceInterface(const QString &identifier, const QString &method) const;
......@@ -364,6 +366,10 @@ private:
void continueStartup();
void registerAgentAtServer(const QString &agentIdentifier, const AgentType &type);
void registerAgentService(const Akonadi::DBus::AgentService &service);
void registerResourceService(const Akonadi::DBus::AgentService &service);
void registerPreprocessorService(const Akonadi::DBus::AgentService &service);
void unregisterPreprocessorService(const Akonadi::DBus::AgentService &service);
private:
/**
* The map which stores the .desktop file
......@@ -382,6 +388,7 @@ private:
std::unique_ptr<Akonadi::ProcessControl> mAgentServer;
std::unique_ptr<Akonadi::ProcessControl> mStorageController;
QDBusServiceWatcher mWatcher;
bool mAgentServerEnabled = false;
bool mVerbose = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment