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,
23 #include "jobtracker.h"
24 #include "jobtrackeradaptor.h"
26 #include <QtCore/QString>
27 #include <QtCore/QStringList>
28 #include <QtCore/QDebug>
29 #include <QtCore/QPair>
30 #include <QtCore/QList>
34 QString
JobInfo::stateAsString() const
39 return QLatin1String("Initial");
41 return QLatin1String("Running");
43 return QLatin1String("Ended");
45 return QString::fromLatin1( "Failed: %1" ).arg( error
);
47 return QLatin1String("Unknown state!");
52 class JobTracker::Private
55 Private( JobTracker
*_q
)
56 :lastId( 42 ), timer( _q
), q( _q
)
58 timer
.setSingleShot( true );
59 timer
.setInterval( 200 );
60 connect( &timer
, SIGNAL(timeout()), q
, SLOT(signalUpdates()) );
63 bool isSession( int id
) const
70 if ( !timer
.isActive() && !disabled
)
75 QMap
<QString
, int> idToSequence
;
76 QMap
<int, QString
> sequenceToId
;
77 QMap
<QString
, QStringList
> jobs
;
78 QMap
<QString
, JobInfo
> infos
;
82 QList
< QPair
<int, int> > unpublishedAdds
;
83 QList
< QPair
<int, int> > unpublishedUpdates
;
88 JobTracker::JobTracker( const char *name
, QObject
* parent
)
89 :QObject( parent
), d( new Private( this ) )
91 new JobTrackerAdaptor( this );
92 QDBusConnection::sessionBus().registerService( QLatin1String("org.kde.akonadiconsole") );
93 QDBusConnection::sessionBus().registerObject( '/'+QLatin1String(name
),
94 this, QDBusConnection::ExportAdaptors
);
97 // dummy data for testing
98 d
->sessions
<< "one" << "two" << "three";
99 d
->jobs
.insert("one", QStringList() << "eins" );
100 d
->jobs
.insert("two", QStringList() );
101 d
->jobs
.insert("three", QStringList() );
103 // create some fake jobs
104 d
->jobs
.insert( "eins", QStringList() << "sub-eins" << "sub-zwei" );
105 d
->idToSequence
.insert( "eins", 0 );
106 d
->sequenceToId
.insert( 0, "eins" );
110 d
->infos
.insert( "eins", info
);
112 d
->jobs
.insert( "sub-eins", QStringList() );
113 d
->idToSequence
.insert( "sub-eins", 1 );
114 d
->sequenceToId
.insert( 1, "sub-eins" );
115 info
.id
= "sub-eins";
117 d
->infos
.insert( "sub-eins", info
);
119 d
->jobs
.insert( "sub-zwei", QStringList() );
120 d
->idToSequence
.insert( "sub-zwei", 2 );
121 d
->sequenceToId
.insert( 2, "sub-zwei" );
122 info
.id
= "sub-zwei";
124 d
->infos
.insert( "sub-zwei", info
);
128 JobTracker::~JobTracker()
133 void JobTracker::jobCreated( const QString
& session
, const QString
& job
, const QString
& parent
, const QString
& jobType
)
135 if ( d
->disabled
|| session
.isEmpty() || job
.isEmpty() ) return;
137 if ( !parent
.isEmpty() && !d
->jobs
.contains( parent
) )
139 qWarning() << "JobTracker: Job arrived before it's parent! Fix the library!";
140 jobCreated( session
, parent
, QString(),"dummy job type" );
142 // check if it's a new session, if so, add it
143 if (!d
->sessions
.contains( session
) )
145 d
->sessions
.append( session
);
146 d
->jobs
.insert( session
, QStringList() );
147 d
->unpublishedAdds
<< QPair
<int, int>( d
->sessions
.count()-1, -1 );
151 if ( d
->jobs
.contains( job
) ) return; // duplicate?
153 d
->jobs
.insert( job
, QStringList() );
157 if ( parent
.isEmpty() )
158 info
.parent
= idForSession( session
);
160 info
.parent
= idForJob( parent
);
161 info
.state
= JobInfo::Initial
;
162 info
.timestamp
= QDateTime::currentDateTime();
164 d
->infos
.insert( job
, info
);
165 const int id
= d
->lastId
++;
166 d
->idToSequence
.insert( job
, id
);
167 d
->sequenceToId
.insert( id
, job
);
170 if ( parent
.isEmpty() )
175 assert(!daddy
.isEmpty());
176 QStringList kids
= d
->jobs
[daddy
];
178 const int pos
= d
->jobs
[daddy
].size();
179 d
->jobs
[daddy
] = kids
;
181 d
->unpublishedAdds
<< QPair
<int, int>( pos
, info
.parent
);
185 void JobTracker::jobEnded( const QString
& job
, const QString
& error
)
187 // this is called from dbus, so better be defensive
188 if ( d
->disabled
|| !d
->jobs
.contains( job
) || !d
->infos
.contains( job
) ) return;
190 JobInfo info
= d
->infos
[job
];
191 if ( error
.isEmpty() ) {
192 info
.state
= JobInfo::Ended
;
194 info
.state
= JobInfo::Failed
;
197 d
->infos
[job
] = info
;
199 d
->unpublishedUpdates
<< QPair
<int, int>( d
->jobs
[jobForId(info
.parent
)].size()-1, info
.parent
);
203 void JobTracker::jobStarted( const QString
& job
)
205 // this is called from dbus, so better be defensive
206 if ( d
->disabled
|| !d
->jobs
.contains( job
) || !d
->infos
.contains( job
) ) return;
208 JobInfo info
= d
->infos
[job
];
209 info
.state
= JobInfo::Running
;
210 d
->infos
[job
] = info
;
212 d
->unpublishedUpdates
<< QPair
<int, int>( d
->jobs
[jobForId(info
.parent
)].size()-1, info
.parent
);
216 QStringList
JobTracker::sessions() const
221 QList
<JobInfo
> JobTracker::jobs( int id
) const
223 if ( d
->isSession( id
) )
224 return jobs( sessionForId( id
) );
225 return jobs( jobForId( id
) );
228 QList
<JobInfo
> JobTracker::jobs( const QString
& parent
) const
230 assert( d
->jobs
.contains(parent
) );
231 const QStringList jobs
= d
->jobs
[parent
];
232 QList
<JobInfo
> infos
;
233 Q_FOREACH( const QString
&job
, jobs
)
235 infos
<< d
->infos
[job
];
240 // only works on jobs
241 int JobTracker::idForJob(const QString
& job
) const
243 assert( d
->idToSequence
.contains(job
) );
244 return d
->idToSequence
[job
];
247 QString
JobTracker::jobForId(int id
) const
249 if ( d
->isSession( id
) )
250 return sessionForId( id
);
251 assert( d
->sequenceToId
.contains(id
) );
252 return d
->sequenceToId
[id
];
256 // To find a session, we take the offset in the list of sessions
257 // in order of appearance, add one, and make it negative. That
258 // way we can discern session ids from job ids and use -1 for invalid
259 int JobTracker::idForSession(const QString
& session
) const
261 assert( d
->sessions
.contains( session
) );
262 return ( d
->sessions
.indexOf(session
) + 2 ) * -1;
265 QString
JobTracker::sessionForId(int _id
) const
267 const int id
= (-_id
)-2;
268 assert( d
->sessions
.size() > id
);
269 return d
->sessions
.at(id
);
272 int JobTracker::parentId( int id
) const
274 if ( d
->isSession( id
) )
280 const QString job
= d
->sequenceToId
[id
];
281 return d
->infos
[job
].parent
;
286 JobInfo
JobTracker::info( int id
) const
288 return info( jobForId( id
) );
291 JobInfo
JobTracker::info(const QString
& job
) const
293 assert( d
->infos
.contains(job
) );
294 return d
->infos
[job
];
297 void JobTracker::triggerReset()
300 d
->idToSequence
.clear();
301 d
->sequenceToId
.clear();
308 void JobTracker::setEnabled( bool on
)
313 bool JobTracker::isEnabled() const
318 void JobTracker::signalUpdates()
320 emit
added( d
->unpublishedAdds
);
321 emit
updated( d
->unpublishedUpdates
);
322 d
->unpublishedAdds
.clear();
323 d
->unpublishedUpdates
.clear();
326 #include "jobtracker.moc"