~ubuntu-branches/ubuntu/natty/kdebase-workspace/natty-proposed

« back to all changes in this revision

Viewing changes to ksysguard/gui/ksgrd/SensorAgent.cc

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2011-04-03 16:54:55 UTC
  • mfrom: (1.1.55 upstream)
  • Revision ID: james.westby@ubuntu.com-20110403165455-8tnwxt82p21p15hh
Tags: 4:4.6.2a-0ubuntu1
* New upstream release
  - Update kde-sc-dev-latest version
  - Update kdebase-workspace-wallpapers.install,
    kde-window-manager.install and not-installed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    KSysGuard, the KDE System Guard
3
 
   
4
 
    Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
5
 
    
6
 
    This program is free software; you can redistribute it and/or
7
 
    modify it under the terms of the GNU General Public
8
 
    License version 2 or at your option version 3 as published by
9
 
    the Free Software Foundation.
10
 
 
11
 
    This program is distributed in the hope that it will be useful,
12
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
    GNU General Public License for more details.
15
 
 
16
 
    You should have received a copy of the GNU General Public License
17
 
    along with this program; if not, write to the Free Software
18
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
 
 
20
 
*/
21
 
 
22
 
//#include <stdlib.h>
23
 
 
24
 
#include <kdebug.h>
25
 
#include <klocale.h>
26
 
 
27
 
#include "SensorClient.h"
28
 
#include "SensorManager.h"
29
 
 
30
 
#include "SensorAgent.h"
31
 
 
32
 
/**
33
 
  This can be used to debug communication problems with the daemon.
34
 
  Should be set to 0 in any production version.
35
 
*/
36
 
#define SA_TRACE 0
37
 
 
38
 
using namespace KSGRD;
39
 
 
40
 
SensorAgent::SensorAgent( SensorManager *sm ) : QObject(sm)
41
 
{
42
 
  mSensorManager = sm;
43
 
  mDaemonOnLine = false;
44
 
}
45
 
 
46
 
SensorAgent::~SensorAgent()
47
 
{
48
 
  for(int i = mInputFIFO.size()-1; i >= 0; --i)
49
 
    delete mInputFIFO.takeAt(i);
50
 
  for(int i = mProcessingFIFO.size()-1; i >= 0; --i)
51
 
    delete mProcessingFIFO.takeAt(i);
52
 
}
53
 
 
54
 
void SensorAgent::sendRequest( const QString &req, SensorClient *client, int id )
55
 
{
56
 
  SensorRequest *sensorreq = 0;
57
 
  for(int i =0; i < mInputFIFO.size(); ++i) {
58
 
    sensorreq = mInputFIFO.at(i);
59
 
    if(id == sensorreq->id() && client == sensorreq->client() && req == sensorreq->request()) {
60
 
      executeCommand();
61
 
      return; //don't bother to resend the same request if we already have it in our queue to send
62
 
    }
63
 
  }
64
 
  for(int i =0; i < mProcessingFIFO.size(); ++i) {
65
 
    sensorreq = mProcessingFIFO.at(i);
66
 
    if(id == sensorreq->id() && client == sensorreq->client() && req == sensorreq->request())
67
 
      return; //don't bother to resend the same request if we have already sent the request to client and just waiting for an answer
68
 
  }
69
 
 
70
 
  /* The request is registered with the FIFO so that the answer can be
71
 
   * routed back to the requesting client. */
72
 
  mInputFIFO.enqueue( new SensorRequest( req, client, id ) );
73
 
 
74
 
#if SA_TRACE
75
 
  kDebug(1215) << "-> " << req << "(" << mInputFIFO.count() << "/"
76
 
                << mProcessingFIFO.count() << ")" << endl;
77
 
#endif
78
 
  executeCommand();
79
 
}
80
 
 
81
 
void SensorAgent::processAnswer( const char *buf, int buflen )
82
 
