Akonadi

collectionattributessynchronizationjob.cpp
1 /*
2  * SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  */
6 
7 #include "collectionattributessynchronizationjob.h"
8 #include "akonadicore_debug.h"
9 #include "kjobprivatebase_p.h"
10 #include "servermanager.h"
11 #include <QDBusConnection>
12 
13 #include "agentinstance.h"
14 #include "agentmanager.h"
15 #include "collection.h"
16 
17 #include <KLocalizedString>
18 
19 #include <QDBusInterface>
20 #include <QTimer>
21 
22 namespace Akonadi
23 {
24 class CollectionAttributesSynchronizationJobPrivate : public KJobPrivateBase
25 {
26  Q_OBJECT
27 
28 public:
29  explicit CollectionAttributesSynchronizationJobPrivate(CollectionAttributesSynchronizationJob *parent)
30  : q(parent)
31  {
32  connect(&safetyTimer, &QTimer::timeout, this, &CollectionAttributesSynchronizationJobPrivate::slotTimeout);
33  safetyTimer.setInterval(std::chrono::seconds{5});
34  safetyTimer.setSingleShot(false);
35  }
36 
37  void doStart() override;
38 
39  CollectionAttributesSynchronizationJob *const q;
40  AgentInstance instance;
41  Collection collection;
42  QDBusInterface *interface = nullptr;
43  QTimer safetyTimer;
44  int timeoutCount = 0;
45  static const int timeoutCountLimit;
46 
47 private Q_SLOTS:
48  void slotSynchronized(qlonglong /*id*/);
49  void slotTimeout();
50 };
51 
52 const int CollectionAttributesSynchronizationJobPrivate::timeoutCountLimit = 2;
53 
55  : KJob(parent)
56  , d(new CollectionAttributesSynchronizationJobPrivate(this))
57 {
58  d->instance = AgentManager::self()->instance(collection.resource());
59  d->collection = collection;
60 }
61 
63 
65 {
66  d->start();
67 }
68 
69 void CollectionAttributesSynchronizationJobPrivate::doStart()
70 {
71  if (!collection.isValid()) {
72  q->setError(KJob::UserDefinedError);
73  q->setErrorText(i18n("Invalid collection instance."));
74  q->emitResult();
75  return;
76  }
77 
78  if (!instance.isValid()) {
79  q->setError(KJob::UserDefinedError);
80  q->setErrorText(i18n("Invalid resource instance."));
81  q->emitResult();
82  return;
83  }
84 
85  interface = new QDBusInterface(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()),
86  QStringLiteral("/"),
87  QStringLiteral("org.freedesktop.Akonadi.Resource"),
89  this);
90  connect(interface, SIGNAL(attributesSynchronized(qlonglong)), this, SLOT(slotSynchronized(qlonglong))); // clazy:exclude=old-style-connect
91 
92  if (interface->isValid()) {
93  const QDBusMessage reply = interface->call(QStringLiteral("synchronizeCollectionAttributes"), collection.id());
94  if (reply.type() == QDBusMessage::ErrorMessage) {
95  // This means that the resource doesn't provide a synchronizeCollectionAttributes method, so we just finish the job
96  q->emitResult();
97  return;
98  }
99  safetyTimer.start();
100  } else {
101  q->setError(KJob::UserDefinedError);
102  q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier()));
103  q->emitResult();
104  return;
105  }
106 }
107 
108 void CollectionAttributesSynchronizationJobPrivate::slotSynchronized(qlonglong id)
109 {
110  if (id == collection.id()) {
111  disconnect(interface, SIGNAL(attributesSynchronized(qlonglong)), this, SLOT(slotSynchronized(qlonglong))); // clazy:exclude=old-style-connect
112  safetyTimer.stop();
113  q->emitResult();
114  }
115 }
116 
117 void CollectionAttributesSynchronizationJobPrivate::slotTimeout()
118 {
119  instance = AgentManager::self()->instance(instance.identifier());
120  timeoutCount++;
121 
122  if (timeoutCount > timeoutCountLimit) {
123  safetyTimer.stop();
124  q->setError(KJob::UserDefinedError);
125  q->setErrorText(i18n("Collection attributes synchronization timed out."));
126  q->emitResult();
127  return;
128  }
129 
130  if (instance.status() == AgentInstance::Idle) {
131  // try again, we might have lost the synchronized() signal
132  qCDebug(AKONADICORE_LOG) << "collection attributes" << collection.id() << instance.identifier();
133  interface->call(QStringLiteral("synchronizeCollectionAttributes"), collection.id());
134  }
135 }
136 
137 } // namespace Akonadi
138 
139 #include "collectionattributessynchronizationjob.moc"
QString identifier() const
Returns the unique identifier of the agent instance.
Q_SCRIPTABLE Q_NOREPLY void start()
Represents a collection of PIM items.
Definition: collection.h:61
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()
Represents one agent instance and takes care of communication with it.
void timeout()
CollectionAttributesSynchronizationJob(const Collection &collection, QObject *parent=nullptr)
Creates a new synchronization job for the given collection.
~CollectionAttributesSynchronizationJob() override
Destroys the synchronization job.
bool isValid(QStringView ifopt)
static AgentManager * self()
Returns the global instance of the agent manager.
@ Idle
The agent instance does currently nothing.
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:00:31 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.