~ubuntu-branches/ubuntu/trusty/icecc-monitor/trusty

« back to all changes in this revision

Viewing changes to src/icecreammonitor.cc

  • Committer: Package Import Robot
  • Author(s): Pino Toscano
  • Date: 2013-06-12 19:13:18 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20130612191318-fnx96k19ehlddj75
Tags: 2.9.90~git20130612-1
* New Git snapshot.
* Drop patch 01_fix_armel_build.diff, applied upstream.
* kdelibs is no more used, so:
  - stop using the kde dh addon
  - remove the pkg-kde-tools and kdelibs5-dev build dependencies
  - add the libqt4-dev build dependency
* There is no more cmake stuff installed, so stop removing it at
  dh_auto_install time.
* Bump the cmake build dependency to 2.8.5, as indicated by the upstream
  build system.
* Override the hyphen-used-as-minus-sign lintian tags, since all the
  man pages shipped are generated from docbook.
* Add the docbook-xml build dependency for correct man pages regeneration.
* Switch copyright to copyright-format v1.0, and update it.
* Update Homepage.
* Add myself to Uploaders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of Icecream.
 
3
 
 
4
    Copyright (c) 2003 Frerich Raabe <raabe@kde.org>
 
5
    Copyright (c) 2003,2004 Stephan Kulow <coolo@kde.org>
 
6
    Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org>
 
7
    Copyright (c) 2007 Dirk Mueller <mueller@kde.org>
 
8
 
 
9
    This program is free software; you can redistribute it and/or modify
 
10
    it under the terms of the GNU General Public License as published by
 
11
    the Free Software Foundation; either version 2 of the License, or
 
12
    (at your option) any later version.
 
13
 
 
14
    This program is distributed in the hope that it will be useful,
 
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
17
    GNU General Public License for more details.
 
18
 
 
19
    You should have received a copy of the GNU General Public License
 
20
    along with this program; if not, write to the Free Software
 
21
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
22
*/
 
23
 
 
24
#include "icecreammonitor.h"
 
25
 
 
26
#include "hostinfo.h"
 
27
#include "statusview.h"
 
28
 
 
29
#include <icecc/comm.h>
 
30
 
 
31
#include <qdebug.h>
 
32
 
 
33
#include <qsocketnotifier.h>
 
34
#include <qtimer.h>
 
35
 
 
36
#include <list>
 
37
#include <iostream>
 
38
 
 
39
using namespace std;
 
40
 
 
41
IcecreamMonitor::IcecreamMonitor( HostInfoManager *manager, QObject *parent)
 
42
    : Monitor(manager, parent)
 
43
    , m_scheduler( 0 )
 
44
    , m_schedulerState( false )
 
45
    , m_discover( 0 )
 
46
    , m_fd_notify( 0 )
 
47
    , m_fd_type(QSocketNotifier::Exception)
 
48
{
 
49
    checkScheduler();
 
50
}
 
51
 
 
52
IcecreamMonitor::~IcecreamMonitor()
 
53
{
 
54
    delete m_scheduler;
 
55
    delete m_discover;
 
56
}
 
57
 
 
58
void IcecreamMonitor::checkScheduler(bool deleteit)
 
59
{
 
60
    qDebug() << "checkScheduler " << deleteit << endl;
 
61
    if ( deleteit ) {
 
62
        m_rememberedJobs.clear();
 
63
        delete m_scheduler;
 
64
        m_scheduler = 0;
 
65
        delete m_fd_notify;
 
66
        m_fd_notify = 0;
 
67
        m_fd_type = QSocketNotifier::Exception;
 
68
        delete m_discover;
 
69
        m_discover = 0;
 
70
        setSchedulerState(false);
 
71
    } else if ( m_scheduler )
 
72
        return;
 
73
    QTimer::singleShot( 1000+(qrand()&1023), this, SLOT( slotCheckScheduler() ) ); // TODO: check if correct
 
74
}
 