{
83
 
  //It is possible for an answer/error message  to be split across multiple processAnswer calls.  This makes our life more difficult
84
 
  //We have to keep track of the state we are in.  Any characters that we have not parsed yet we put in
85
 
  //mLeftOverBuffer
86
 
  QByteArray buffer = QByteArray::fromRawData(buf, buflen);
87
 
  if(!mLeftOverBuffer.isEmpty()) {
88
 
        buffer = mLeftOverBuffer + buffer; //If we have data left over from a previous processAnswer, then we have to prepend this on
89
 
        mLeftOverBuffer.clear();
90
 
  }
91
 
  
92
 
#if SA_TRACE
93
 
  kDebug(1215) << "<- " << QString::fromUtf8(buffer, buffer.size());
94
 
#endif
95
 
  int startOfAnswer = 0;  //This can become >= buffer.size(), so check before using!
96
 
  for ( int i = 0; i < buffer.size(); ++i ) {
97
 
    if ( buffer.at(i) == '\033' ) {  // 033 in octal is the escape character.  The signifies the start of an error
98
 
      int startOfError = i;
99
 
      bool found = false;
100
 
      while(++i < buffer.size()) {
101
 
        if(buffer.at(i) == '\033') {
102
 
          QString error = QString::fromUtf8(buffer.constData() + startOfError+1, i-startOfError-1);
103
 
          if ( error.startsWith(QLatin1String("RECONFIGURE")) ) {
104
 
            emit reconfigure( this );
105
 
          }
106
 
          else {
107
 
            /* We just received the end of an error message, so we
108
 
             * can display it. */
109
 
            SensorMgr->notify( i18nc( "%1 is a host name", "Message from %1:\n%2",
110
 
                               mHostName ,
111
 
                               error ) );
112
 
          }
113
 
          found = true;
114
 
          break;
115
 
        }
116
 
      }
117
 
      if(found) {
118
 
        buffer.remove(startOfError, i-startOfError+1);
119
 
        i = startOfAnswer - 1;
120
 
        continue;
121
 
      } else {
122
 
        //We have not found the end of the escape string.  Try checking in the next packet
123
 
        mLeftOverBuffer = QByteArray(buffer.constData()+startOfAnswer, buffer.size()-startOfAnswer);
124
 
        return;
125
 
      }
126
 
    }
127
 
 
128
 
    //The spec was supposed to be that it returned "\nksysguardd> " but some seem to forget the space, so we have to compensate.  Sigh 
129
 
    if( (i==startOfAnswer && buffer.size() -i >= (signed)(sizeof("ksysguardd>"  ))-1 && qstrncmp(buffer.constData()+i, "ksysguardd>",   sizeof("ksysguardd>"  )-1) == 0) ||
130
 
        (buffer.size() -i >= (signed)(sizeof("\nksysguardd>"))-1 && qstrncmp(buffer.constData()+i, "\nksysguardd>", sizeof("\nksysguardd>")-1) == 0)) {
131
 
 
132
 
        QByteArray answer(buffer.constData()+startOfAnswer, i-startOfAnswer);
133
 
        if(!answer.isEmpty())
134
 
                mAnswerBuffer << answer;
135
 
#if SA_TRACE
136
 
        kDebug(1215) << "<= " << mAnswerBuffer
137
 
                << "(" << mInputFIFO.count() << "/"
138
 
                << mProcessingFIFO.count() << ")" << endl;
139
 
#endif
140
 
        if(buffer.at(i) == '\n')
141
 
                i++;
142
 
        i += sizeof("ksysguardd>") -2;  //Move i on to the next answer (if any). -2 because sizeof adds one for \0  and the for loop will increment by 1 also
143
 
        if(i+1 < buffer.size() && buffer.at(i+1) == ' ') i++;
144
 
        startOfAnswer = i+1;
145
 
 
146
 
        //We have found the end of one reply
147
 
        if ( !mDaemonOnLine ) {
148
 
                /* First '\nksysguardd> ' signals that the daemon is
149
 
                 * ready to serve requests now. */
150
 
                mDaemonOnLine = true;
151
 
#if SA_TRACE
152
 
                kDebug(1215) << "Daemon now online!";
153
 
#endif
154
 
                mAnswerBuffer.clear();
155
 
                continue;
156
 
        }
157
 
 
158
 
        //Deal with the answer we have now read in
159
 
 
160
 
        // remove pending request from FIFO
161
 
        if ( mProcessingFIFO.isEmpty() ) {
162
 
                kDebug(1215)    << "ERROR: Received answer but have no pending "
163
 
                                << "request!" << endl;
164
 
                mAnswerBuffer.clear();
165
 
                continue;
166
 
        }
167
 
                
168
 
        SensorRequest *req = mProcessingFIFO.dequeue();
169
 
        // we are now responsible for the memory of req - we must delete it!
170
 
        if ( !req->client() ) {
171
 
                /* The client has disappeared before receiving the answer
172
 
                 * to his request. */
173
 
                delete req;
174
 
                mAnswerBuffer.clear();
175
 
                continue;
176
 
        }
177
 
                
178
 
        if(!mAnswerBuffer.isEmpty() && mAnswerBuffer[0] == "UNKNOWN COMMAND") {
179
 
                /* Notify client that the sensor seems to be no longer available. */
180
 
        kDebug(1215) << "Received UNKNOWN COMMAND for: " << req->request(); 
181
 
                req->client()->sensorLost( req->id() );
182
 
        } else {
183
 
                // Notify client of newly arrived answer.
184
 
                req->client()->answerReceived( req->id(), mAnswerBuffer );
185
 
        }
186
 
        delete req;
187
 
        mAnswerBuffer.clear();
188
 
    } else if(buffer.at(i) == '\n'){
189
 
        mAnswerBuffer << QByteArray(buffer.constData()+startOfAnswer, i-startOfAnswer);
190
 
        startOfAnswer = i+1;
191
 
    }
192
 
  }
193
 
 
194
 
  mLeftOverBuffer += QByteArray(buffer.constData()+startOfAnswer, buffer.size()-startOfAnswer);
195
 
  executeCommand();
196
 
}
197
 
 
198
 
