1/*
2 * Copyright (c) 2009 Volker Krause <vkrause@kde.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "collectionattributessynchronizationjob.h"
19#include "dbusconnectionpool.h"
20#include "kjobprivatebase_p.h"
21#include "servermanager.h"
22
23#include <akonadi/agentinstance.h>
24#include <akonadi/agentmanager.h>
25#include <akonadi/collection.h>
26
27#include <KDebug>
28#include <KLocalizedString>
29
30#include <QDBusConnection>
31#include <QDBusInterface>
32#include <QTimer>
33
34namespace Akonadi
35{
36
37class CollectionAttributesSynchronizationJobPrivate : public KJobPrivateBase
38{
39public:
40 CollectionAttributesSynchronizationJobPrivate(CollectionAttributesSynchronizationJob *parent)
41 : q(parent)
42 , interface(0)
43 , safetyTimer(0)
44 , timeoutCount(0)
45 {
46 }
47
48 void doStart();
49
50 CollectionAttributesSynchronizationJob *q;
51 AgentInstance instance;
52 Collection collection;
53 QDBusInterface *interface;
54 QTimer *safetyTimer;
55 int timeoutCount;
56 static int timeoutCountLimit;
57
58 void slotSynchronized(qlonglong);
59 void slotTimeout();
60};
61
62int CollectionAttributesSynchronizationJobPrivate::timeoutCountLimit = 2;
63
64CollectionAttributesSynchronizationJob::CollectionAttributesSynchronizationJob(const Collection &collection, QObject *parent)
65 : KJob(parent)
66 , d(new CollectionAttributesSynchronizationJobPrivate(this))
67{
68 d->instance = AgentManager::self()->instance(collection.resource());
69 d->collection = collection;
70 d->safetyTimer = new QTimer(this);
71 connect(d->safetyTimer, SIGNAL(timeout()), SLOT(slotTimeout()));
72 d->safetyTimer->setInterval(5 * 1000);
73 d->safetyTimer->setSingleShot(false);
74}
75
76CollectionAttributesSynchronizationJob::~CollectionAttributesSynchronizationJob()
77{
78 delete d;
79}
80
81void CollectionAttributesSynchronizationJob::start()
82{
83 d->start();
84}
85
86void CollectionAttributesSynchronizationJobPrivate::doStart()
87{
88 if (!collection.isValid()) {
89 q->setError(KJob::UserDefinedError);
90 q->setErrorText(i18n("Invalid collection instance."));
91 q->emitResult();
92 return;
93 }
94
95 if (!instance.isValid()) {
96 q->setError(KJob::UserDefinedError);
97 q->setErrorText(i18n("Invalid resource instance."));
98 q->emitResult();
99 return;
100 }
101
102 interface = new QDBusInterface(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()),
103 QString::fromLatin1("/"),
104 QString::fromLatin1("org.freedesktop.Akonadi.Resource"),
105 DBusConnectionPool::threadConnection(), this);
106 connect(interface, SIGNAL(attributesSynchronized(qlonglong)),
107 q, SLOT(slotSynchronized(qlonglong)));
108
109 if (interface->isValid()) {
110 const QDBusMessage reply = interface->call(QString::fromUtf8("synchronizeCollectionAttributes"), collection.id());
111 if (reply.type() == QDBusMessage::ErrorMessage) {
112 // This means that the resource doesn't provide a synchronizeCollectionAttributes method, so we just finish the job
113 q->emitResult();
114 return;
115 }
116 safetyTimer->start();
117 } else {
118 q->setError(KJob::UserDefinedError);
119 q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier()));
120 q->emitResult();
121 return;
122 }
123}
124
125void CollectionAttributesSynchronizationJobPrivate::slotSynchronized(qlonglong id)
126{
127 if (id == collection.id()) {
128 q->disconnect(interface, SIGNAL(attributesSynchronized(qlonglong)),
129 q, SLOT(slotSynchronized(qlonglong)));
130 safetyTimer->stop();
131 q->emitResult();
132 }
133}
134
135void CollectionAttributesSynchronizationJobPrivate::slotTimeout()
136{
137 instance = AgentManager::self()->instance(instance.identifier());
138 timeoutCount++;
139
140 if (timeoutCount > timeoutCountLimit) {
141 safetyTimer->stop();
142 q->setError(KJob::UserDefinedError);
143 q->setErrorText(i18n("Collection attributes synchronization timed out."));
144 q->emitResult();
145 return;
146 }
147
148 if (instance.status() == AgentInstance::Idle) {
149 // try again, we might have lost the synchronized() signal
150 kDebug() << "trying again to sync collection attributes" << collection.id() << instance.identifier();
151 interface->call(QString::fromUtf8("synchronizeCollectionAttributes"), collection.id());
152 }
153}
154
155}
156
157#include "moc_collectionattributessynchronizationjob.cpp"
158