Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArSystemStatus.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ariaUtil.h"
00030 #include "ArSystemStatus.h"
00031 #include <stdio.h>
00032 
00033 double ArSystemStatus::ourCPU = -1.0;
00034 unsigned long ArSystemStatus::ourUptime = 0;
00035 unsigned long ArSystemStatus::ourLastCPUTime = 0;
00036 ArTime ArSystemStatus::ourLastCPURefreshTime;
00037 ArGlobalRetFunctor<double> ArSystemStatus::ourGetCPUPercentCallback(&ArSystemStatus::getCPUPercent);
00038 ArGlobalRetFunctor<double> ArSystemStatus::ourGetUptimeHoursCallback(&ArSystemStatus::getUptimeHours);
00039 int ArSystemStatus::ourLinkQuality = -1;
00040 int ArSystemStatus::ourLinkSignal = -1;
00041 int ArSystemStatus::ourLinkNoise = -1;
00042 int ArSystemStatus::ourDiscardedTotal = -1;
00043 int ArSystemStatus::ourDiscardedConflict = -1;
00044 int ArSystemStatus::ourDiscardedDecrypt = -1;
00045 ArMutex ArSystemStatus::ourCPUMutex;
00046 ArMutex ArSystemStatus::ourWirelessMutex;
00047 ArGlobalRetFunctor<int> ArSystemStatus::ourGetWirelessLinkQualityCallback(&ArSystemStatus::getWirelessLinkQuality);
00048 ArGlobalRetFunctor<int> ArSystemStatus::ourGetWirelessLinkNoiseCallback(&ArSystemStatus::getWirelessLinkNoise);
00049 ArGlobalRetFunctor<int> ArSystemStatus::ourGetWirelessLinkSignalCallback(&ArSystemStatus::getWirelessLinkSignal);
00050 ArSystemStatusRefreshThread* ArSystemStatus::ourPeriodicUpdateThread = 0;
00051 bool ArSystemStatus::ourShouldRefreshWireless = true;
00052 bool ArSystemStatus::ourShouldRefreshCPU = true;
00053 
00054 
00055 class ArScopedLock {
00056 private:
00057   ArMutex& mtx;
00058 public:
00059   ArScopedLock(ArMutex& m) : mtx(m) {
00060     mtx.lock();
00061   }
00062   ~ArScopedLock() {
00063     mtx.unlock();
00064   }
00065 };
00066 
00067 
00068 void ArSystemStatus::refreshCPU()
00069 {
00070 #ifndef WIN32
00071   if(ourPeriodicUpdateThread && !ourShouldRefreshCPU) return;
00072   unsigned long interval = ourLastCPURefreshTime.mSecSince();
00073   FILE* statfp = fopen("/proc/stat", "r");
00074   FILE* uptimefp = fopen("/proc/uptime", "r");
00075   if(!statfp) {
00076     ArLog::log(ArLog::Terse, "ArSystemStatus: Error: Failed to open /proc/stat!");
00077   }
00078   if(!uptimefp) {
00079     ArLog::log(ArLog::Terse, "ArSystemStatus: Error: Failed to open /proc/uptime!");
00080   }
00081   if(!statfp || !uptimefp)
00082   {
00083     ourCPU = -1.0;
00084     ourLastCPUTime = ourUptime = 0;
00085     ourShouldRefreshCPU = false;
00086     return;
00087   }
00088   double uptime = 0, idle_uptime = 0;
00089   //char line[512];
00090   //fgets(line,  512, uptimefp);
00091   //printf("read uptime file: %s\n", line);
00092   fscanf(uptimefp, "%lf %lf", &uptime, &idle_uptime);
00093   fclose(uptimefp);
00094   unsigned long user, nice, sys, idle, total;
00095   char tag[32];
00096   fscanf(statfp, "%s %lu %lu %lu %lu", &tag, &user, &nice, &sys, &idle);
00097   fclose(statfp);
00098   ourUptime = (unsigned long)uptime;
00099   total = user+nice+sys; // total non-idle cpu time in 100ths of a sec
00100   if(ourLastCPUTime == 0 || interval == 0) 
00101   {
00102     // no time has past since last refresh
00103     ourLastCPUTime = total;
00104     ourShouldRefreshCPU = false;
00105     return;
00106   }
00107   ourCPU = (double)(total - ourLastCPUTime) / ((double)interval/10.0); // convert 'interval' to 1/100 sec units
00108   ourLastCPUTime = total;
00109   ourLastCPURefreshTime.setToNow();
00110   ourShouldRefreshCPU = false;
00111 #endif // WIN32
00112 }
00113 
00114 
00115 
00117 class ArSystemStatusRefreshThread : public virtual ArASyncTask {
00118 public:
00119   ArSystemStatusRefreshThread(int refreshFrequency) :
00120     myRefreshFrequency(refreshFrequency)
00121   {
00122   }
00123   void runAsync() { create(false); }
00124   void setRefreshFreq(int freq) { myRefreshFrequency = freq; }
00125 private:
00126   int myRefreshFrequency;
00127   virtual void* runThread(void* arg)
00128   {
00129     while(getRunning())
00130     {
00131       ArSystemStatus::invalidate();
00132       ArUtil::sleep(myRefreshFrequency);
00133     }
00134     return NULL;
00135   }
00136 };
00140 AREXPORT void ArSystemStatus::startPeriodicUpdate(int refreshFrequency)
00141 {
00142   if(ourPeriodicUpdateThread) {
00143     printf("***** Setting refresh freq to %d ms.\n", refreshFrequency);
00144     ourPeriodicUpdateThread->setRefreshFreq(refreshFrequency);
00145     return;
00146   }
00147   ourPeriodicUpdateThread = new ArSystemStatusRefreshThread(refreshFrequency);
00148   ourPeriodicUpdateThread->runAsync();
00149 }
00150 
00151 AREXPORT void ArSystemStatus::stopPeriodicUpdate()
00152 {
00153   if(!ourPeriodicUpdateThread) return;
00154   ourPeriodicUpdateThread->stopRunning();
00155   delete ourPeriodicUpdateThread;
00156   ourPeriodicUpdateThread = 0;
00157 }
00158 
00159 
00160 
00161 AREXPORT double ArSystemStatus::getCPU() {
00162   ArScopedLock lock(ourCPUMutex);
00163   refreshCPU();
00164   return ourCPU;
00165 }
00166 
00167 AREXPORT double ArSystemStatus::getCPUPercent() {
00168   ArScopedLock lock(ourCPUMutex);
00169   refreshCPU();
00170   if(ourCPU < 0)
00171   {
00172     return ourCPU;  // invalid value indicator
00173   }
00174   return ourCPU * 100.0;
00175 }
00176 
00177 // Get CPU percentage in a string
00178 AREXPORT std::string ArSystemStatus::getCPUPercentAsString() {
00179   ArScopedLock lock(ourCPUMutex);
00180   refreshCPU();
00181   if(ourCPU < 0)
00182   {
00183     return std::string("n/a");
00184   }
00185   char tmp[32];
00186   snprintf(tmp, 31, "%.2f", getCPUPercent());
00187   return std::string(tmp);
00188 }
00189 
00190 // Get total system uptime (seconds)
00191 AREXPORT unsigned long ArSystemStatus::getUptime() {
00192   ArScopedLock lock(ourCPUMutex);
00193   refreshCPU();
00194   return ourUptime;
00195 }
00196 
00197 // Get total system uptime (hours)
00198 AREXPORT double ArSystemStatus::getUptimeHours() {
00199   ArScopedLock lock(ourCPUMutex);
00200   refreshCPU();
00201   return ourUptime / 3600.0;
00202 }
00203 
00204 // Get total system uptime in a string (hours)
00205 AREXPORT std::string ArSystemStatus::getUptimeHoursAsString() {
00206   ArScopedLock lock(ourCPUMutex);
00207   refreshCPU();
00208   char tmp[32];
00209   snprintf(tmp, 31, "%.2f", getUptimeHours());
00210   return std::string(tmp);
00211 }
00212 
00213 // return Pointer to a functor which can be used to retrieve the current CPU percentage
00214 AREXPORT ArRetFunctor<double>* ArSystemStatus::getCPUPercentFunctor() {
00215   return &ourGetCPUPercentCallback;
00216 }
00217 
00218 // return Pointer to a functor which can be used to retrieve the current uptime (hours)
00219 AREXPORT ArRetFunctor<double>* ArSystemStatus::getUptimeHoursFunctor() {
00220   return &ourGetUptimeHoursCallback;
00221 }
00222 
00223 AREXPORT ArRetFunctor<int>* ArSystemStatus::getWirelessLinkQualityFunctor() {
00224   return &ourGetWirelessLinkQualityCallback;
00225 }
00226 AREXPORT ArRetFunctor<int>* ArSystemStatus::getWirelessLinkNoiseFunctor() {
00227   return &ourGetWirelessLinkNoiseCallback;
00228 }
00229 AREXPORT ArRetFunctor<int>* ArSystemStatus::getWirelessLinkSignalFunctor() {
00230   return &ourGetWirelessLinkSignalCallback;
00231 }
00232 
00233 // Get wireless stats from /proc/net/wireless:
00234 
00235 void ArSystemStatus::refreshWireless()
00236 {
00237 #ifndef WIN32
00238   if(ourPeriodicUpdateThread && !ourShouldRefreshWireless) return;
00239   FILE* fp = fopen("/proc/net/wireless", "r");
00240   if(!fp)
00241   {
00242     ArLog::log(ArLog::Terse, "ArSystemStatus: Error: Failed to open /proc/net/wireless!");
00243     ourShouldRefreshWireless = false;
00244     return;
00245   }
00246 
00247   // first two lines are header info
00248   char line[256];
00249   if(! (fgets(line, 256, fp) && fgets(line, 256, fp)) ) 
00250   {
00251     fclose(fp); 
00252     ourLinkQuality = ourLinkSignal = ourLinkNoise =
00253       ourDiscardedTotal = ourDiscardedDecrypt = -1;
00254     ourShouldRefreshWireless = false;
00255     return;
00256   }
00257 
00258 
00259   // next line is info for first device
00260   char id[32];
00261   unsigned int stat;
00262   int disc_frag, disc_retry, disc_misc, missed;
00263   disc_frag = disc_retry = disc_misc = missed = 0;
00264   int r = fscanf(fp, "%31s %x %d. %d. %d. %d %d %d %d %d %d", 
00265       id, &stat,
00266       &ourLinkQuality, &ourLinkSignal, &ourLinkNoise,
00267       &ourDiscardedConflict, &ourDiscardedDecrypt, 
00268       &disc_frag, &disc_retry, &disc_misc, &missed) ;
00269   fclose(fp);
00270   if(r < 11)
00271     ArLog::log(ArLog::Verbose, "ArSystemStatus: Warning: Failed to parse /proc/net/wireless (only %d out of 11 values parsed).", r);
00272   if(ourDiscardedConflict == -1 || ourDiscardedDecrypt == -1)
00273     ourDiscardedTotal = -1;
00274   else
00275     ourDiscardedTotal = ourDiscardedConflict + ourDiscardedDecrypt 
00276       + disc_frag + disc_retry + disc_misc;
00277   ourShouldRefreshWireless = false;
00278 #endif // WIN32
00279 }
00280 
00281 
00282 AREXPORT int ArSystemStatus::getWirelessLinkQuality() {
00283   ArScopedLock lock(ourWirelessMutex);
00284   refreshWireless();
00285   return ourLinkQuality; 
00286 }
00287 
00288 AREXPORT int ArSystemStatus::getWirelessLinkSignal() {
00289   ArScopedLock lock(ourWirelessMutex);
00290   refreshWireless();
00291   return ourLinkSignal; 
00292 }
00293 
00294 AREXPORT int ArSystemStatus::getWirelessLinkNoise() {
00295   ArScopedLock lock(ourWirelessMutex);
00296   refreshWireless();
00297   return ourLinkNoise; 
00298 }
00299 
00300 AREXPORT int ArSystemStatus::getWirelessDiscardedPackets() {
00301   ArScopedLock lock(ourWirelessMutex);
00302   refreshWireless();
00303   return ourDiscardedTotal; 
00304 }
00305 
00306 AREXPORT int ArSystemStatus::getWirelessDiscardedPacketsBecauseNetConflict() {
00307   ArScopedLock lock(ourWirelessMutex);
00308   refreshWireless();
00309   return ourDiscardedConflict; 
00310 }
00311 
00312 
00313 
00314 AREXPORT void ArSystemStatus::invalidate()
00315 {
00316   ArScopedLock lockc(ourCPUMutex);
00317   ArScopedLock lockw(ourWirelessMutex);
00318   ourShouldRefreshCPU = ourShouldRefreshWireless = true;
00319 }

Generated on Tue Feb 20 10:51:41 2007 for Aria by  doxygen 1.4.0