75
 
 
76
void IcecreamMonitor::registerNotify(int fd, QSocketNotifier::Type type, const char* slot)
 
77
{
 
78
    if (m_fd_notify) {
 
79
        m_fd_notify->disconnect(this);
 
80
        m_fd_notify->deleteLater();
 
81
    }
 
82
    m_fd_notify = new QSocketNotifier(fd, type, this);
 
83
    m_fd_type = type;
 
84
    QObject::connect(m_fd_notify, SIGNAL(activated(int)), slot);
 
85
}
 
86
 
 
87
void IcecreamMonitor::slotCheckScheduler()
 
88
{
 
89
    if ( m_scheduler )
 
90
        return;
 
91
 
 
92
    list<string> names;
 
93
 
 
94
    if ( !m_current_netname.isEmpty() )
 
95
        names.push_front( m_current_netname.data() );
 
96
    else
 
97
        names.push_front("ICECREAM");
 
98
 
 
99
    if (!qgetenv("USE_SCHEDULER").isEmpty())
 
100
        names.push_front(""); // try $USE_SCHEDULER
 
101
 
 
102
    for ( list<string>::const_iterator it = names.begin(); it != names.end();
 
103
          ++it ) {
 
104
 
 
105
        m_current_netname = it->c_str();
 
106
        if (!m_discover
 
107
            || m_discover->timed_out()) {
 
108
            delete m_discover;
 
109
            m_discover = new DiscoverSched ( m_current_netname.data() );
 
110
        }
 
111
 
 
112
        m_scheduler = m_discover->try_get_scheduler ();
 
113
 
 
114
        if ( m_scheduler ) {
 
115
            hostInfoManager()->setSchedulerName( QString::fromLatin1(m_discover->schedulerName().data()) );
 
116
            hostInfoManager()->setNetworkName( QString::fromLatin1(m_discover->networkName().data()) );
 
117
            m_scheduler->setBulkTransfer();
 
118
            delete m_discover;
 
119
            m_discover = 0;
 
120
            registerNotify(m_scheduler->fd,
 
121
                    QSocketNotifier::Read, SLOT(msgReceived()));
 
122
 
 
123
            if ( !m_scheduler->send_msg ( MonLoginMsg() ) ) {
 
124
                checkScheduler(true);
 
125
                QTimer::singleShot(0, this, SLOT(slotCheckScheduler()));
 
126
            }
 
127
            else {
 
128
                setSchedulerState( true );
 
129
            }
 
130
            return;
 
131
        }
 
132
 
 
133
        if (m_fd_type != QSocketNotifier::Write
 
134
            && m_discover->connect_fd() >= 0) {
 
135
            registerNotify(m_discover->connect_fd(),
 
136
                    QSocketNotifier::Write, SLOT(slotCheckScheduler()));
 
137
            return;
 
138
        }
 
139
        else if (m_fd_type != QSocketNotifier::Read
 
140
                && m_discover->listen_fd() >= 0) {
 
141
                registerNotify(m_discover->listen_fd(),
 
142
                        QSocketNotifier::Read, SLOT(slotCheckScheduler()));
 
143
        }
 
144
        if (m_fd_type == QSocketNotifier::Read)
 
145
            QTimer::singleShot(1000+(qrand()&1023), this, SLOT(slotCheckScheduler()));
 
146
 
 
147
    }
 
148
    setSchedulerState( false );
 
149
}
 
150
 
 
151
void IcecreamMonitor::msgReceived()
 
152
{
 
153
    while (!m_scheduler->read_a_bit() || m_scheduler->has_msg())
 
154
        if (!handle_activity())
 
155
            break;
 
156
}
 
157
 
 
158
bool IcecreamMonitor::handle_activity()
 
