File indexing completed on 2024-11-10 04:40:31
0001 /* 0002 * SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "resourcesynchronizationjob.h" 0008 #include "agentinstance.h" 0009 #include "agentmanager.h" 0010 #include "akonadicore_debug.h" 0011 #include "kjobprivatebase_p.h" 0012 #include "resourceinterface.h" 0013 #include "servermanager.h" 0014 #include <QDBusConnection> 0015 0016 #include <KLocalizedString> 0017 0018 #include <QDBusInterface> 0019 #include <QTimer> 0020 0021 namespace Akonadi 0022 { 0023 class ResourceSynchronizationJobPrivate : public KJobPrivateBase 0024 { 0025 Q_OBJECT 0026 0027 public: 0028 explicit ResourceSynchronizationJobPrivate(ResourceSynchronizationJob *parent) 0029 : q(parent) 0030 { 0031 connect(&safetyTimer, &QTimer::timeout, this, &ResourceSynchronizationJobPrivate::slotTimeout); 0032 safetyTimer.setInterval(std::chrono::seconds{30}); 0033 safetyTimer.setSingleShot(true); 0034 } 0035 0036 void doStart() override; 0037 0038 ResourceSynchronizationJob *const q; 0039 AgentInstance instance; 0040 std::unique_ptr<org::freedesktop::Akonadi::Resource> interface; 0041 QTimer safetyTimer; 0042 int timeoutCount = 60; 0043 bool collectionTreeOnly = false; 0044 int timeoutCountLimit = 0; 0045 0046 void slotSynchronized(); 0047 void slotTimeout(); 0048 }; 0049 0050 ResourceSynchronizationJob::ResourceSynchronizationJob(const AgentInstance &instance, QObject *parent) 0051 : KJob(parent) 0052 , d(new ResourceSynchronizationJobPrivate(this)) 0053 { 0054 d->instance = instance; 0055 } 0056 0057 ResourceSynchronizationJob::~ResourceSynchronizationJob() = default; 0058 0059 void ResourceSynchronizationJob::start() 0060 { 0061 d->start(); 0062 } 0063 0064 void ResourceSynchronizationJob::setTimeoutCountLimit(int count) 0065 { 0066 d->timeoutCountLimit = count; 0067 } 0068 0069 int ResourceSynchronizationJob::timeoutCountLimit() const 0070 { 0071 return d->timeoutCountLimit; 0072 } 0073 0074 bool ResourceSynchronizationJob::collectionTreeOnly() const 0075 { 0076 return d->collectionTreeOnly; 0077 } 0078 0079 void ResourceSynchronizationJob::setCollectionTreeOnly(bool b) 0080 { 0081 d->collectionTreeOnly = b; 0082 } 0083 0084 void ResourceSynchronizationJobPrivate::doStart() 0085 { 0086 if (!instance.isValid()) { 0087 q->setError(KJob::UserDefinedError); 0088 q->setErrorText(i18n("Invalid resource instance.")); 0089 q->emitResult(); 0090 return; 0091 } 0092 0093 using ResourceIface = org::freedesktop::Akonadi::Resource; 0094 interface = std::make_unique<ResourceIface>(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()), 0095 QStringLiteral("/"), 0096 QDBusConnection::sessionBus()); 0097 if (collectionTreeOnly) { 0098 connect(interface.get(), &ResourceIface::collectionTreeSynchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized); 0099 } else { 0100 connect(interface.get(), &ResourceIface::synchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized); 0101 } 0102 0103 if (interface->isValid()) { 0104 if (collectionTreeOnly) { 0105 instance.synchronizeCollectionTree(); 0106 } else { 0107 instance.synchronize(); 0108 } 0109 0110 safetyTimer.start(); 0111 } else { 0112 q->setError(KJob::UserDefinedError); 0113 q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier())); 0114 q->emitResult(); 0115 return; 0116 } 0117 } 0118 0119 void ResourceSynchronizationJobPrivate::slotSynchronized() 0120 { 0121 using ResourceIface = org::freedesktop::Akonadi::Resource; 0122 if (collectionTreeOnly) { 0123 disconnect(interface.get(), &ResourceIface::collectionTreeSynchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized); 0124 } else { 0125 disconnect(interface.get(), &ResourceIface::synchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized); 0126 } 0127 safetyTimer.stop(); 0128 q->emitResult(); 0129 } 0130 0131 void ResourceSynchronizationJobPrivate::slotTimeout() 0132 { 0133 instance = AgentManager::self()->instance(instance.identifier()); 0134 timeoutCount++; 0135 0136 if (timeoutCount > timeoutCountLimit) { 0137 safetyTimer.stop(); 0138 q->setError(KJob::UserDefinedError); 0139 q->setErrorText(i18n("Resource synchronization timed out.")); 0140 q->emitResult(); 0141 return; 0142 } 0143 0144 if (instance.status() == AgentInstance::Idle) { 0145 // try again, we might have lost the synchronized()/synchronizedCollectionTree() signal 0146 qCDebug(AKONADICORE_LOG) << "trying again to sync resource" << instance.identifier(); 0147 if (collectionTreeOnly) { 0148 instance.synchronizeCollectionTree(); 0149 } else { 0150 instance.synchronize(); 0151 } 0152 } 0153 } 0154 0155 AgentInstance ResourceSynchronizationJob::resource() const 0156 { 0157 return d->instance; 0158 } 0159 0160 } // namespace Akonadi 0161 0162 #include "resourcesynchronizationjob.moc" 0163 0164 #include "moc_resourcesynchronizationjob.cpp"