libGizmod/CPUUsage.cpp

Go to the documentation of this file.
00001 
00012 /*
00013   
00014   Copyright (c) 2007, Tim Burrell
00015   Licensed under the Apache License, Version 2.0 (the "License");
00016   you may not use this file except in compliance with the License.
00017   You may obtain a copy of the License at 
00018 
00019         http://www.apache.org/licenses/LICENSE-2.0
00020 
00021   Unless required by applicable law or agreed to in writing, software
00022   distributed under the License is distributed on an "AS IS" BASIS,
00023   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00024   See the License for the specific language governing permissions and 
00025   limitations under the License. 
00026   
00027 */
00028 
00029 #include "CPUUsage.hpp"
00030 #include "../libH/Debug.hpp"
00031 #include "../libH/Exception.hpp"
00032 #include "../libH/UtilTime.hpp"
00033 #include <fstream>
00034 #include <iostream>
00035 #include <boost/filesystem/operations.hpp>
00036 #include <boost/filesystem/exception.hpp>
00037 #include <boost/thread/thread.hpp>
00038 
00039 using namespace std;
00040 using namespace boost;
00041 using namespace boost::filesystem;
00042 using namespace H;
00043 using namespace Gizmod;
00044 
00046 // Typedef's / defines
00048 
00053 #define PROC_STAT_PATH          "/proc/stat"
00054 
00059 #define DEFAULT_UPDATE_DELAY    0.1f
00060 
00062 // Statics 
00064         
00066 // Construction
00068 
00072 CPUUsage::CPUUsage() : mThreadProc(this) {
00073         mSecsBetweenUpdates = DEFAULT_UPDATE_DELAY;
00074         mWatching = false;
00075         mThreading = false;
00076         getNumCPUs();
00077 }
00078 
00082 CPUUsageInfo::CPUUsageInfo() {
00083         memset(Field, 0, sizeof(double) * CPUUSAGE_MAX);
00084         memset(Stat, 0, sizeof(double) * CPUUSAGE_MAX); 
00085         Usage = 0.0;
00086         Average = 0.0;
00087 }
00088 
00092 CPUUsage::~CPUUsage() {
00093         shutdown();
00094 }
00095 
00099 CPUUsageInfo::~CPUUsageInfo() {
00100 }
00101 
00103 // Class Body
00105 
00110 size_t CPUUsage::getNumCPUs() {
00111         if (mCPUUsage.size() == 0) {
00112                 if (!filesystem::exists(path(PROC_STAT_PATH))) {
00113                         cdbg << "Can not update CPU Usage Stats!" << endl;
00114                         return -1;
00115                 }
00116                                         
00117                 // open the file
00118                 ifstream StatFile(PROC_STAT_PATH);
00119                 if (!StatFile.is_open()) {
00120                         cdbg << "Error Updating CPU Usage Stats!" << endl;
00121                         return -1;
00122                 }
00123                                 
00124                 // read the contents
00125                 string Line;
00126                 int cpus = 0;
00127                 while (true) {
00128                         // get the line and make sure it's related to cpu information
00129                         getline(StatFile, Line);
00130                         if (Line.find("cpu") != 0)
00131                                 break;
00132                         cpus ++;
00133                 }
00134                 
00135                 mCPUUsage.resize(cpus);
00136                 for (int lp = 0; lp < cpus; lp ++)
00137                         mCPUUsage[lp] = shared_ptr<CPUUsageInfo>(new CPUUsageInfo);
00138         }
00139         
00140         return mCPUUsage.size() - 1;
00141 }
00142 
00146 void CPUUsage::init() {
00147         if (getNumCPUs() < 0) {
00148                 cdbg << "Cannot give CPU Usage Stats! -- Cannot access [" << PROC_STAT_PATH << "]" << endl;
00149                 return;
00150         }
00151         
00152         // initialize the event handler thread
00153         thread thrd(mThreadProc);
00154 }
00155 
00160 void CPUUsage::onCPUUsage(std::vector< boost::shared_ptr<CPUUsageInfo> > const & Event) {
00161         // override me
00162 }
00163 
00168 void CPUUsage::setTimeBetweenUpdates(float Seconds) {
00169         mSecsBetweenUpdates = Seconds;
00170 }
00171 
00175 void CPUUsage::shutdown() {
00176         mWatching = false;
00177         while (mThreading) {
00178                 cdbg5 << "Waiting on CPUUsage Thread to Finish..." << endl;
00179                 UtilTime::sleep(0.1f);
00180         }
00181 }
00182 
00186 void CPUUsage::threadProc() {
00187         // wait for events to occur
00188         mWatching = true;
00189         while (mWatching) {
00190                 updateUsageStats();
00191                 UtilTime::sleep(mSecsBetweenUpdates);
00192         }
00193 }
00194 
00198 void CPUUsage::updateUsageStats() {
00199         // open the file
00200         FILE * StatFile;
00201         if ((StatFile = fopen(PROC_STAT_PATH, "r")) == NULL) {
00202                 cdbg << "Failed get CPU Usage Information" << endl;
00203                 return;
00204         }
00205 
00206         // read and close
00207         for (size_t cpu = 0; cpu < mCPUUsage.size(); cpu ++) {
00208                 double Info[CPUUSAGE_MAX];
00209                 int CpuIndex = 0;
00210                 shared_ptr<CPUUsageInfo> pUsage = mCPUUsage[cpu];
00211                 if (cpu == 0)
00212                         fscanf(StatFile, "cpu %lf %lf %lf %lf %lf %lf %lf %lf\n", Info, Info + 1, Info + 2, Info + 3, Info + 4, Info + 5, Info + 6, Info + 7);
00213                 else {
00214                         fscanf(StatFile, "cpu%d %lf %lf %lf %lf %lf %lf %lf %lf\n", &CpuIndex, Info, Info + 1, Info + 2, Info + 3, Info + 4, Info + 5, Info + 6, Info + 7);
00215                 }
00216                 
00217                 // calculate the total
00218                 double Total = 0.0;
00219                 for (int lp = 0; lp < CPUUSAGE_MAX; lp ++) {
00220                         //Total 
00221                         pUsage->Field[lp] = Info[lp] - pUsage->Stat[lp];
00222                         Total += pUsage->Field[lp];
00223                         pUsage->Stat[lp] = Info[lp];
00224                 } 
00225                 pUsage->Usage = ((Total - pUsage->Field[CPUUSAGE_IDLE] - pUsage->Field[CPUUSAGE_IOWAIT]) / Total) * 100.0;
00226                 pUsage->mAverager.push(pUsage->Usage);
00227                 pUsage->Average = pUsage->mAverager.average();
00228         }
00229         fclose(StatFile);
00230 
00231         // fire the event
00232         onCPUUsage(mCPUUsage);
00233 }

Generated on Wed Nov 7 10:04:16 2007 for gizmod by  doxygen 1.5.3