alarmserver.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qdir.h>
00022 #include <qfile.h>
00023 #include <qmessagebox.h>
00024 #include <qtextstream.h>
00025
00026
00027 #include <qpe/qpeapplication.h>
00028 #include "global.h"
00029 #include "resource.h"
00030
00031 #include <qpe/qcopenvelope_qws.h>
00032 #include "alarmserver.h"
00033 #include <qpe/timeconversion.h>
00034
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040
00041
00042 #undef USE_ATD // not used anymore -- we run opie-alarm on suspend/resume
00043
00044
00045 struct timerEventItem
00046 {
00047 time_t UTCtime;
00048 QCString channel, message;
00049 int data;
00050 bool operator==( const timerEventItem &right ) const
00051 {
00052 return ( UTCtime == right.UTCtime
00053 && channel == right.channel
00054 && message == right.message
00055 && data == right.data );
00056 }
00057 };
00058
00059 class TimerReceiverObject : public QObject
00060 {
00061 public:
00062 TimerReceiverObject()
00063 { }
00064 ~TimerReceiverObject()
00065 { }
00066 void resetTimer();
00067 void setTimerEventItem();
00068 void deleteTimer();
00069 protected:
00070 void timerEvent( QTimerEvent *te );
00071
00072 #ifdef USE_ATD
00073 private:
00074 QString atfilename;
00075 #endif
00076 };
00077
00078 TimerReceiverObject *timerEventReceiver = NULL;
00079 QList<timerEventItem> timerEventList;
00080 timerEventItem *nearestTimerEvent = NULL;
00081
00082
00083
00084 void setNearestTimerEvent()
00085 {
00086 nearestTimerEvent = NULL;
00087 QListIterator<timerEventItem> it( timerEventList );
00088 if ( *it )
00089 nearestTimerEvent = *it;
00090 for ( ; *it; ++it )
00091 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime )
00092 nearestTimerEvent = *it;
00093 if (nearestTimerEvent)
00094 timerEventReceiver->resetTimer();
00095 else
00096 timerEventReceiver->deleteTimer();
00097 }
00098
00099
00100
00101
00102
00103 static void saveState()
00104 {
00105 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
00106 if ( timerEventList.isEmpty() ) {
00107 unlink( savefilename );
00108 return ;
00109 }
00110
00111 QFile savefile(savefilename + ".new");
00112 if ( savefile.open(IO_WriteOnly) ) {
00113 QDataStream ds( &savefile );
00114
00115
00116
00117 QListIterator<timerEventItem> it( timerEventList );
00118 for ( ; *it; ++it ) {
00119 ds << it.current()->UTCtime;
00120 ds << it.current()->channel;
00121 ds << it.current()->message;
00122 ds << it.current()->data;
00123 }
00124
00125
00126 savefile.close();
00127 unlink( savefilename );
00128 QDir d;
00129 d.rename(savefilename + ".new", savefilename);
00130
00131 }
00132 }
00133
00137 void AlarmServer::initialize()
00138 {
00139
00140
00141 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
00142
00143 QFile savefile(savefilename);
00144 if ( savefile.open(IO_ReadOnly) ) {
00145 QDataStream ds( &savefile );
00146 while ( !ds.atEnd() ) {
00147 timerEventItem *newTimerEventItem = new timerEventItem;
00148 ds >> newTimerEventItem->UTCtime;
00149 ds >> newTimerEventItem->channel;
00150 ds >> newTimerEventItem->message;
00151 ds >> newTimerEventItem->data;
00152 timerEventList.append( newTimerEventItem );
00153 }
00154 savefile.close();
00155 if (!timerEventReceiver)
00156 timerEventReceiver = new TimerReceiverObject;
00157 setNearestTimerEvent();
00158 }
00159 }
00160
00161
00162 #ifdef USE_ATD
00163
00164 static const char* atdir = "/var/spool/at/";
00165
00166 static bool triggerAtd( bool writeHWClock = FALSE )
00167 {
00168 QFile trigger(QString(atdir) + "trigger");
00169 if ( trigger.open(IO_WriteOnly | IO_Raw) ) {
00170 if ( trigger.writeBlock("\n", 2) != 2 ) {
00171 QMessageBox::critical( 0, QObject::tr( "Out of Space" ),
00172 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) );
00173 trigger.close();
00174 QFile::remove
00175 ( trigger.name() );
00176 return FALSE;
00177 }
00178 return TRUE;
00179 }
00180 return FALSE;
00181 }
00182
00183 #else
00184
00185 static bool writeResumeAt ( time_t wakeup )
00186 {
00187 FILE *fp = ::fopen ( "/var/run/resumeat", "w" );
00188
00189 if ( fp ) {
00190 ::fprintf ( fp, "%d\n", (int) wakeup );
00191 ::fclose ( fp );
00192 }
00193 else
00194 qWarning ( "Failed to write wakeup time to /var/run/resumeat" );
00195
00196 return ( fp );
00197 }
00198
00199 #endif
00200
00201 void TimerReceiverObject::deleteTimer()
00202 {
00203 #ifdef USE_ATD
00204 if ( !atfilename.isEmpty() ) {
00205 unlink( atfilename );
00206 atfilename = QString::null;
00207 triggerAtd( FALSE );
00208 }
00209 #else
00210 writeResumeAt ( 0 );
00211 #endif
00212 }
00213
00214 void TimerReceiverObject::resetTimer()
00215 {
00216 const int maxsecs = 2147000;
00217 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime);
00218 QDateTime now = QDateTime::currentDateTime();
00219 if ( nearest < now )
00220 nearest = now;
00221 int secs = TimeConversion::secsTo( now, nearest );
00222 if ( secs > maxsecs ) {
00223
00224 secs = maxsecs;
00225 }
00226
00227
00228
00229
00230 int at_secs = TimeConversion::toUTC(nearest);
00231
00232
00233 #ifdef USE_ATD
00234
00235 QString fn = atdir + QString::number(at_secs) + "."
00236 + QString::number(getpid());
00237 if ( fn != atfilename ) {
00238 QFile atfile(fn + ".new");
00239 if ( atfile.open(IO_WriteOnly | IO_Raw) ) {
00240 int total_written;
00241
00242
00243 QString cmd = "#!/bin/sh\nrm " + fn;
00244 total_written = atfile.writeBlock(cmd.latin1(), cmd.length());
00245 if ( total_written != int(cmd.length()) ) {
00246 QMessageBox::critical( 0, tr("Out of Space"),
00247 tr("Unable to schedule alarm.\n"
00248 "Please free up space and try again") );
00249 atfile.close();
00250 QFile::remove
00251 ( atfile.name() );
00252 return ;
00253 }
00254 atfile.close();
00255 unlink( atfilename );
00256 QDir d;
00257 d.rename(fn + ".new", fn);
00258 chmod(fn.latin1(), 0755);
00259 atfilename = fn;
00260 triggerAtd( FALSE );
00261 }
00262 else {
00263 qWarning("Cannot open atd file %s", fn.latin1());
00264 }
00265 }
00266 #else
00267 writeResumeAt ( at_secs );
00268
00269 #endif
00270
00271
00272
00273
00274 qDebug("AlarmServer waiting %d seconds", secs);
00275 startTimer( 1000 * secs + 500 );
00276 }
00277
00278 void TimerReceiverObject::timerEvent( QTimerEvent * )
00279 {
00280 bool needSave = FALSE;
00281 killTimers();
00282 if (nearestTimerEvent) {
00283 if ( nearestTimerEvent->UTCtime
00284 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) {
00285 #ifndef QT_NO_COP
00286 QCopEnvelope e( nearestTimerEvent->channel,
00287 nearestTimerEvent->message );
00288 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime )
00289 << nearestTimerEvent->data;
00290 #endif
00291
00292 timerEventList.remove( nearestTimerEvent );
00293 needSave = TRUE;
00294 }
00295 setNearestTimerEvent();
00296 }
00297 else {
00298 resetTimer();
00299 }
00300 if ( needSave )
00301 saveState();
00302 }
00303
00394 void AlarmServer::addAlarm ( QDateTime when, const QCString& channel,
00395 const QCString& message, int data)
00396 {
00397 if ( qApp->type() == QApplication::GuiServer ) {
00398 bool needSave = FALSE;
00399
00400
00401 if (!timerEventReceiver)
00402 timerEventReceiver = new TimerReceiverObject;
00403
00404 timerEventItem *newTimerEventItem = new timerEventItem;
00405 newTimerEventItem->UTCtime = TimeConversion::toUTC( when );
00406 newTimerEventItem->channel = channel;
00407 newTimerEventItem->message = message;
00408 newTimerEventItem->data = data;
00409
00410 QListIterator<timerEventItem> it( timerEventList );
00411 for ( ; *it; ++it )
00412 if ( *(*it) == *newTimerEventItem )
00413 return ;
00414
00415 timerEventList.append( newTimerEventItem );
00416 needSave = TRUE;
00417
00418 if ( nearestTimerEvent ) {
00419 if (newTimerEventItem->UTCtime < nearestTimerEvent->UTCtime) {
00420 nearestTimerEvent = newTimerEventItem;
00421 timerEventReceiver->killTimers();
00422 timerEventReceiver->resetTimer();
00423 }
00424 }
00425 else {
00426 nearestTimerEvent = newTimerEventItem;
00427 timerEventReceiver->resetTimer();
00428 }
00429 if ( needSave )
00430 saveState();
00431 }
00432 else {
00433 #ifndef QT_NO_COP
00434 QCopEnvelope e( "QPE/System", "addAlarm(QDateTime,QCString,QCString,int)" );
00435 e << when << channel << message << data;
00436 #endif
00437
00438 }
00439 }
00440
00454 void AlarmServer::deleteAlarm (QDateTime when, const QCString& channel, const QCString& message, int data)
00455 {
00456 if ( qApp->type() == QApplication::GuiServer) {
00457 bool needSave = FALSE;
00458 if ( timerEventReceiver != NULL ) {
00459 timerEventReceiver->killTimers();
00460
00461
00462 QListIterator<timerEventItem> it( timerEventList );
00463 time_t deleteTime = TimeConversion::toUTC( when );
00464 for ( ; *it; ++it ) {
00465
00466 if ( ( (*it)->UTCtime == deleteTime || when.isNull() )
00467 && ( channel.isNull() || (*it)->channel == channel )
00468 && ( message.isNull() || (*it)->message == message )
00469 && ( data == -1 || (*it)->data == data ) ) {
00470
00471 if ( (*it) == nearestTimerEvent ) {
00472 timerEventList.remove(*it);
00473 setNearestTimerEvent();
00474 }
00475 else {
00476 timerEventList.remove(*it);
00477 }
00478 needSave = TRUE;
00479 }
00480 }
00481 if ( nearestTimerEvent )
00482 timerEventReceiver->resetTimer();
00483 }
00484 if ( needSave )
00485 saveState();
00486 }
00487 else {
00488 #ifndef QT_NO_COP
00489 QCopEnvelope e( "QPE/System", "deleteAlarm(QDateTime,QCString,QCString,int)" );
00490 e << when << channel << message << data;
00491 #endif
00492
00493 }
00494 }
00495
00502 void Global::writeHWClock()
00503 {
00504 #ifdef USE_ATD
00505 if ( !triggerAtd( TRUE ) ) {
00506
00507 system("/sbin/hwclock --systohc");
00508 }
00509 #else
00510
00511 #endif
00512 }
This file is part of the documentation for OPIE Version 1.5.5.