Akonadi

resourcesynchronizationjob.cpp
1 /*
2  * SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  */
6 
7 #include "resourcesynchronizationjob.h"
8 #include "agentinstance.h"
9 #include "agentmanager.h"
10 #include "akonadicore_debug.h"
11 #include "kjobprivatebase_p.h"
12 #include "resourceinterface.h"
13 #include "servermanager.h"
14 #include <QDBusConnection>
15 
16 #include <KLocalizedString>
17 
18 #include <QDBusInterface>
19 #include <QTimer>
20 
21 namespace Akonadi
22 {
23 class ResourceSynchronizationJobPrivate : public KJobPrivateBase
24 {
25  Q_OBJECT
26 
27 public:
28  explicit ResourceSynchronizationJobPrivate(ResourceSynchronizationJob *parent)
29  : q(parent)
30  {
31  connect(&safetyTimer, &QTimer::timeout, this, &ResourceSynchronizationJobPrivate::slotTimeout);
32  safetyTimer.setInterval(std::chrono::seconds{30});
33  safetyTimer.setSingleShot(true);
34  }
35 
36  void doStart() override;
37 
38  ResourceSynchronizationJob *const q;
39  AgentInstance instance;
40  std::unique_ptr<org::freedesktop::Akonadi::Resource> interface;
41  QTimer safetyTimer;
42  int timeoutCount = 60;
43  bool collectionTreeOnly = false;
44  int timeoutCountLimit = 0;
45 
46  void slotSynchronized();
47  void slotTimeout();
48 };
49 
51  : KJob(parent)
52  , d(new ResourceSynchronizationJobPrivate(this))
53 {
54  d->instance = instance;
55 }
56 
58 
59 void ResourceSynchronizationJob::start()
60 {
61  d->start();
62 }
63 
64 void ResourceSynchronizationJob::setTimeoutCountLimit(int count)
65 {
66  d->timeoutCountLimit = count;
67 }
68 
69 int ResourceSynchronizationJob::timeoutCountLimit() const
70 {
71  return d->timeoutCountLimit;
72 }
73 
75 {
76  return d->collectionTreeOnly;
77 }
78 
80 {
81  d->collectionTreeOnly = b;
82 }
83 
84 void ResourceSynchronizationJobPrivate::doStart()
85 {
86  if (!instance.isValid()) {
87  q->setError(KJob::UserDefinedError);
88  q->setErrorText(i18n("Invalid resource instance."));
89  q->emitResult();
90  return;
91  }
92 
93  using ResourceIface = org::freedesktop::Akonadi::Resource;
94  interface = std::make_unique<ResourceIface>(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()),
95  QStringLiteral("/"),
97  if (collectionTreeOnly) {
98  connect(interface.get(), &ResourceIface::collectionTreeSynchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized);
99  } else {
100  connect(interface.get(), &ResourceIface::synchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized);
101  }
102 
103  if (interface->isValid()) {
104  if (collectionTreeOnly) {
105  instance.synchronizeCollectionTree();
106  } else {
107  instance.synchronize();
108  }
109 
110  safetyTimer.start();
111  } else {
112  q->setError(KJob::UserDefinedError);
113  q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier()));
114  q->emitResult();
115  return;
116  }
117 }
118 
119 void ResourceSynchronizationJobPrivate::slotSynchronized()
120 {
121  using ResourceIface = org::freedesktop::Akonadi::Resource;
122  if (collectionTreeOnly) {
123  disconnect(interface.get(), &ResourceIface::collectionTreeSynchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized);
124  } else {
125  disconnect(interface.get(), &ResourceIface::synchronized, this, &ResourceSynchronizationJobPrivate::slotSynchronized);
126  }
127  safetyTimer.stop();
128  q->emitResult();
129 }
130 
131 void ResourceSynchronizationJobPrivate::slotTimeout()
132 {
133  instance = AgentManager::self()->instance(instance.identifier());
134  timeoutCount++;
135 
136  if (timeoutCount > timeoutCountLimit) {
137  safetyTimer.stop();
138  q->setError(KJob::UserDefinedError);
139  q->setErrorText(i18n("Resource synchronization timed out."));
140  q->emitResult();
141  return;
142  }
143 
144  if (instance.status() == AgentInstance::Idle) {
145  // try again, we might have lost the synchronized()/synchronizedCollectionTree() signal
146  qCDebug(AKONADICORE_LOG) << "trying again to sync resource" << instance.identifier();
147  if (collectionTreeOnly) {
148  instance.synchronizeCollectionTree();
149  } else {
150  instance.synchronize();
151  }
152  }
153 }
154 
156 {
157  return d->instance;
158 }
159 
160 } // namespace Akonadi
161 
162 #include "resourcesynchronizationjob.moc"
QString identifier() const
Returns the unique identifier of the agent instance.
bool collectionTreeOnly() const
Returns whether a full synchronization will be done, or just the collection tree (without items).
void setCollectionTreeOnly(bool collectionTreeOnly)
Sets the collectionTreeOnly property.
AgentInstance resource() const
Returns the resource that has been synchronized.
ResourceSynchronizationJob(const AgentInstance &instance, QObject *parent=nullptr)
Creates a new synchronization job for the given resource.
AgentInstance instance(const QString &identifier) const
Returns the agent instance with the given identifier or an invalid agent instance if the identifier d...
QString i18n(const char *text, const TYPE &arg...)
QDBusConnection sessionBus()
~ResourceSynchronizationJob() override
Destroys the synchronization job.
Represents one agent instance and takes care of communication with it.
void timeout()
static AgentManager * self()
Returns the global instance of the agent manager.
@ Idle
The agent instance does currently nothing.
A representation of an agent instance.
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:52:16 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.