00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00090
00091
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;
00100 if(ourLastCPUTime == 0 || interval == 0)
00101 {
00102
00103 ourLastCPUTime = total;
00104 ourShouldRefreshCPU = false;
00105 return;
00106 }
00107 ourCPU = (double)(total - ourLastCPUTime) / ((double)interval/10.0);
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;
00173 }
00174 return ourCPU * 100.0;
00175 }
00176
00177
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
00191 AREXPORT unsigned long ArSystemStatus::getUptime() {
00192 ArScopedLock lock(ourCPUMutex);
00193 refreshCPU();
00194 return ourUptime;
00195 }
00196
00197
00198 AREXPORT double ArSystemStatus::getUptimeHours() {
00199 ArScopedLock lock(ourCPUMutex);
00200 refreshCPU();
00201 return ourUptime / 3600.0;
00202 }
00203
00204
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
00214 AREXPORT ArRetFunctor<double>* ArSystemStatus::getCPUPercentFunctor() {
00215 return &ourGetCPUPercentCallback;
00216 }
00217
00218
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
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
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
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 }