memsensor.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2003 by Hans Karlsson                                   *
00003  *   karlsson.h@home.se                                                      *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 #include "memsensor.h"
00011 #include <qfile.h>
00012 #include <qglobal.h>
00013 #include <qtextstream.h>
00014 #include <qstring.h>
00015 #include <qregexp.h>
00016 
00017 #ifdef Q_OS_FREEBSD
00018 #include <sys/time.h>
00019 #include <sys/param.h>
00020 #include <sys/sysctl.h>
00021 #include <sys/resource.h>
00022 #include <unistd.h>
00023 #include <kvm.h>
00024 #include <sys/file.h>
00025 #include <osreldate.h>
00026 #endif
00027 
00028 #if defined(Q_OS_NETBSD)
00029 #include <sys/param.h>
00030 #include <sys/sysctl.h>
00031 #include <sys/sched.h>
00032 #include <sys/swap.h>
00033 #endif
00034 
00035 #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD)
00036 /* define pagetok in terms of pageshift */
00037 #define pagetok(size) ((size) << pageshift)
00038 #endif
00039 
00040 MemSensor::MemSensor(int msec) : Sensor(msec)
00041 {
00042 #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD)
00043    /* get the page size with "getpagesize" and calculate pageshift from it */
00044     int pagesize = getpagesize();
00045     pageshift = 0;
00046     while (pagesize > 1)
00047     {
00048         pageshift++;
00049         pagesize >>= 1;
00050     }
00051 
00052     /* we only need the amount of log(2)1024 for our conversion */
00053     pageshift -= 10;
00054 # if (defined(Q_OS_FREEBSD) && __FreeBSD_version < 500018)
00055     connect(&ksp, SIGNAL(receivedStdout(KProcess *, char *, int )),
00056             this,SLOT(receivedStdout(KProcess *, char *, int )));
00057     connect(&ksp, SIGNAL(processExited(KProcess *)),
00058             this,SLOT(processExited( KProcess * )));
00059 
00060     swapTotal = swapUsed = 0;
00061 
00062     MaxSet = false;
00063 
00064     readValues();
00065 # elif defined Q_OS_FREEBSD
00066     kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open");
00067 # endif
00068 #else
00069     readValues();
00070 #endif
00071 }
00072 
00073 MemSensor::~MemSensor()
00074 {}
00075 
00076 #ifdef Q_OS_FREEBSD
00077 void MemSensor::receivedStdout(KProcess *, char *buffer, int len )
00078 {
00079     buffer[len] = 0;
00080     sensorResult += QString( QCString(buffer) );
00081 }
00082 #else
00083 void MemSensor::receivedStdout(KProcess *, char *, int)
00084 {
00085 }
00086 #endif
00087 
00088 void MemSensor::processExited(KProcess *)
00089 {
00090 #ifdef Q_OS_FREEBSD
00091     QStringList stringList = QStringList::split('\n',sensorResult);
00092     sensorResult = "";
00093     QStringList itemsList = QStringList::split(' ', stringList[1]);
00094 
00095     swapUsed = itemsList[2].toInt();
00096     swapTotal = itemsList[1].toInt();
00097 #endif
00098 }
00099 
00100 int MemSensor::getMemTotal()
00101 {
00102 #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD)
00103     static int mem = 0;
00104     size_t size = sizeof(mem);
00105 
00106     sysctlbyname("hw.physmem", &mem, &size, NULL, 0);
00107     return (mem / 1024);
00108 #else
00109     QRegExp rx( "MemTotal:\\s*(\\d+)" );
00110     rx.search( meminfo );
00111     return ( rx.cap(1).toInt() );
00112 #endif
00113 }
00114 
00115 int MemSensor::getMemFree()
00116 {
00117 #ifdef Q_OS_FREEBSD
00118     static int mem = 0;
00119     size_t size = sizeof(mem);
00120 
00121     sysctlbyname("vm.stats.vm.v_free_count", &mem, &size, NULL, 0);
00122     return (pagetok(mem));
00123 #elif defined(Q_OS_NETBSD)
00124     struct uvmexp_sysctl uvmexp;
00125     int mib[2];
00126     size_t ssize;
00127     mib[0] = CTL_VM;
00128     mib[1] = VM_UVMEXP2;
00129     ssize = sizeof(uvmexp);
00130     sysctl(mib,2,&uvmexp,&ssize,NULL,0);
00131     return pagetok(uvmexp.free);
00132 #else
00133     QRegExp rx( "MemFree:\\s*(\\d+)" );
00134     rx.search( meminfo );
00135     return ( rx.cap(1).toInt() );
00136 #endif
00137 }
00138 
00139 int MemSensor::getBuffers()
00140 {
00141 #ifdef Q_OS_FREEBSD
00142     static int mem = 0;
00143     size_t size = sizeof(mem);
00144 
00145     sysctlbyname("vfs.bufspace", &mem, &size, NULL, 0);
00146     return (mem / 1024);
00147 #elif defined(Q_OS_NETBSD)
00148     static int buf_mem = 0;
00149     size_t size = sizeof(buf_mem);
00150 
00151     sysctlbyname("vm.bufmem", &buf_mem, &size, NULL, 0);
00152     return (buf_mem / 1024);
00153 #else
00154     QRegExp rx( "Buffers:\\s*(\\d+)" );
00155     rx.search( meminfo );
00156     return ( rx.cap(1).toInt() );
00157 #endif
00158 }
00159 
00160 int MemSensor::getCached()
00161 {
00162 #ifdef Q_OS_FREEBSD
00163     static int mem = 0;
00164     size_t size = sizeof(mem);
00165 
00166     sysctlbyname("vm.stats.vm.v_cache_count", &mem, &size, NULL, 0);
00167     return (pagetok(mem));
00168 #elif defined(Q_OS_NETBSD)
00169     return 0;
00170 #else
00171     QRegExp rx1( "Cached:\\s*(\\d+)" );
00172     QRegExp rx2( "SwapCached:\\s*(\\d+)" );
00173     rx1.search( meminfo );
00174     rx2.search( meminfo );
00175     return ( rx1.cap(1).toInt() + rx2.cap(1).toInt() );
00176 #endif
00177 }
00178 
00179 
00180 int MemSensor::getSwapTotal()
00181 {
00182 #ifdef Q_OS_FREEBSD
00183 # if __FreeBSD_version < 500018
00184     return(swapTotal);
00185 # else
00186     int n = -1;
00187     int pagesize = getpagesize();
00188     int retavail = 0;
00189 
00190     if (kd != NULL)
00191         n = kvm_getswapinfo(kd, &swapinfo, 1, 0);
00192 
00193     if (n < 0 || swapinfo.ksw_total == 0)
00194         return(0);
00195 
00196     retavail = swapinfo.ksw_total * pagesize / 1024;
00197 
00198     return(retavail);
00199 # endif
00200 #elif defined(Q_OS_NETBSD)
00201     struct uvmexp_sysctl uvmexp;
00202     int STotal = 0;
00203     int pagesize = 1;
00204     int mib[2];
00205     size_t ssize;
00206     mib[0] = CTL_VM;
00207     mib[1] = VM_UVMEXP;
00208     ssize = sizeof(uvmexp);
00209 
00210     if (sysctl(mib,2,&uvmexp,&ssize,NULL,0) != -1) {
00211     pagesize = uvmexp.pagesize;
00212     STotal = (pagesize*uvmexp.swpages) >> 10;
00213     }
00214     return STotal;
00215 #else
00216     QRegExp rx( "SwapTotal:\\s*(\\d+)" );
00217     rx.search( meminfo );
00218     return ( rx.cap(1).toInt() );
00219 #endif
00220 }
00221 
00222 int MemSensor::getSwapFree()
00223 {
00224 #ifdef Q_OS_FREEBSD
00225 # if __FreeBSD_version < 500018
00226     return(swapTotal - swapUsed);
00227 # else
00228     int n = -1;
00229     int pagesize = getpagesize();
00230     int retfree = 0;
00231 
00232     if (kd != NULL)
00233         n = kvm_getswapinfo(kd, &swapinfo, 1, 0);
00234     if (n < 0 || swapinfo.ksw_total == 0)
00235         return(0);
00236 
00237     retfree = (swapinfo.ksw_total - swapinfo.ksw_used) * pagesize / 1024;
00238 
00239     return(retfree);
00240 # endif
00241 #elif defined(Q_OS_NETBSD)
00242     struct uvmexp_sysctl uvmexp;
00243     int STotal = 0;
00244     int SFree = 0;
00245     int SUsed = 0;
00246     int pagesize = 1;
00247     int mib[2];
00248     size_t ssize;
00249     mib[0] = CTL_VM;
00250     mib[1] = VM_UVMEXP;
00251     ssize = sizeof(uvmexp);
00252 
00253     if (sysctl(mib,2,&uvmexp,&ssize,NULL,0) != -1) {
00254     pagesize = uvmexp.pagesize;
00255     STotal = (pagesize*uvmexp.swpages) >> 10;
00256     SUsed = (pagesize*uvmexp.swpginuse) >> 10;
00257     SFree = STotal - SUsed;
00258     }
00259     return SFree;
00260 #else
00261     QRegExp rx( "SwapFree:\\s*(\\d+)" );
00262     rx.search( meminfo );
00263     return ( rx.cap(1).toInt() );
00264 #endif
00265 }
00266 
00267 void MemSensor::readValues()
00268 {
00269 #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD)
00270 # if (defined(Q_OS_FREEBSD) && __FreeBSD_version < 500018)
00271     ksp.clearArguments();
00272     ksp << "swapinfo";
00273     ksp.start( KProcess::NotifyOnExit,KProcIO::Stdout);
00274 # endif
00275 #else
00276     QFile file("/proc/meminfo");
00277     QString line;
00278     if ( file.open(IO_ReadOnly | IO_Translate) )
00279     {
00280         QTextStream t( &file );        // use a text stream
00281         meminfo = t.read();
00282         file.close();
00283     }
00284 #endif
00285 }
00286 
00287 void MemSensor::update()
00288 {
00289     readValues();
00290     QString format;
00291     SensorParams *sp;
00292     Meter *meter;
00293     QObjectListIt it( *objList );
00294 #if (defined(Q_OS_FREEBSD) && __FreeBSD_version < 500018)
00295     bool set = false;
00296 #endif
00297     int totalMem = getMemTotal();
00298     int usedMem = totalMem - getMemFree();
00299     int usedMemNoBuffers =  usedMem - getBuffers() - getCached();
00300     int totalSwap = getSwapTotal();
00301     int usedSwap = totalSwap - getSwapFree();
00302 
00303     while (it != 0)
00304     {
00305         sp = (SensorParams*)(*it);
00306 #if (defined(Q_OS_FREEBSD) && __FreeBSD_version < 500018)
00307         if ( (!MaxSet) && (totalSwap > 0) ) {
00308            setMaxValue(sp);
00309            bool set = true;
00310         }
00311 #endif
00312         meter = sp->getMeter();
00313         format = sp->getParam("FORMAT");
00314         if (format.length() == 0 )
00315         {
00316             format = "%um";
00317         }
00318 
00319         format.replace( QRegExp("%fmb", false), QString::number( (int)(( totalMem - usedMemNoBuffers)/1024.0+0.5)));
00320         format.replace( QRegExp("%fm", false), QString::number( (int)( ( totalMem - usedMem  )/1024.0+0.5) ));
00321 
00322         format.replace( QRegExp("%umb", false), QString::number( (int)((usedMemNoBuffers)/1024.0+0.5)));
00323         format.replace( QRegExp("%um", false), QString::number( (int)((usedMem)/1024.0+0.5 )));
00324 
00325         format.replace( QRegExp("%tm", false), QString::number( (int)( (totalMem)/1024.0+0.5)));
00326 
00327         format.replace( QRegExp("%fs", false), QString::number( (int)((totalSwap - usedSwap)/1024.0+0.5)));
00328         format.replace( QRegExp("%us", false), QString::number( (int)(usedSwap/1024.0+0.5)));
00329         format.replace( QRegExp("%ts", false), QString::number( (int)(totalSwap/1024.0+0.5)));
00330 
00331         meter->setValue(format);
00332         ++it;
00333     }
00334 #if (defined(Q_OS_FREEBSD) && __FreeBSD_version < 500018)
00335     if (set)
00336         MaxSet = true;
00337 #endif
00338 }
00339 
00340 void MemSensor::setMaxValue( SensorParams *sp )
00341 {
00342     Meter *meter;
00343     meter = sp->getMeter();
00344     QString f;
00345     f = sp->getParam("FORMAT");
00346 
00347     if (f.length() == 0 )
00348     {
00349         f = "%um";
00350     }
00351     if( f=="%fm" || f== "%um" || f=="%fmb" || f=="%umb" )
00352         meter->setMax( getMemTotal() / 1024 );
00353     if( f=="%fs" || f== "%us" )
00354         meter->setMax( getSwapTotal() / 1024 );
00355 }
00356 
00357 #include "memsensor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys