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