CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/EventFilter/StorageManager/src/ResourceMonitorCollection.cc

Go to the documentation of this file.
00001 // $Id: ResourceMonitorCollection.cc,v 1.47 2011/11/16 14:32:22 mommsen Exp $
00003 
00004 #include <stdio.h>
00005 #include <string>
00006 #include <sstream>
00007 #include <iomanip>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <fcntl.h>
00011 #include <dirent.h>
00012 #include <fnmatch.h>
00013 #include <pwd.h>
00014 #include <fstream>
00015 #include <algorithm>
00016 
00017 #include <boost/bind.hpp>
00018 #include <boost/regex.hpp> 
00019 
00020 #include "EventFilter/StorageManager/interface/AlarmHandler.h"
00021 #include "EventFilter/StorageManager/interface/CurlInterface.h"
00022 #include "EventFilter/StorageManager/interface/Exception.h"
00023 #include "EventFilter/StorageManager/interface/ResourceMonitorCollection.h"
00024 #include "EventFilter/StorageManager/interface/Utils.h"
00025 
00026 
00027 namespace stor {
00028   
00029   ResourceMonitorCollection::ResourceMonitorCollection
00030   (
00031     const utils::Duration_t& updateInterval,
00032     AlarmHandlerPtr ah
00033   ) :
00034   MonitorCollection(updateInterval),
00035   updateInterval_(updateInterval),
00036   alarmHandler_(ah),
00037   numberOfCopyWorkers_(-1),
00038   numberOfInjectWorkers_(-1),
00039   nLogicalDisks_(0),
00040   latchedSataBeastStatus_(-1)
00041   {}
00042   
00043   
00044   void ResourceMonitorCollection::configureDisks(DiskWritingParams const& dwParams)
00045   {
00046     boost::mutex::scoped_lock sl(diskUsageListMutex_);
00047     
00048     dwParams_ = dwParams;
00049     
00050     nLogicalDisks_ = std::max(dwParams.nLogicalDisk_, 1);
00051     diskUsageList_.clear();
00052     diskUsageList_.reserve(nLogicalDisks_+dwParams.otherDiskPaths_.size()+1);
00053     
00054     for (unsigned int i=0; i<nLogicalDisks_; ++i) {
00055       
00056       std::ostringstream pathName;
00057       pathName << dwParams.filePath_;
00058       if( dwParams.nLogicalDisk_ > 0 ) {
00059         pathName << "/" << std::setfill('0') << std::setw(2) << i; 
00060       }
00061       addDisk(pathName.str());
00062     }
00063     addDisk(dwParams.dbFilePath_);
00064     
00065     if ( alarmParams_.isProductionSystem_ )
00066     {
00067       addOtherDisks();
00068     }
00069   }
00070   
00071   
00072   void ResourceMonitorCollection::addDisk(const std::string& pathname)
00073   {
00074     if ( pathname.empty() ) return;
00075     
00076     DiskUsagePtr diskUsage( new DiskUsage(pathname) );
00077     retrieveDiskSize(diskUsage);
00078     diskUsageList_.push_back(diskUsage);
00079   }
00080   
00081   
00082   void ResourceMonitorCollection::addOtherDisks()
00083   {
00084     for ( DiskWritingParams::OtherDiskPaths::const_iterator
00085             it = dwParams_.otherDiskPaths_.begin(),
00086             itEnd =  dwParams_.otherDiskPaths_.end();
00087           it != itEnd;
00088           ++it)
00089     {
00090       addDisk(*it);
00091     }
00092   }
00093   
00094   
00095   void ResourceMonitorCollection::configureResources
00096   (
00097     ResourceMonitorParams const& rmParams
00098   )
00099   {
00100     rmParams_ = rmParams;
00101   }
00102   
00103   
00104   void ResourceMonitorCollection::configureAlarms
00105   (
00106     AlarmParams const& alarmParams
00107   )
00108   {
00109     alarmParams_ = alarmParams;
00110   }
00111   
00112   
00113   void ResourceMonitorCollection::getStats(Stats& stats) const
00114   {
00115     getDiskStats(stats);
00116     
00117     stats.numberOfCopyWorkers = numberOfCopyWorkers_;
00118     stats.numberOfInjectWorkers = numberOfInjectWorkers_;
00119     
00120     stats.sataBeastStatus = latchedSataBeastStatus_;
00121   }
00122   
00123   
00124   void ResourceMonitorCollection::getDiskStats(Stats& stats) const
00125   {
00126     boost::mutex::scoped_lock sl(diskUsageListMutex_);
00127     
00128     stats.diskUsageStatsList.clear();
00129     stats.diskUsageStatsList.reserve(diskUsageList_.size());
00130     for ( DiskUsagePtrList::const_iterator it = diskUsageList_.begin(),
00131             itEnd = diskUsageList_.end();
00132           it != itEnd;
00133           ++it)
00134     {
00135       DiskUsageStatsPtr diskUsageStats(new DiskUsageStats);
00136       diskUsageStats->diskSize = (*it)->diskSize_;
00137       diskUsageStats->absDiskUsage = (*it)->absDiskUsage_;
00138       diskUsageStats->relDiskUsage = (*it)->relDiskUsage_;
00139       diskUsageStats->pathName = (*it)->pathName_;
00140       diskUsageStats->alarmState = (*it)->alarmState_;
00141       stats.diskUsageStatsList.push_back(diskUsageStats);
00142     }
00143   }
00144   
00145   
00146   void ResourceMonitorCollection::do_calculateStatistics()
00147   {
00148     calcDiskUsage();
00149     calcNumberOfCopyWorkers();
00150     calcNumberOfInjectWorkers();
00151     checkSataBeasts();
00152   }
00153   
00154   
00155   void ResourceMonitorCollection::do_reset()
00156   {
00157     numberOfCopyWorkers_ = -1;
00158     numberOfInjectWorkers_ = -1;
00159     latchedSataBeastStatus_ = -1;
00160     
00161     boost::mutex::scoped_lock sl(diskUsageListMutex_);
00162     for ( DiskUsagePtrList::const_iterator it = diskUsageList_.begin(),
00163             itEnd = diskUsageList_.end();
00164           it != itEnd;
00165           ++it)
00166     {
00167       if ( ! (*it)->retrievingDiskSize_ )
00168       {
00169         (*it)->diskSize_ = -1;
00170         (*it)->absDiskUsage_ = -1;
00171         (*it)->relDiskUsage_ = -1;
00172         (*it)->retVal_ = 0;
00173         (*it)->alarmState_ = AlarmHandler::OKAY;
00174       }
00175     }
00176   }
00177   
00178   
00179   void ResourceMonitorCollection::do_appendInfoSpaceItems(InfoSpaceItems& infoSpaceItems)
00180   {
00181     infoSpaceItems.push_back(std::make_pair("copyWorkers", &copyWorkers_));
00182     infoSpaceItems.push_back(std::make_pair("injectWorkers", &injectWorkers_));
00183     infoSpaceItems.push_back(std::make_pair("sataBeastStatus", &sataBeastStatus_));
00184     infoSpaceItems.push_back(std::make_pair("numberOfDisks", &numberOfDisks_));
00185     infoSpaceItems.push_back(std::make_pair("diskPaths", &diskPaths_));
00186     infoSpaceItems.push_back(std::make_pair("totalDiskSpace", &totalDiskSpace_));
00187     infoSpaceItems.push_back(std::make_pair("usedDiskSpace", &usedDiskSpace_));
00188   }
00189   
00190   
00191   void ResourceMonitorCollection::do_updateInfoSpaceItems()
00192   {
00193     Stats stats;
00194     getStats(stats);
00195     
00196     if (stats.numberOfCopyWorkers > 0)
00197       copyWorkers_ = static_cast<xdata::UnsignedInteger32>(stats.numberOfCopyWorkers);
00198     else
00199       copyWorkers_ = 0;
00200 
00201     if (stats.numberOfInjectWorkers > 0)
00202       injectWorkers_ = static_cast<xdata::UnsignedInteger32>(stats.numberOfInjectWorkers);
00203     else
00204       injectWorkers_ = 0;
00205     
00206     sataBeastStatus_ = stats.sataBeastStatus;
00207     numberOfDisks_ = nLogicalDisks_;
00208     
00209     diskPaths_.clear();
00210     totalDiskSpace_.clear();
00211     usedDiskSpace_.clear();
00212     
00213     diskPaths_.reserve(stats.diskUsageStatsList.size());
00214     totalDiskSpace_.reserve(stats.diskUsageStatsList.size());
00215     usedDiskSpace_.reserve(stats.diskUsageStatsList.size());
00216     
00217     for (DiskUsageStatsPtrList::const_iterator
00218            it = stats.diskUsageStatsList.begin(),
00219            itEnd = stats.diskUsageStatsList.end();
00220          it != itEnd;
00221          ++it)
00222     {
00223       diskPaths_.push_back(
00224         static_cast<xdata::String>( (*it)->pathName )
00225       );
00226       totalDiskSpace_.push_back(
00227         static_cast<xdata::UnsignedInteger32>(
00228           static_cast<unsigned int>( (*it)->diskSize * 1024 )
00229         )
00230       );
00231       usedDiskSpace_.push_back(
00232         static_cast<xdata::UnsignedInteger32>( 
00233           static_cast<unsigned int>( (*it)->absDiskUsage * 1024 )
00234         )
00235       );
00236     }
00237     
00238     calcDiskUsage();
00239   }
00240   
00241   
00242   void ResourceMonitorCollection::calcDiskUsage()
00243   {
00244     boost::mutex::scoped_lock sl(diskUsageListMutex_);
00245     
00246     for ( DiskUsagePtrList::iterator it = diskUsageList_.begin(),
00247             itEnd = diskUsageList_.end();
00248           it != itEnd;
00249           ++it)
00250     {
00251       retrieveDiskSize(*it);
00252     }
00253   }
00254   
00255   
00256   void ResourceMonitorCollection::retrieveDiskSize(DiskUsagePtr diskUsage)
00257   {
00258     if ( ! diskUsage->retrievingDiskSize_ )
00259       // don't start another thread if there's already one
00260     {
00261       boost::thread thread(
00262         boost::bind( &ResourceMonitorCollection::doStatFs, this, diskUsage)
00263       );
00264       if (
00265         ( ! thread.timed_join( boost::posix_time::milliseconds(500) ) )
00266         || (diskUsage->retVal_ != 0)
00267       )
00268       {
00269         emitDiskAlarm(diskUsage);
00270       }
00271       else
00272       {
00273         const unsigned int blksize = diskUsage->statfs_.f_bsize;
00274         diskUsage->diskSize_ =
00275           static_cast<double>(diskUsage->statfs_.f_blocks * blksize) / 1024 / 1024 / 1024;
00276         diskUsage->absDiskUsage_ =
00277           diskUsage->diskSize_ -
00278           static_cast<double>(diskUsage->statfs_.f_bavail * blksize) / 1024 / 1024 / 1024;
00279         diskUsage->relDiskUsage_ = (100 * (diskUsage->absDiskUsage_ / diskUsage->diskSize_));
00280         if ( diskUsage->relDiskUsage_ > dwParams_.highWaterMark_ )
00281         {
00282           emitDiskSpaceAlarm(diskUsage);
00283         }
00284         else if ( diskUsage->relDiskUsage_ < dwParams_.highWaterMark_*0.95 )
00285           // do not change alarm level if we are close to the high water mark
00286         {
00287           revokeDiskAlarm(diskUsage);
00288         }
00289       }
00290     }
00291   }
00292   
00293   
00294   void ResourceMonitorCollection::doStatFs(DiskUsagePtr diskUsage)
00295   {
00296     diskUsage->retrievingDiskSize_ = true;
00297 
00298     #if __APPLE__
00299     diskUsage->retVal_ = statfs(diskUsage->pathName_.c_str(), &(diskUsage->statfs_));
00300     #else
00301     diskUsage->retVal_ = statfs64(diskUsage->pathName_.c_str(), &(diskUsage->statfs_));
00302     #endif
00303     if (diskUsage->pathName_ == "/aSlowDiskForUnitTests") ::sleep(5);
00304 
00305     diskUsage->retrievingDiskSize_ = false;
00306   }
00307   
00308   
00309   void ResourceMonitorCollection::emitDiskAlarm(DiskUsagePtr diskUsage)
00310   {
00311     const std::string msg = "Cannot access " + diskUsage->pathName_ + ". Is it mounted?";
00312 
00313     diskUsage->diskSize_ = -1;
00314     diskUsage->absDiskUsage_ = -1;
00315     diskUsage->relDiskUsage_ = -1;
00316 
00317     if ( isImportantDisk(diskUsage->pathName_) )
00318     {
00319       diskUsage->alarmState_ = AlarmHandler::FATAL;
00320       XCEPT_DECLARE(stor::exception::DiskSpaceAlarm, ex, msg);
00321       alarmHandler_->moveToFailedState(ex);
00322     }
00323     else
00324     {    
00325       diskUsage->alarmState_ = AlarmHandler::ERROR;
00326       XCEPT_DECLARE(stor::exception::DiskSpaceAlarm, ex, msg);
00327       alarmHandler_->raiseAlarm(diskUsage->pathName_, diskUsage->alarmState_, ex);
00328     }
00329   }
00330   
00331   
00332   void ResourceMonitorCollection::emitDiskSpaceAlarm(DiskUsagePtr diskUsage)
00333   {
00334     if (
00335       isImportantDisk(diskUsage->pathName_) &&
00336       (diskUsage->relDiskUsage_ > dwParams_.failHighWaterMark_)
00337     )
00338     {
00339       diskUsage->alarmState_ = AlarmHandler::FATAL;
00340       XCEPT_DECLARE(stor::exception::DiskSpaceAlarm, ex, diskUsage->toString());
00341       alarmHandler_->moveToFailedState(ex);
00342     }
00343     else
00344     {    
00345       diskUsage->alarmState_ = AlarmHandler::WARNING;
00346       XCEPT_DECLARE(stor::exception::DiskSpaceAlarm, ex, diskUsage->toString());
00347       alarmHandler_->raiseAlarm(diskUsage->pathName_, diskUsage->alarmState_, ex);
00348     }
00349   }
00350   
00351   
00352   bool ResourceMonitorCollection::isImportantDisk(const std::string& pathName)
00353   {
00354     DiskWritingParams::OtherDiskPaths::const_iterator begin =
00355       dwParams_.otherDiskPaths_.begin();
00356     DiskWritingParams::OtherDiskPaths::const_iterator end =
00357       dwParams_.otherDiskPaths_.end();
00358     return ( std::find(begin, end, pathName) == end );
00359   }
00360   
00361 
00362   void ResourceMonitorCollection::revokeDiskAlarm(DiskUsagePtr diskUsage)
00363   {
00364     diskUsage->alarmState_ = AlarmHandler::OKAY;
00365     
00366     alarmHandler_->revokeAlarm(diskUsage->pathName_);
00367   }
00368   
00369   
00370   void ResourceMonitorCollection::calcNumberOfCopyWorkers()
00371   {
00372     struct passwd* passwd = getpwnam(rmParams_.copyWorkers_.user_.c_str());
00373     if (passwd)
00374     {
00375       numberOfCopyWorkers_ =
00376         getProcessCount(rmParams_.copyWorkers_.command_, passwd->pw_uid);
00377     }
00378     else
00379     {
00380       numberOfCopyWorkers_ = 0;
00381     }
00382     
00383     if ( alarmParams_.isProductionSystem_ && rmParams_.copyWorkers_.expectedCount_ >= 0 )
00384     {
00385       checkNumberOfCopyWorkers();
00386     }
00387   }
00388   
00389   
00390   void ResourceMonitorCollection::checkNumberOfCopyWorkers()
00391   {
00392     const std::string alarmName = "CopyWorkers";
00393     
00394     if ( numberOfCopyWorkers_ < rmParams_.copyWorkers_.expectedCount_ )
00395     {
00396       std::ostringstream msg;
00397       msg << "Expected " << rmParams_.copyWorkers_.expectedCount_ <<
00398         " running CopyWorkers, but found " <<
00399         numberOfCopyWorkers_ << ".";
00400       XCEPT_DECLARE(stor::exception::CopyWorkers, ex, msg.str());
00401       alarmHandler_->raiseAlarm(alarmName, AlarmHandler::WARNING, ex);
00402     }
00403     else
00404     {
00405       alarmHandler_->revokeAlarm(alarmName);
00406     }
00407   }
00408   
00409   
00410   void ResourceMonitorCollection::calcNumberOfInjectWorkers()
00411   {
00412     struct passwd* passwd = getpwnam(rmParams_.injectWorkers_.user_.c_str());
00413     if (passwd)
00414     {
00415       numberOfInjectWorkers_ = getProcessCount(rmParams_.injectWorkers_.command_, passwd->pw_uid);
00416     }
00417     else
00418     {
00419       numberOfInjectWorkers_ = 0;
00420     }
00421     
00422     if (
00423       alarmParams_.isProductionSystem_ &&
00424       rmParams_.injectWorkers_.expectedCount_ >= 0
00425     )
00426     {
00427       checkNumberOfInjectWorkers();
00428     }
00429   }
00430   
00431   
00432   void ResourceMonitorCollection::checkNumberOfInjectWorkers()
00433   {
00434     const std::string alarmName = "InjectWorkers";
00435     
00436     if ( numberOfInjectWorkers_ != rmParams_.injectWorkers_.expectedCount_ )
00437     {
00438       std::ostringstream msg;
00439       msg << "Expected " << rmParams_.injectWorkers_.expectedCount_ <<
00440         " running InjectWorkers, but found " <<
00441         numberOfInjectWorkers_ << ".";
00442       XCEPT_DECLARE(stor::exception::InjectWorkers, ex, msg.str());
00443       alarmHandler_->raiseAlarm(alarmName, AlarmHandler::WARNING, ex);
00444     }
00445     else
00446     {
00447       alarmHandler_->revokeAlarm(alarmName);
00448     }
00449   }
00450   
00451   
00452   void ResourceMonitorCollection::checkSataBeasts()
00453   {
00454     SATABeasts sataBeasts;
00455     if ( getSataBeasts(sataBeasts) )
00456     {
00457       for (
00458         SATABeasts::const_iterator it = sataBeasts.begin(),
00459           itEnd= sataBeasts.end();
00460         it != itEnd;
00461         ++it
00462       )
00463       {
00464         checkSataBeast(*it);
00465       }
00466     }
00467     else
00468     {
00469       latchedSataBeastStatus_ = -1;
00470     }
00471   }
00472   
00473   
00474   bool ResourceMonitorCollection::getSataBeasts(SATABeasts& sataBeasts)
00475   {
00476     if (! alarmParams_.isProductionSystem_) return false;
00477     
00478     std::ifstream in;
00479     in.open( "/proc/mounts" );
00480     
00481     if ( ! in.is_open() ) return false;
00482     
00483     std::string line;
00484     while( getline(in,line) )
00485     {
00486       size_t pos = line.find("sata");
00487       if ( pos != std::string::npos )
00488       {
00489         std::ostringstream host;
00490         host << "satab-c2c"
00491           << std::setw(2) << std::setfill('0')
00492           << line.substr(pos+4,1)
00493           << "-"
00494           << std::setw(2) << std::setfill('0')
00495           << line.substr(pos+5,1);
00496         sataBeasts.insert(host.str());
00497       }
00498     }
00499     return !sataBeasts.empty();
00500   }
00501   
00502   
00503   void ResourceMonitorCollection::checkSataBeast(const std::string& sataBeast)
00504   {
00505     if ( ! (checkSataDisks(sataBeast,"-00.cms") || checkSataDisks(sataBeast,"-10.cms")) )
00506     {
00507       XCEPT_DECLARE(stor::exception::SataBeast, ex, 
00508         "Failed to connect to SATA beast " + sataBeast);
00509       alarmHandler_->raiseAlarm(sataBeast, AlarmHandler::ERROR, ex);
00510       
00511       latchedSataBeastStatus_ = 99999;
00512     }
00513   }
00514   
00515   
00516   bool ResourceMonitorCollection::checkSataDisks
00517   (
00518     const std::string& sataBeast,
00519     const std::string& hostSuffix
00520   )
00521   {
00522     CurlInterfacePtr curlInterface = CurlInterface::getInterface();
00523     CurlInterface::Content content;
00524     
00525     // Do not try to connect if we have no user name
00526     if ( rmParams_.sataUser_.empty() ) return true;
00527     
00528     const CURLcode returnCode =
00529       curlInterface->getContent(
00530         "http://" + sataBeast + hostSuffix + "/status.asp",rmParams_.sataUser_,
00531         content
00532       );
00533     
00534     if (returnCode == CURLE_OK)
00535     {
00536       updateSataBeastStatus(sataBeast, std::string(&content[0]));
00537       return true;
00538     }
00539     else
00540     {
00541       std::ostringstream msg;
00542       msg << "Failed to connect to SATA controller "
00543         << sataBeast << hostSuffix 
00544         << ": " << std::string(&content[0]);
00545       XCEPT_DECLARE(stor::exception::SataBeast, ex, msg.str());
00546       alarmHandler_->notifySentinel(AlarmHandler::WARNING, ex);
00547       
00548       return false;
00549     }
00550   }
00551   
00552   
00553   void ResourceMonitorCollection::updateSataBeastStatus
00554   (
00555     const std::string& sataBeast,
00556     const std::string& content
00557   )
00558   {
00559     boost::regex failedEntry(">([^<]* has failed[^<]*)");
00560     boost::regex failedDisk("Hard disk([[:digit:]]+)");
00561     boost::regex failedController("RAID controller ([[:digit:]]+)");
00562     boost::match_results<std::string::const_iterator> matchedEntry, matchedCause;
00563     boost::match_flag_type flags = boost::match_default;
00564     
00565     std::string::const_iterator start = content.begin();
00566     std::string::const_iterator end = content.end();
00567     
00568     unsigned int newSataBeastStatus = 0;
00569     
00570     while( regex_search(start, end, matchedEntry, failedEntry, flags) )
00571     {
00572       std::string errorMsg = matchedEntry[1];
00573       XCEPT_DECLARE(stor::exception::SataBeast, ex, sataBeast+": "+errorMsg);
00574       alarmHandler_->raiseAlarm(sataBeast, AlarmHandler::ERROR, ex);
00575       
00576       // find what failed
00577       if ( regex_search(errorMsg, matchedCause, failedDisk) )
00578       {
00579         // Update the number of failed disks
00580         ++newSataBeastStatus;
00581       }
00582       else if ( regex_search(errorMsg, matchedCause, failedController) )
00583       {
00584         // Update the number of failed controllers
00585         newSataBeastStatus += 100;
00586       }
00587       else
00588       {
00589         // Unknown failure
00590         newSataBeastStatus += 1000;
00591       }
00592       
00593       // update search position:
00594       start = matchedEntry[0].second;
00595       // update flags:
00596       flags |= boost::match_prev_avail;
00597       flags |= boost::match_not_bob;
00598     }
00599     
00600     latchedSataBeastStatus_ = newSataBeastStatus;
00601     
00602     if (latchedSataBeastStatus_ == 0) // no more problems
00603       alarmHandler_->revokeAlarm(sataBeast);
00604     
00605   }
00606   
00607   
00608   namespace {
00609     int filter(const struct dirent *dir)
00610     {
00611       return !fnmatch("[1-9]*", dir->d_name, 0);
00612     }
00613     
00614     bool matchUid(const std::string& filename, const uid_t& uid)
00615     {
00616       struct stat filestat;
00617       int result = stat(filename.c_str(), &filestat);
00618       return (result == 0 && filestat.st_uid == uid);
00619     }
00620     
00621     bool isMaster(const char* pid)
00622     {
00623       // Adapted from procps::minimal::stat2proc
00624       char buf[800]; // about 40 fields, 64-bit decimal is about 20 chars
00625       int fd;
00626       int ppid = 0;
00627       std::ostringstream statfile;
00628       statfile << "/proc/" << pid << "/stat";
00629       snprintf(buf, 32, statfile.str().c_str(), pid);
00630       if ( (fd = open(buf, O_RDONLY, 0) ) == -1 ) return false;
00631       int num = read(fd, buf, sizeof buf - 1);
00632       if(num<80) return false;
00633       buf[num] = '\0';
00634       char* tmp = strrchr(buf, ')');  // split into "PID (cmd" and "<rest>"
00635       num = sscanf(tmp + 4,           // skip ') %c '
00636         "%d", &ppid);
00637       close(fd);
00638       return ( num == 1 && ppid == 1 ); // scan succeeded and parent pid is 1
00639     }
00640     
00641     bool grep(const std::string& cmdline, const std::string& name)
00642     {
00643       
00644       std::ifstream in;
00645       in.open( cmdline.c_str() );
00646       
00647       std::string line;
00648       if ( in.is_open() )
00649       {
00650         std::string tmp;
00651         while( getline(in,tmp,'\0') )
00652         {
00653           line.append(tmp);
00654           line.append(" ");
00655         }
00656         in.close();
00657       }
00658 
00659       return ( line.find(name) != std::string::npos );
00660     }
00661   }
00662   
00663   
00664   int ResourceMonitorCollection::getProcessCount
00665   (
00666     const std::string& processName,
00667     const int& uid
00668   )
00669   {
00670     int count(0);
00671     struct dirent **namelist;
00672     int n;
00673     
00674     #if __APPLE__
00675     return -1;
00676     #else 
00677     n = scandir("/proc", &namelist, filter, 0);
00678     #endif
00679     if (n < 0) return -1;
00680     
00681     while(n--)
00682     {
00683       std::ostringstream cmdline;
00684       cmdline << "/proc/" << namelist[n]->d_name << "/cmdline";
00685       
00686       if ( grep(cmdline.str(), processName) &&
00687         (uid < 0 || matchUid(cmdline.str(), uid)) &&
00688         isMaster(namelist[n]->d_name) )
00689       {
00690         ++count;
00691       }
00692       free(namelist[n]);
00693     }
00694     free(namelist);
00695     
00696     return count;
00697   }
00698   
00699   
00700   ResourceMonitorCollection::DiskUsage::DiskUsage(const std::string& path)
00701   : pathName_(path), absDiskUsage_(-1), relDiskUsage_(-1), diskSize_(-1),
00702     retrievingDiskSize_(false), alarmState_(AlarmHandler::OKAY), retVal_(0)
00703   {}
00704   
00705   
00706   std::string ResourceMonitorCollection::DiskUsage::toString()
00707   {
00708     std::ostringstream msg;
00709     msg << std::fixed << std::setprecision(1) <<
00710       "Disk space usage for " << pathName_ <<
00711       " is " << relDiskUsage_ << "% (" <<
00712       absDiskUsage_ << "GB of " <<
00713       diskSize_ << "GB).";
00714     return msg.str();
00715   }
00716   
00717 } // namespace stor
00718