159
{
 
160
    Msg *m = m_scheduler->get_msg ();
 
161
    if ( !m ) {
 
162
        qDebug() << "lost connection to scheduler\n";
 
163
        checkScheduler( true );
 
164
        setSchedulerState( false );
 
165
        return false;
 
166
    }
 
167
 
 
168
    switch ( m->type ) {
 
169
    case M_MON_GET_CS:
 
170
        handle_getcs( m );
 
171
        break;
 
172
    case M_MON_JOB_BEGIN:
 
173
        handle_job_begin( m );
 
174
        break;
 
175
    case M_MON_JOB_DONE:
 
176
        handle_job_done( m );
 
177
        break;
 
178
    case M_END:
 
179
        std::cout << "END" << endl;
 
180
        checkScheduler( true );
 
181
        break;
 
182
    case M_MON_STATS:
 
183
        handle_stats( m );
 
184
        break;
 
185
    case M_MON_LOCAL_JOB_BEGIN:
 
186
        handle_local_begin( m );
 
187
        break;
 
188
    case M_JOB_LOCAL_DONE:
 
189
        handle_local_done( m );
 
190
        break;
 
191
    default:
 
192
        cout << "UNKNOWN" << endl;
 
193
        break;
 
194
    }
 
195
    delete m;
 
196
    return true;
 
197
}
 
198
 
 
199
void IcecreamMonitor::handle_getcs( Msg *_m )
 
200
{
 
201
    MonGetCSMsg *m = dynamic_cast<MonGetCSMsg*>( _m );
 
202
    if ( !m ) return;
 
203
    m_rememberedJobs[m->job_id] = Job( m->job_id, m->clientid,
 
204
                                       m->filename.c_str(),
 
205
                                       m->lang == CompileJob::Lang_C ? "C" :
 
206
                                       "C++" );
 
207
    m_view->update( m_rememberedJobs[m->job_id] );
 
208
}
 
209
 
 
210
void IcecreamMonitor::handle_local_begin( Msg *_m )
 
211
{
 
212
    MonLocalJobBeginMsg *m = dynamic_cast<MonLocalJobBeginMsg*>( _m );
 
213
    if ( !m ) return;
 
214
 
 
215
    m_rememberedJobs[m->job_id] = Job( m->job_id, m->hostid,
 
216
                                       m->file.c_str(),
 
217
                                       "C++" );
 
218
    m_rememberedJobs[m->job_id].setState( Job::LocalOnly );
 
219
    m_view->update( m_rememberedJobs[m->job_id] );
 
220
}
 
221
 
 
222
void IcecreamMonitor::handle_local_done( Msg *_m )
 
223
{
 
224
    JobLocalDoneMsg *m = dynamic_cast<JobLocalDoneMsg*>( _m );
 
225
    if ( !m ) return;
 
226
 
 
227
    JobList::iterator it = m_rememberedJobs.find( m->job_id );
 
228
    if ( it == m_rememberedJobs.end() ) {
 
229
        // we started in between
 
230
        return;
 
231
    }
 
232
 
 
233
    ( *it ).setState( Job::Finished );
 
234
    m_view->update( *it );
 
235
 
 
236
    if ( m_rememberedJobs.size() > 3000 ) { // now remove 1000
 
237
        uint count = 1000;
 
238
 
 
239
        while ( --count )
 
240
            m_rememberedJobs.erase( m_rememberedJobs.begin() );
 
241
    }
 
242
}
 
243
 
 
244
void IcecreamMonitor::handle_stats( Msg *_m )
 
245
{
 
246
    MonStatsMsg *m = dynamic_cast<MonStatsMsg*>( _m );
 
247
    if ( !m ) return;
 
248
 
 
249
    QStringList statmsg = QString( m->statmsg.c_str() ).split( '\n' );
 
250
    HostInfo::StatsMap stats;
 
251
    for ( QStringList::ConstIterator it = statmsg.constBegin(); it != statmsg.constEnd();
 
252
          ++it ) {
 
253
        QString key = *it;
 
254
        key = key.left( key.indexOf( ':' ) );
 
255
        QString value = *it;
 
256
        value = value.mid( value.indexOf( ':' ) + 1 );
 
257
        stats[key] = value;
 
258
    }
 
259
 
 
260
    HostInfo *hostInfo = hostInfoManager()->checkNode( m->hostid, stats );
 
261
 
 
262
    if ( hostInfo->isOffline() ) {
 
263
        m_view->removeNode( m->hostid );
 
264
    } else {
 
265
        m_view->checkNode( m->hostid );
 
266
    }
 
267
}
 
