SVN_SILENT made messages (.desktop file) - always resolve ours
[kdepim.git] / akonadiconsole / jobtracker.cpp
blob5a6280f1fd5c5706262f510d9e9248aa69bd5a95
1 /*
2 This file is part of Akonadi.
4 Copyright (c) 2009 KDAB
5 Author: Till Adam <adam@kde.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 USA.
23 #include "jobtracker.h"
24 #include "jobtrackeradaptor.h"
25 #include "akonadiconsole_debug.h"
26 #include <QString>
27 #include <QStringList>
28 #include <QPair>
29 #include <QList>
31 #include <cassert>
33 QString JobInfo::stateAsString() const
35 switch (state) {
36 case Initial:
37 return QStringLiteral("Waiting");
38 case Running:
39 return QStringLiteral("Running");
40 case Ended:
41 return QStringLiteral("Ended");
42 case Failed:
43 return QStringLiteral("Failed: %1").arg(error);
44 default:
45 return QStringLiteral("Unknown state!");
49 class JobTracker::Private
51 public:
52 Private(JobTracker *_q)
53 : lastId(42), timer(_q), disabled(false), q(_q)
55 timer.setSingleShot(true);
56 timer.setInterval(200);
57 connect(&timer, &QTimer::timeout, q, &JobTracker::signalUpdates);
60 bool isSession(int id) const
62 return id < -1;
65 void emitUpdated()
67 if (!timer.isActive() && !disabled) {
68 timer.start();
72 QStringList sessions;
73 QHash<QString, int> idToSequence;
74 QHash<int, QString> sequenceToId;
75 QHash<QString, QStringList> jobs;
76 QHash<QString, JobInfo> infoList;
77 int lastId;
78 QTimer timer;
79 bool disabled;
80 QList< QPair<int, int> > unpublishedAdds;
81 QList< QPair<int, int> > unpublishedUpdates;
82 private:
83 JobTracker *const q;
86 JobTracker::JobTracker(const char *name, QObject *parent)
87 : QObject(parent), d(new Private(this))
89 new JobTrackerAdaptor(this);
90 QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.akonadiconsole"));
91 QDBusConnection::sessionBus().registerObject(QLatin1Char('/') + QLatin1String(name),
92 this, QDBusConnection::ExportAdaptors);
94 #if 0
95 // dummy data for testing
96 d->sessions << "one" << "two" << "three";
97 d->jobs.insert("one", QStringList() << "eins");
98 d->jobs.insert("two", QStringList());
99 d->jobs.insert("three", QStringList());
101 // create some fake jobs
102 d->jobs.insert("eins", QStringList() << "sub-eins" << "sub-zwei");
103 d->idToSequence.insert("eins", 0);
104 d->sequenceToId.insert(0, "eins");
105 JobInfo info;
106 info.id = "eins";
107 info.parent = -2;
108 d->infoList.insert("eins", info);
110 d->jobs.insert("sub-eins", QStringList());
111 d->idToSequence.insert("sub-eins", 1);
112 d->sequenceToId.insert(1, "sub-eins");
113 info.id = "sub-eins";
114 info.parent = 0;
115 d->infoList.insert("sub-eins", info);
117 d->jobs.insert("sub-zwei", QStringList());
118 d->idToSequence.insert("sub-zwei", 2);
119 d->sequenceToId.insert(2, "sub-zwei");
120 info.id = "sub-zwei";
121 info.parent = 0;
122 d->infoList.insert("sub-zwei", info);
123 #endif
126 JobTracker::~JobTracker()
128 delete d;
131 void JobTracker::jobCreated(const QString &session, const QString &job, const QString &parent, const QString &jobType, const QString &debugString)
133 if (d->disabled || session.isEmpty() || job.isEmpty()) {
134 return;
137 if (!parent.isEmpty() && !d->jobs.contains(parent)) {
138 qCWarning(AKONADICONSOLE_LOG) << "JobTracker: Job arrived before its parent! Fix the library!";
139 jobCreated(session, parent, QString(), QStringLiteral("dummy job type"), QString());
141 // check if it's a new session, if so, add it
142 if (d->sessions.isEmpty() || !d->sessions.contains(session)) {
143 d->sessions.append(session);
144 d->jobs.insert(session, QStringList());
145 d->unpublishedAdds << QPair<int, int>(d->sessions.count() - 1, -1);
148 // deal with the job
149 if (d->jobs.contains(job)) {
150 if (d->infoList.value(job).state == JobInfo::Running) {
151 qCDebug(AKONADICONSOLE_LOG) << "Job was already known and still running:" << job << "from" << d->infoList.value(job).timestamp.secsTo(QDateTime::currentDateTime()) << "s ago";
153 // otherwise it just means the pointer got reused... replace old job
156 d->jobs.insert(job, QStringList());
158 JobInfo info;
159 info.id = job;
160 if (parent.isEmpty()) {
161 info.parent = idForSession(session);
162 } else {
163 info.parent = idForJob(parent);
165 info.state = JobInfo::Initial;
166 info.timestamp = QDateTime::currentDateTime();
167 info.type = jobType;
168 info.debugString = debugString;
169 d->infoList.insert(job, info);
170 const int id = d->lastId++;
171 d->idToSequence.insert(job, id);
172 d->sequenceToId.insert(id, job);
174 QString daddy;
175 if (parent.isEmpty()) {
176 daddy = session;
177 } else {
178 daddy = parent;
181 assert(!daddy.isEmpty());
182 QStringList kids = d->jobs[daddy];
183 kids << job;
184 const int pos = d->jobs[daddy].size();
185 d->jobs[daddy] = kids;
187 d->unpublishedAdds << QPair<int, int>(pos, info.parent);
188 d->emitUpdated();
191 void JobTracker::jobEnded(const QString &job, const QString &error)
193 // this is called from dbus, so better be defensive
194 if (d->disabled || !d->jobs.contains(job) || !d->infoList.contains(job)) {
195 return;
198 JobInfo info = d->infoList[job];
199 if (error.isEmpty()) {
200 info.state = JobInfo::Ended;
201 } else {
202 info.state = JobInfo::Failed;
203 info.error = error;
205 info.endedTimestamp = QDateTime::currentDateTime();
206 d->infoList[job] = info;
208 d->unpublishedUpdates << QPair<int, int>(d->jobs[jobForId(info.parent)].size() - 1, info.parent);
209 d->emitUpdated();
212 void JobTracker::jobStarted(const QString &job)
214 // this is called from dbus, so better be defensive
215 if (d->disabled || !d->jobs.contains(job) || !d->infoList.contains(job)) {
216 return;
219 JobInfo info = d->infoList[job];
220 info.state = JobInfo::Running;
221 info.startedTimestamp = QDateTime::currentDateTime();
222 d->infoList[job] = info;
224 d->unpublishedUpdates << QPair<int, int>(d->jobs[jobForId(info.parent)].size() - 1, info.parent);
225 d->emitUpdated();
228 QStringList JobTracker::sessions() const
230 return d->sessions;
233 QList<JobInfo> JobTracker::jobs(int id) const
235 if (d->isSession(id)) {
236 return jobs(sessionForId(id));
238 return jobs(jobForId(id));
241 QList<JobInfo> JobTracker::jobs(const QString &parent) const
243 assert(d->jobs.contains(parent));
244 const QStringList jobs = d->jobs.value(parent);
245 QList<JobInfo> infoList;
246 Q_FOREACH (const QString &job, jobs) {
247 infoList << d->infoList.value(job);
249 return infoList;
252 QStringList JobTracker::jobNames(int id) const
254 if (d->isSession(id)) {
255 return d->jobs.value(sessionForId(id));
257 return d->jobs.value(jobForId(id));
260 // only works on jobs
261 int JobTracker::idForJob(const QString &job) const
263 assert(d->idToSequence.contains(job));
264 return d->idToSequence.value(job);
267 QString JobTracker::jobForId(int id) const
269 if (d->isSession(id)) {
270 return sessionForId(id);
272 assert(d->sequenceToId.contains(id));
273 return d->sequenceToId.value(id);
276 // To find a session, we take the offset in the list of sessions
277 // in order of appearance, add one, and make it negative. That
278 // way we can discern session ids from job ids and use -1 for invalid
279 int JobTracker::idForSession(const QString &session) const
281 assert(d->sessions.contains(session));
282 return (d->sessions.indexOf(session) + 2) * -1;
285 QString JobTracker::sessionForId(int _id) const
287 const int id = (-_id) - 2;
288 assert(d->sessions.size() > id);
289 if (!d->sessions.isEmpty()) {
290 return d->sessions.at(id);
291 } else {
292 return QString();
296 int JobTracker::parentId(int id) const
298 if (d->isSession(id)) {
299 return -1;
300 } else {
301 const QString job = d->sequenceToId.value(id);
302 return d->infoList[job].parent;
307 JobInfo JobTracker::info(int id) const
309 return info(jobForId(id));
312 JobInfo JobTracker::info(const QString &job) const
314 assert(d->infoList.contains(job));
315 return d->infoList.value(job);
318 void JobTracker::triggerReset()
320 d->sessions.clear();
321 d->idToSequence.clear();
322 d->sequenceToId.clear();
323 d->jobs.clear();
324 d->infoList.clear();
326 Q_EMIT reset();
329 void JobTracker::setEnabled(bool on)
331 d->disabled = !on;
334 bool JobTracker::isEnabled() const
336 return !d->disabled;
339 void JobTracker::signalUpdates()
341 Q_EMIT added(d->unpublishedAdds);
342 Q_EMIT updated(d->unpublishedUpdates);
343 d->unpublishedAdds.clear();
344 d->unpublishedUpdates.clear();