CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/FWCore/Services/src/ProcInfoFetcher.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Services
00004 // Class  :     ProcInfoFetcher
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Sun May  6 11:14:31 CDT 2012
00011 // $Id: ProcInfoFetcher.cc,v 1.1 2012/05/06 19:11:56 chrjones Exp $
00012 //
00013 
00014 // system include files
00015 
00016 // user include files
00017 
00018 #include <cstring>
00019 #include <cassert>
00020 #include <iostream>
00021 #ifdef __linux__
00022 #include <malloc.h>
00023 #endif
00024 #include <sstream>
00025 //#include <stdio.h>
00026 #include <string>
00027 #include <boost/lexical_cast.hpp>
00028 
00029 #include <fcntl.h>
00030 #include <unistd.h>
00031 
00032 #include "FWCore/Services/src/ProcInfoFetcher.h"
00033 #include "FWCore/Utilities/interface/EDMException.h"
00034 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00035 
00036 
00037 //
00038 // constants, enums and typedefs
00039 //
00040 
00041 //
00042 // static data member definitions
00043 //
00044 
00045 namespace { 
00046   struct linux_proc {
00047     int pid; // %d
00048     std::string comm;
00049     char state; // %c
00050     int ppid; // %d
00051     int pgrp; // %d
00052     int session; // %d
00053     int tty; // %d
00054     int tpgid; // %d
00055     unsigned long flags; // %lu
00056     unsigned long minflt; // %lu
00057     unsigned long cminflt; // %lu
00058     unsigned long majflt; // %lu
00059     unsigned long cmajflt; // %lu
00060     unsigned long utime; // %lu
00061     unsigned long stime; // %lu
00062     long cutime; // %ld
00063     long cstime; // %ld
00064     long priority; // %ld
00065     long nice; // %ld
00066     long num_threads; // %ld
00067     long itrealvalue; // %ld
00068     int starttime; // %d
00069     unsigned long vsize; // %lu
00070     long rss; // %ld
00071     unsigned long rlim; // %lu
00072     unsigned long startcode; // %lu
00073     unsigned long endcode; // %lu
00074     unsigned long startstack; // %lu
00075     unsigned long kstkesp; // %lu
00076     unsigned long kstkeip; // %lu
00077     unsigned long signal; // %lu
00078     unsigned long blocked; // %lu
00079     unsigned long sigignore; // %lu
00080     unsigned long sigcatch; // %lu
00081     unsigned long wchan; // %lu
00082   };
00083   
00084   class Fetcher {
00085   public:
00086     friend Fetcher& operator>>(Fetcher&, int&);
00087     friend Fetcher& operator>>(Fetcher&, long&);
00088     friend Fetcher& operator>>(Fetcher&, unsigned int&);
00089     friend Fetcher& operator>>(Fetcher&, unsigned long&);
00090     friend Fetcher& operator>>(Fetcher&, char&);
00091     friend Fetcher& operator>>(Fetcher&, std::string&);
00092     
00093     explicit Fetcher(char* buffer) : 
00094     buffer_(buffer),
00095     save_(0),
00096     delims_(" \t\n\f\v\r") {
00097     }
00098   private:
00099     int getInt() {
00100       const char* t = getItem();
00101       //std::cout <<"int '"<<t <<"'"<<std::endl;
00102       return boost::lexical_cast<int>(t);
00103     }
00104     long getLong() {
00105       const char* t = getItem();
00106       //std::cout <<"long '"<<t <<"'"<<std::endl;
00107       return boost::lexical_cast<long>(t);
00108     }
00109     unsigned int getUInt() {
00110       const char* t = getItem();
00111       //std::cout <<"uint '"<<t <<"'"<<std::endl;
00112       return boost::lexical_cast<unsigned int>(t);
00113     }
00114     unsigned long getULong() {
00115       const char* t = getItem();
00116       //std::cout <<"ulong '"<<t <<"'"<<std::endl;
00117       return boost::lexical_cast<unsigned long>(t);
00118     }
00119     char getChar() {
00120       return *getItem();
00121     }
00122     std::string getString() {
00123       return std::string(getItem());
00124     }
00125     char* getItem() {
00126       char* item = strtok_r(buffer_, delims_, &save_); 
00127       assert(item);
00128       buffer_ = 0; // Null for subsequent strtok_r calls.
00129       return item;
00130     }
00131     char* buffer_;
00132     char* save_;
00133     char const* const delims_; 
00134   };
00135   
00136   Fetcher& operator>>(Fetcher& iFetch, int& oValue) {
00137     oValue = iFetch.getInt();
00138     return iFetch;
00139   }
00140   Fetcher& operator>>(Fetcher& iFetch, long& oValue) {
00141     oValue = iFetch.getLong();
00142     return iFetch;
00143   }
00144   Fetcher& operator>>(Fetcher& iFetch, unsigned int& oValue) {
00145     oValue = iFetch.getUInt();
00146     return iFetch;      
00147   }
00148   Fetcher& operator>>(Fetcher& iFetch, unsigned long& oValue) {
00149     oValue = iFetch.getULong();
00150     return iFetch;      
00151   }
00152   Fetcher& operator>>(Fetcher& iFetch, char& oValue) {
00153     oValue = iFetch.getChar();
00154     return iFetch;
00155   }
00156   Fetcher& operator>>(Fetcher& iFetch, std::string& oValue) {
00157     oValue = iFetch.getString();
00158     return iFetch;
00159   }
00160 }
00161 
00162 namespace edm {
00163   namespace service {
00164   
00165     ProcInfoFetcher::ProcInfoFetcher():
00166     pg_size_(sysconf(_SC_PAGESIZE)) {
00167 #ifdef __linux__
00168       std::ostringstream ost;
00169       ost << "/proc/" << getpid() << "/stat";
00170       
00171       if((fd_ = open(ost.str().c_str(), O_RDONLY)) < 0) {
00172         throw Exception(errors::Configuration)
00173         << "Failed to open " << ost.str() << std::endl;
00174       }
00175 #endif
00176     }
00177     ProcInfoFetcher::~ProcInfoFetcher() {
00178 #ifdef LINUX
00179       close(fd_);
00180 #endif      
00181     }
00182     ProcInfo ProcInfoFetcher::fetch() const {
00183       ProcInfo ret;
00184       
00185 #ifdef __linux__
00186       double pr_size = 0.0, pr_rssize = 0.0;
00187       
00188       linux_proc pinfo;
00189       int cnt;
00190       
00191       lseek(fd_, 0, SEEK_SET);
00192       
00193       if((cnt = read(fd_, buf_, sizeof(buf_) - 1)) < 0) {
00194         perror("Read of Proc file failed:");
00195         return ProcInfo();
00196       }
00197       
00198       if(cnt > 0) {
00199         buf_[cnt] = '\0';
00200         
00201         
00202         try {
00203           Fetcher fetcher(buf_);
00204           fetcher >> pinfo.pid
00205           >> pinfo.comm
00206           >> pinfo.state
00207           >> pinfo.ppid
00208           >> pinfo.pgrp
00209           >> pinfo.session
00210           >> pinfo.tty
00211           >> pinfo.tpgid
00212           >> pinfo.flags
00213           >> pinfo.minflt
00214           >> pinfo.cminflt
00215           >> pinfo.majflt
00216           >> pinfo.cmajflt
00217           >> pinfo.utime
00218           >> pinfo.stime
00219           >> pinfo.cutime
00220           >> pinfo.cstime
00221           >> pinfo.priority
00222           >> pinfo.nice
00223           >> pinfo.num_threads
00224           >> pinfo.itrealvalue
00225           >> pinfo.starttime
00226           >> pinfo.vsize
00227           >> pinfo.rss
00228           >> pinfo.rlim
00229           >> pinfo.startcode
00230           >> pinfo.endcode
00231           >> pinfo.startstack
00232           >> pinfo.kstkesp
00233           >> pinfo.kstkeip
00234           >> pinfo.signal
00235           >> pinfo.blocked
00236           >> pinfo.sigignore
00237           >> pinfo.sigcatch
00238           >> pinfo.wchan;
00239         } catch (boost::bad_lexical_cast& iE) {
00240           LogWarning("ProcInfoFetcher")<<"Parsing of Prof file failed:"<<iE.what()<<std::endl;
00241           return ProcInfo();
00242         }
00243         
00244         // resident set size in pages
00245         pr_size = (double)pinfo.vsize;
00246         pr_rssize = (double)pinfo.rss;
00247         
00248         ret.vsize = pr_size / (1024.0*1024.0);
00249         ret.rss   = (pr_rssize * pg_size_) / (1024.0*1024.0);
00250       }
00251 #else
00252       ret.vsize = 0;
00253       ret.rss = 0;
00254 #endif
00255       return ret;
00256     }
00257   }
00258 }