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 | |
32 | namespace Akonadi |
33 | { |
34 | |
35 | class ResourceSynchronizationJobPrivate : public KJobPrivateBase |
36 | { |
37 | public: |
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 | |
61 | int ResourceSynchronizationJobPrivate::timeoutCountLimit = 60; |
62 | |
63 | ResourceSynchronizationJob::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 | |
74 | ResourceSynchronizationJob::~ResourceSynchronizationJob() |
75 | { |
76 | delete d; |
77 | } |
78 | |
79 | void ResourceSynchronizationJob::start() |
80 | { |
81 | d->start(); |
82 | } |
83 | |
84 | bool ResourceSynchronizationJob::collectionTreeOnly() const |
85 | { |
86 | return d->collectionTreeOnly; |
87 | } |
88 | |
89 | void ResourceSynchronizationJob::setCollectionTreeOnly(bool b) |
90 | { |
91 | d->collectionTreeOnly = b; |
92 | } |
93 | |
94 | void 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 | |
129 | void 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 | |
140 | void 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 | |
164 | AgentInstance ResourceSynchronizationJob::resource() const |
165 | { |
166 | return d->instance; |
167 | } |
168 | |
169 | } |
170 | |
171 | #include "moc_resourcesynchronizationjob.cpp" |
172 | |