268
 
 
269
void IcecreamMonitor::handle_job_begin( Msg *_m )
 
270
{
 
271
    MonJobBeginMsg *m = dynamic_cast<MonJobBeginMsg*>( _m );
 
272
    if ( !m ) return;
 
273
 
 
274
    JobList::iterator it = m_rememberedJobs.find( m->job_id );
 
275
    if ( it == m_rememberedJobs.end() ) {
 
276
        // we started in between
 
277
        return;
 
278
    }
 
279
 
 
280
    ( *it ).setServer( m->hostid );
 
281
    ( *it ).setStartTime( m->stime );
 
282
    ( *it ).setState( Job::Compiling );
 
283
 
 
284
#if 0
 
285
    qDebug() << "BEGIN: " << (*it).fileName() << " (" << (*it).jobId()
 
286
             << ")" << endl;
 
287
#endif
 
288
 
 
289
    m_view->update( *it );
 
290
}
 
291
 
 
292
void IcecreamMonitor::handle_job_done( Msg *_m )
 
293
{
 
294
    MonJobDoneMsg *m = dynamic_cast<MonJobDoneMsg*>( _m );
 
295
    if ( !m ) return;
 
296
 
 
297
    JobList::iterator it = m_rememberedJobs.find( m->job_id );
 
298
    if ( it == m_rememberedJobs.end() ) {
 
299
        // we started in between
 
300
        return;
 
301
    }
 
302
 
 
303
    ( *it ).exitcode = m->exitcode;
 
304
    if ( m->exitcode ) {
 
305
        ( *it ).setState( Job::Failed );
 
306
    } else {
 
307
        ( *it ).setState( Job::Finished );
 
308
        ( *it ).real_msec = m->real_msec;
 
309
        ( *it ).user_msec = m->user_msec;
 
310
        ( *it ).sys_msec = m->sys_msec;   /* system time used */
 
311
        ( *it ).pfaults = m->pfaults;     /* page faults */
 
312
 
 
313
        ( *it ).in_compressed = m->in_compressed;
 
314
        ( *it ).in_uncompressed = m->in_uncompressed;
 
315
        ( *it ).out_compressed = m->out_compressed;
 
316
        ( *it ).out_uncompressed = m->out_uncompressed;
 
317
    }
 
318
 
 
319
#if 0
 
320
    qDebug() << "DONE: " << (*it).fileName() << " (" << (*it).jobId()
 
321
             << ")" << endl;
 
322
#endif
 
323
 
 
324
    m_view->update( *it );
 
325
}
 
326
 
 
327
void IcecreamMonitor::setCurrentView( StatusView *view, bool rememberJobs )
 
328
{
 
329
    m_view = view;
 
330
 
 
331
    m_view->updateSchedulerState( m_schedulerState );
 
332
 
 
333
    if ( rememberJobs ) {
 
334
        JobList::ConstIterator it = m_rememberedJobs.constBegin();
 
335
        for ( ; it != m_rememberedJobs.constEnd(); ++it )
 
336
            m_view->update( *it );
 
337
    }
 
338
}
 
339
 
 
340
void IcecreamMonitor::setCurrentNet( const QByteArray &netName )
 
341
{
 
342
    m_current_netname = netName;
 
343
}
 
344
 
 
345
void IcecreamMonitor::setSchedulerState( bool online )
 
346
{
 
347
    if (m_schedulerState == online)
 
348
        return;
 
349
    m_schedulerState = online;
 
350
    emit schedulerStateChanged( online );
 
351
    m_view->updateSchedulerState( online );
 
352
}
 
353
 
 
354
#include "icecreammonitor.moc"