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 <tqfile.h> 00012 #include <tqglobal.h> 00013 #include <tqtextstream.h> 00014 #include <tqstring.h> 00015 #include <tqregexp.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, TQT_SIGNAL(receivedStdout(KProcess *, char *, int )), 00060 this,TQT_SLOT(receivedStdout(KProcess *, char *, int ))); 00061 connect(&ksp, TQT_SIGNAL(processExited(KProcess *)), 00062 this,TQT_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 += TQString( TQCString(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 TQStringList stringList = TQStringList::split('\n',sensorResult); 00094 sensorResult = ""; 00095 TQStringList itemsList = TQStringList::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 TQRegExp 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 TQRegExp 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 TQRegExp 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 TQRegExp rx1( "Cached:\\s*(\\d+)" ); 00174 TQRegExp 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 TQRegExp 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 TQRegExp 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 TQFile file("/proc/meminfo"); 00279 TQString line; 00280 if ( file.open(IO_ReadOnly | IO_Translate) ) 00281 { 00282 TQTextStream 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 TQString format; 00293 SensorParams *sp; 00294 Meter *meter; 00295 TQObjectListIt 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( TQRegExp("%fmb", false), TQString::number( (int)(( totalMem - usedMemNoBuffers)/1024.0+0.5))); 00322 format.replace( TQRegExp("%fm", false), TQString::number( (int)( ( totalMem - usedMem )/1024.0+0.5) )); 00323 00324 format.replace( TQRegExp("%umb", false), TQString::number( (int)((usedMemNoBuffers)/1024.0+0.5))); 00325 format.replace( TQRegExp("%um", false), TQString::number( (int)((usedMem)/1024.0+0.5 ))); 00326 00327 format.replace( TQRegExp("%tm", false), TQString::number( (int)( (totalMem)/1024.0+0.5))); 00328 00329 format.replace( TQRegExp("%fs", false), TQString::number( (int)((totalSwap - usedSwap)/1024.0+0.5))); 00330 format.replace( TQRegExp("%us", false), TQString::number( (int)(usedSwap/1024.0+0.5))); 00331 format.replace( TQRegExp("%ts", false), TQString::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 TQString 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"