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