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 | |
34 | namespace Akonadi |
35 | { |
36 | |
37 | class CollectionAttributesSynchronizationJobPrivate : public KJobPrivateBase |
38 | { |
39 | public: |
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 | |
62 | int CollectionAttributesSynchronizationJobPrivate::timeoutCountLimit = 2; |
63 | |
64 | CollectionAttributesSynchronizationJob::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 | |
76 | CollectionAttributesSynchronizationJob::~CollectionAttributesSynchronizationJob() |
77 | { |
78 | delete d; |
79 | } |
80 | |
81 | void CollectionAttributesSynchronizationJob::start() |
82 | { |
83 | d->start(); |
84 | } |
85 | |
86 | void 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 | |
125 | void 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 | |
135 | void 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 | |