void SensorAgent::executeCommand()
199
 
{
200
 
  /* This function is called whenever there is a chance that we have a
201
 
   * command to pass to the daemon. But the command may only be sent
202
 
   * if the daemon is online and there is no other command currently
203
 
   * being sent. */
204
 
  if ( mDaemonOnLine && !mInputFIFO.isEmpty() ) {
205
 
    SensorRequest *req = mInputFIFO.dequeue();
206
 
 
207
 
#if SA_TRACE
208
 
    kDebug(1215) << ">> " << req->request().toAscii() << "(" << mInputFIFO.count()
209
 
                  << "/" << mProcessingFIFO.count() << ")" << endl;
210
 
#endif
211
 
    // send request to daemon
212
 
    QString cmdWithNL = req->request() + '\n';
213
 
    if ( !writeMsg( cmdWithNL.toLatin1(), cmdWithNL.length() ) )
214
 
      kDebug(1215) << "SensorAgent::writeMsg() failed";
215
 
 
216
 
    // add request to processing FIFO.
217
 
    // Note that this means that mProcessingFIFO is now responsible for managing the memory for it.
218
 
    mProcessingFIFO.enqueue( req );
219
 
  }
220
 
}
221
 
 
222
 
void SensorAgent::disconnectClient( SensorClient *client )
223
 
{
224
 
  for (int i = 0; i < mInputFIFO.size(); ++i)
225
 
    if ( mInputFIFO[i]->client() == client )
226
 
      mInputFIFO[i]->setClient(0);
227
 
  for (int i = 0; i < mProcessingFIFO.size(); ++i)
228
 
    if ( mProcessingFIFO[i]->client() == client )
229
 
      mProcessingFIFO[i]->setClient( 0 );
230
 
  
231
 
}
232
 
 
233
 
SensorManager *SensorAgent::sensorManager()
234
 
{
235
 
  return mSensorManager;
236
 
}
237
 
 
238
 
void SensorAgent::setDaemonOnLine( bool value )
239
 
{
240
 
  mDaemonOnLine = value;
241
 
}
242
 
 
243
 
bool SensorAgent::daemonOnLine() const
244
 
{
245
 
  return mDaemonOnLine;
246
 
}
247
 
 
248
 
void SensorAgent::setHostName( const QString &hostName )
249
 
{
250
 
  mHostName = hostName;
251
 
}
252
 
 
253
 
QString SensorAgent::hostName() const
254
 
{
255
 
  return mHostName;
256
 
}
257
 
 
258
 
QString SensorAgent::reasonForOffline() const
259
 
{
260
 
  return mReasonForOffline;
261
 
}
262
 
 
263
 
void SensorAgent::setReasonForOffline(const QString &reasonForOffline)
264
 
{
265
 
  mReasonForOffline = reasonForOffline;
266
 
}
267
 
 
268
 
SensorRequest::SensorRequest( const QString &request, SensorClient *client, int id )
269
 
  : mRequest( request ), mClient( client ), mId( id )
270
 
{
271
 
}
272
 
 
273
 
SensorRequest::~SensorRequest()
274
 
{
275
 
}
276
 
 
277
 
void SensorRequest::setRequest( const QString &request )
278
 
{
279
 
  mRequest = request;
280
 
}
281
 
 
282
 
QString SensorRequest::request() const
283
 
{
284
 
  return mRequest;
285
 
}
286
 
 
287
 
void SensorRequest::setClient( SensorClient *client )
288
 
{
289
 
  mClient = client;
290
 
}
291
 
 
292
 
SensorClient *SensorRequest::client()
293
 
{
294
 
  return mClient;
295
 
}
296
 
 
297
 
void SensorRequest::setId( int id )
298
 
{
299
 
  mId = id;
300
 
}
301
 
 
302
 
int SensorRequest::id()
303
 
{
304
 
  return mId;
305
 
}
306
 
 
307
 
#include "SensorAgent.moc"