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 "resourcesynchronizationjob.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
26#include <KDebug>
27#include <KLocalizedString>
28
29#include <QDBusInterface>
30#include <QTimer>
31
32namespace Akonadi
33{
34
35class ResourceSynchronizationJobPrivate : public KJobPrivateBase
36{
37public:
38 ResourceSynchronizationJobPrivate(ResourceSynchronizationJob *parent)
39 : q(parent)
40 , interface(0)
41 , safetyTimer(0)
42 , timeoutCount(0)
43 , collectionTreeOnly(false)
44 {
45 }
46
47 void doStart();
48
49 ResourceSynchronizationJob *q;
50 AgentInstance instance;
51 QDBusInterface *interface;
52 QTimer *safetyTimer;
53 int timeoutCount;
54 bool collectionTreeOnly;
55 static int timeoutCountLimit;
56
57 void slotSynchronized();
58 void slotTimeout();
59};
60
61int ResourceSynchronizationJobPrivate::timeoutCountLimit = 60;
62
63ResourceSynchronizationJob::ResourceSynchronizationJob(const AgentInstance &instance, QObject *parent)
64 : KJob(parent)
65 , d(new ResourceSynchronizationJobPrivate(this))
66{
67 d->instance = instance;
68 d->safetyTimer = new QTimer(this);
69 connect(d->safetyTimer, SIGNAL(timeout()), SLOT(slotTimeout()));
70 d->safetyTimer->setInterval(10 * 1000);
71 d->safetyTimer->setSingleShot(false);
72}
73
74ResourceSynchronizationJob::~ResourceSynchronizationJob()
75{
76 delete d;
77}
78
79void ResourceSynchronizationJob::start()
80{
81 d->start();
82}
83
84bool ResourceSynchronizationJob::collectionTreeOnly() const
85{
86 return d->collectionTreeOnly;
87}
88
89void ResourceSynchronizationJob::setCollectionTreeOnly(bool b)
90{
91 d->collectionTreeOnly = b;
92}
93
94void ResourceSynchronizationJobPrivate::doStart()
95{
96 if (!instance.isValid()) {
97 q->setError(KJob::UserDefinedError);
98 q->setErrorText(i18n("Invalid resource instance."));
99 q->emitResult();
100 return;
101 }
102
103 interface = new QDBusInterface(ServerManager::agentServiceName(ServerManager::Resource, instance.identifier()),
104 QString::fromLatin1("/"),
105 QString::fromLatin1("org.freedesktop.Akonadi.Resource"),
106 DBusConnectionPool::threadConnection(), this);
107 if (collectionTreeOnly) {
108 connect(interface, SIGNAL(collectionTreeSynchronized()), q, SLOT(slotSynchronized()));
109 } else {
110 connect(interface, SIGNAL(synchronized()), q, SLOT(slotSynchronized()));
111 }
112
113 if (interface->isValid()) {
114 if (collectionTreeOnly) {
115 instance.synchronizeCollectionTree();
116 } else {
117 instance.synchronize();
118 }
119
120 safetyTimer->start();
121 } else {
122 q->setError(KJob::UserDefinedError);
123 q->setErrorText(i18n("Unable to obtain D-Bus interface for resource '%1'", instance.identifier()));
124 q->emitResult();
125 return;
126 }
127}
128
129void ResourceSynchronizationJobPrivate::slotSynchronized()
130{
131 if (collectionTreeOnly) {
132 q->disconnect(interface, SIGNAL(collectionTreeSynchronized()), q, SLOT(slotSynchronized()));
133 } else {
134 q->disconnect(interface, SIGNAL(synchronized()), q, SLOT(slotSynchronized()));
135 }
136 safetyTimer->stop();
137 q->emitResult();
138}
139
140void ResourceSynchronizationJobPrivate::slotTimeout()
141{
142 instance = AgentManager::self()->instance(instance.identifier());
143 timeoutCount++;
144
145 if (timeoutCount > timeoutCountLimit) {
146 safetyTimer->stop();
147 q->setError(KJob::UserDefinedError);
148 q->setErrorText(i18n("Resource synchronization timed out."));
149 q->emitResult();
150 return;
151 }
152
153 if (instance.status() == AgentInstance::Idle) {
154 // try again, we might have lost the synchronized()/synchronizedCollectionTree() signal
155 kDebug() << "trying again to sync resource" << instance.identifier();
156 if (collectionTreeOnly) {
157 instance.synchronizeCollectionTree();
158 } else {
159 instance.synchronize();
160 }
161 }
162}
163
164AgentInstance ResourceSynchronizationJob::resource() const
165{
166 return d->instance;
167}
168
169}
170
171#include "moc_resourcesynchronizationjob.cpp"
172