Commit 6ea76b4f authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Partially revert porting away from serviceOwnerChanged signal

This reverts commits 5242bf27
(D26274) and 8b879883 (D26282).

The QDBusServiceWatcher support for wildcard service watching
has been introduced in Qt 5.13, which we cannot depend on
yet. For now we have to revert to the deprected serviceOwnerChanged()
signal in those cases.
parent 253bb028
......@@ -104,57 +104,12 @@ AgentManager::AgentManager(bool verbose, QObject *parent)
{
new AgentManagerAdaptor(this);
new AgentManagerInternalAdaptor(this);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/AgentManager"), this);
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;
}
}
});
connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged,
this, &AgentManager::serviceOwnerChanged);
if (bus.interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) {
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) {
qFatal("akonadiserver already running!");
}
......@@ -682,116 +637,134 @@ void AgentManager::save()
file.endGroup();
}
void AgentManager::registerAgentService(const Akonadi::DBus::AgentService &service)
void AgentManager::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
{
if (!mAgentInstances.contains(service.identifier)) {
return;
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();
}
}
const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier);
const bool restarting = instance->hasAgentInterface();
if (!instance->obtainAgentInterface()) {
const auto service = Akonadi::DBus::parseAgentServiceName(name);
if (!service.has_value()) {
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.
}
Q_ASSERT(mAgents.contains(instance->agentType()));
const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource);
if (!mAgentInstances.contains(service->identifier)) {
return;
}
if (!restarting && (!isResource || instance->hasResourceInterface())) {
Q_EMIT agentInstanceAdded(service.identifier);
}
}
const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier);
const bool restarting = instance->hasAgentInterface();
if (!instance->obtainAgentInterface()) {
return;
}
void AgentManager::registerResourceService(const Akonadi::DBus::AgentService &service)
{
if (!mAgentInstances.contains(service.identifier)) {
return;
}
Q_ASSERT(mAgents.contains(instance->agentType()));
const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource);
const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier);
const bool restarting = instance->hasResourceInterface();
if (!instance->obtainResourceInterface()) {
return;
}
if (!restarting && (!isResource || instance->hasResourceInterface())) {
Q_EMIT agentInstanceAdded(service->identifier);
}
if (!restarting && instance->hasAgentInterface()) {
Q_EMIT agentInstanceAdded(service.identifier);
break;
}
}
case Akonadi::DBus::Resource: {
// A resource service went up or down
if (newOwner.isEmpty()) {
return; // It went down: we don't care here.
}
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.
if (!mAgentInstances.contains(service->identifier)) {
return;
}
const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier);
const bool restarting = instance->hasResourceInterface();
if (!instance->obtainResourceInterface()) {
return;
}
qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service.identifier << " is going up or down...";
if (!restarting && instance->hasAgentInterface()) {
Q_EMIT agentInstanceAdded(service->identifier);
}
// 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 (?)
break;
}
case Akonadi::DBus::Preprocessor: {
// A preprocessor service went up or down
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
// 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 (!preProcessorManager.isValid()) {
qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message();
return;
}
// 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.
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;
}
// Check if we "know" about it.
qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service->identifier << " is going up or down...";
qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service.identifier;
if (!mAgentInstances.contains(service->identifier)) {
qCDebug(AKONADICONTROL_LOG) << "But it isn't registered as agent... not mine (anymore?)";
return; // not our agent (?)
}
// Add to the preprocessor chain
preProcessorManager.registerInstance(service.identifier);
}
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
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.
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.
org::freedesktop::Akonadi::PreprocessorManager preProcessorManager(
Akonadi::DBus::serviceName(Akonadi::DBus::Server),
QStringLiteral("/PreprocessorManager"),
QDBusConnection::sessionBus(),
this);
preProcessorManager.unregisterInstance(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);
}
} else {
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;
// The preprocessor went up. Register it on server side.
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;
}
qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service->identifier;
// Add to the preprocessor chain
preProcessorManager.registerInstance(service->identifier);
}
}
}
return false;
break;
}
default:
break;
}
}
bool AgentManager::checkInstance(const QString &identifier) const
......
......@@ -23,11 +23,9 @@
#include <QHash>
#include <QStringList>
#include <QDBusServiceWatcher>
#include "agenttype.h"
#include "agentinstance.h"
#include <private/dbus_p.h>
class QDir;
......@@ -325,6 +323,7 @@ Q_SIGNALS:
private Q_SLOTS:
void updatePluginInfos();
void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
void agentExeChanged(const QString &fileName);
private:
......@@ -357,7 +356,6 @@ 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;
......@@ -366,10 +364,6 @@ 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
......@@ -388,7 +382,6 @@ private:
std::unique_ptr<Akonadi::ProcessControl> mAgentServer;
std::unique_ptr<Akonadi::ProcessControl> mStorageController;
QDBusServiceWatcher mWatcher;
bool mAgentServerEnabled = false;
bool mVerbose = false;
......
......@@ -25,14 +25,13 @@
#include "resourceinterface.h"
#include <memory>
#include <private/dbus_p.h>
#include <QReadWriteLock>
#include <QScopedPointer>
#include <QWaitCondition>
#include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <QDBusConnectionInterface>
using namespace Akonadi;
using namespace Akonadi::Server;
......@@ -66,22 +65,28 @@ void ItemRetrievalManager::init()
AkThread::init();
QDBusConnection conn = DBusConnectionPool::threadConnection();
mDBusWatcher = std::make_unique<QDBusServiceWatcher>(
QStringLiteral("org.freedesktop.Akonadi.Resource*"), conn,
QDBusServiceWatcher::WatchForUnregistration);
connect(mDBusWatcher.get(), &QDBusServiceWatcher::serviceUnregistered,
this, [this](const QString &serviceName) {
const auto service = DBus::parseAgentServiceName(serviceName);
if (service.has_value() && service->agentType == DBus::Resource) {
qCInfo(AKONADISERVER_LOG) << "ItemRetrievalManager has lost connection to resource" << serviceName << ", discarding cached interface.";
mResourceInterfaces.erase(service->identifier);
}
});
connect(conn.interface(), &QDBusConnectionInterface::serviceOwnerChanged,
this, &ItemRetrievalManager::serviceOwnerChanged);
connect(this, &ItemRetrievalManager::requestAdded,
this, &ItemRetrievalManager::processRequest,
Qt::QueuedConnection);
}
// called within the retrieval thread
void ItemRetrievalManager::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
{
Q_UNUSED(newOwner);
if (oldOwner.isEmpty()) {
return;
}
const auto service = DBus::parseAgentServiceName(serviceName);
if (!service.has_value() || service->agentType != DBus::Resource) {
return;
}
qCDebug(AKONADISERVER_LOG) << "ItemRetrievalManager lost connection to resource" << serviceName << ", discarding cached interface";
mResourceInterfaces.erase(service->identifier);
}
// called within the retrieval thread
org::freedesktop::Akonadi::Resource *ItemRetrievalManager::resourceInterface(const QString &id)
{
......
......@@ -32,7 +32,6 @@
#include <unordered_map>
class OrgFreedesktopAkonadiResourceInterface;
class QDBusServiceWatcher;
namespace Akonadi
{
......@@ -81,6 +80,7 @@ private:
private Q_SLOTS:
void init() override;
void serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner);
void processRequest();
void retrievalJobFinished(ItemRetrievalRequest *request, const QString &errorMsg);
......@@ -98,7 +98,6 @@ protected:
// resource dbus interface cache
std::unordered_map<QString, std::unique_ptr<OrgFreedesktopAkonadiResourceInterface>> mResourceInterfaces;
std::unique_ptr<QDBusServiceWatcher> mDBusWatcher;
};
} // namespace Server
......
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