File indexing completed on 2024-11-10 04:40:28

0001 /*
0002  * SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include "collectionattributessynchronizationjob.h"
0008 #include "akonadicore_debug.h"
0009 #include "kjobprivatebase_p.h"
0010 #include "servermanager.h"
0011 #include <QDBusConnection>
0012 
0013 #include "agentinstance.h"
0014 #include "agentmanager.h"
0015 #include "collection.h"
0016 
0017 #include <KLocalizedString>
0018 
0019 #include <QDBusInterface>
0020 #include <QTimer>
0021 
0022 namespace Akonadi
0023 {
0024 class CollectionAttributesSynchronizationJobPrivate : public KJobPrivateBase
0025 {
0026     Q_OBJECT
0027 
0028 public:
0029     explicit CollectionAttributesSynchronizationJobPrivate(CollectionAttributesSynchronizationJob *parent)
0030         : q(parent)
0031     {
0032         connect(&safetyTimer, &QTimer::timeout, this, &CollectionAttributesSynchronizationJobPrivate::slotTimeout);
0033         safetyTimer.setInterval(std::chrono::seconds{5});
0034         safetyTimer.setSingleShot(false);
0035     }
0036 
0037     void doStart() override;
0038 
0039     CollectionAttributesSynchronizationJob *const q;
0040     AgentInstance instance;
0041     Collection collection;
0042     QDBusInterface *interface = nullptr;
0043     QTimer safetyTimer;
0044     int timeoutCount = 0;
0045     static const int timeoutCountLimit;
0046 
0047 private Q_SLOTS:
0048     void slotSynchronized(qlonglong /*id*/);
0049     void slotTimeout();
0050 };
0051 
0052 const int CollectionAttributesSynchronizationJobPrivate::timeoutCountLimit = 2;
0053 
0054 CollectionAttributesSynchronizationJob::CollectionAttributesSynchronizationJob(const Collection &collection, QObject *parent)
0055     : KJob(parent)
0056     , d(new CollectionAttributesSynchronizationJobPrivate(this))
0057 {
0058     d->instance = AgentManager::self()->instance(collection.resource());
0059     d->collection = collection;
0060 }
0061 
0062 CollectionAttributesSynchronizationJob::~CollectionAttributesSynchronizationJob() = default;
0063 
0064 void CollectionAttributesSynchronizationJob::start()
0065 {
0066     d->start();
0067 }
0068 
0069 void CollectionAttributesSynchronizationJobPrivate::doStart()
0070 {
0071     if (!collection.isValid()) {
0072         q->setError(KJob::UserDefinedError);
0073         q->setErrorText(i18n("Invalid collection instance."));
0074         q->emitResult();
0075         return;
0076     }
0077 
0078     if (!instance.isValid()) {
0079         q->setError(KJob::UserDefinedError);
0080         q->setErrorText(i18n("Invalid resource instance."));
0081         q->emitResult();
0082         return;
0083     }
0084 
0085     interface = new QDBusInterface(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()),
0086                                    QStringLiteral("/"),
0087                                    QStringLiteral("org.freedesktop.Akonadi.Resource"),
0088                                    QDBusConnection::sessionBus(),
0089                                    this);
0090     connect(interface, SIGNAL(attributesSynchronized(qlonglong)), this, SLOT(slotSynchronized(qlonglong))); // clazy:exclude=old-style-connect
0091 
0092     if (interface->isValid()) {
0093         const QDBusMessage reply = interface->call(QStringLiteral("synchronizeCollectionAttributes"), collection.id());
0094         if (reply.type() == QDBusMessage::ErrorMessage) {
0095             // This means that the resource doesn't provide a synchronizeCollectionAttributes method, so we just finish the job
0096             q->emitResult();
0097             return;
0098         }
0099         safetyTimer.start();
0100     } else {
0101         q->setError(KJob::UserDefinedError);
0102         q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier()));
0103         q->emitResult();
0104         return;
0105     }
0106 }
0107 
0108 void CollectionAttributesSynchronizationJobPrivate::slotSynchronized(qlonglong id)
0109 {
0110     if (id == collection.id()) {
0111         disconnect(interface, SIGNAL(attributesSynchronized(qlonglong)), this, SLOT(slotSynchronized(qlonglong))); // clazy:exclude=old-style-connect
0112         safetyTimer.stop();
0113         q->emitResult();
0114     }
0115 }
0116 
0117 void CollectionAttributesSynchronizationJobPrivate::slotTimeout()
0118 {
0119     instance = AgentManager::self()->instance(instance.identifier());
0120     timeoutCount++;
0121 
0122     if (timeoutCount > timeoutCountLimit) {
0123         safetyTimer.stop();
0124         q->setError(KJob::UserDefinedError);
0125         q->setErrorText(i18n("Collection attributes synchronization timed out."));
0126         q->emitResult();
0127         return;
0128     }
0129 
0130     if (instance.status() == AgentInstance::Idle) {
0131         // try again, we might have lost the synchronized() signal
0132         qCDebug(AKONADICORE_LOG) << "collection attributes" << collection.id() << instance.identifier();
0133         interface->call(QStringLiteral("synchronizeCollectionAttributes"), collection.id());
0134     }
0135 }
0136 
0137 } // namespace Akonadi
0138 
0139 #include "collectionattributessynchronizationjob.moc"
0140 
0141 #include "moc_collectionattributessynchronizationjob.cpp"