/*************************************************************************** * Copyright (C) 2003 by Hans Karlsson * * karlsson.h@home.se * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "memsensor.h" #include #include #include #include #include #ifdef Q_OS_FREEBSD #include #include #include #include #include #include #include #include #endif #if defined(Q_OS_NETBSD) #include #include #include #include #include #endif #include #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) /* define pagetok in terms of pageshift */ #define pagetok(size) ((size) << pageshift) #endif MemSensor::MemSensor(int msec) : Sensor(msec) { #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) /* get the page size with "getpagesize" and calculate pageshift from it */ int pagesize = getpagesize(); pageshift = 0; while (pagesize > 1) { pageshift++; pagesize >>= 1; } /* we only need the amount of log(2)1024 for our conversion */ pageshift -= 10; # if defined(Q_OS_FREEBSD) && defined(__FreeBSD_version) && __FreeBSD_version >= 500018 kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open"); # elif defined Q_OS_FREEBSD connect(&ksp, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int )), this,TQ_SLOT(receivedStdout(TDEProcess *, char *, int ))); connect(&ksp, TQ_SIGNAL(processExited(TDEProcess *)), this,TQ_SLOT(processExited( TDEProcess * ))); swapTotal = swapUsed = 0; MaxSet = false; readValues(); # endif #else readValues(); #endif } MemSensor::~MemSensor() {} #ifdef Q_OS_FREEBSD void MemSensor::receivedStdout(TDEProcess *, char *buffer, int len ) { buffer[len] = 0; sensorResult += TQString( TQCString(buffer) ); } #else void MemSensor::receivedStdout(TDEProcess *, char *, int) { } #endif void MemSensor::processExited(TDEProcess *) { #ifdef Q_OS_FREEBSD TQStringList stringList = TQStringList::split('\n',sensorResult); sensorResult = ""; TQStringList itemsList = TQStringList::split(' ', stringList[1]); swapUsed = itemsList[2].toInt(); swapTotal = itemsList[1].toInt(); #endif } int MemSensor::getMemTotal() { #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) static int mem = 0; size_t size = sizeof(mem); sysctlbyname("hw.physmem", &mem, &size, NULL, 0); return (mem / 1024); #else TQRegExp rx( "MemTotal:\\s*(\\d+)" ); rx.search( meminfo ); return ( rx.cap(1).toInt() ); #endif } int MemSensor::getMemFree() { #ifdef Q_OS_FREEBSD static int mem = 0; size_t size = sizeof(mem); sysctlbyname("vm.stats.vm.v_free_count", &mem, &size, NULL, 0); return (pagetok(mem)); #elif defined(Q_OS_NETBSD) struct uvmexp_sysctl uvmexp; int mib[2]; size_t ssize; mib[0] = CTL_VM; mib[1] = VM_UVMEXP2; ssize = sizeof(uvmexp); sysctl(mib,2,&uvmexp,&ssize,NULL,0); return pagetok(uvmexp.free); #else TQRegExp rx( "MemFree:\\s*(\\d+)" ); rx.search( meminfo ); return ( rx.cap(1).toInt() ); #endif } int MemSensor::getBuffers() { #ifdef Q_OS_FREEBSD static int mem = 0; size_t size = sizeof(mem); sysctlbyname("vfs.bufspace", &mem, &size, NULL, 0); return (mem / 1024); #elif defined(Q_OS_NETBSD) static int buf_mem = 0; size_t size = sizeof(buf_mem); sysctlbyname("vm.bufmem", &buf_mem, &size, NULL, 0); return (buf_mem / 1024); #else TQRegExp rx( "Buffers:\\s*(\\d+)" ); rx.search( meminfo ); return ( rx.cap(1).toInt() ); #endif } int MemSensor::getCached() { #ifdef Q_OS_FREEBSD static int mem = 0; size_t size = sizeof(mem); sysctlbyname("vm.stats.vm.v_cache_count", &mem, &size, NULL, 0); return (pagetok(mem)); #elif defined(Q_OS_NETBSD) return 0; #else TQRegExp rx1( "Cached:\\s*(\\d+)" ); TQRegExp rx2( "SwapCached:\\s*(\\d+)" ); rx1.search( meminfo ); rx2.search( meminfo ); return ( rx1.cap(1).toInt() + rx2.cap(1).toInt() ); #endif } int MemSensor::getSwapTotal() { #ifdef Q_OS_FREEBSD # if defined(__FreeBSD_version) && __FreeBSD_version >= 500018 int n = -1; int pagesize = getpagesize(); int retavail = 0; if (kd != NULL) n = kvm_getswapinfo(kd, &swapinfo, 1, 0); if (n < 0 || swapinfo.ksw_total == 0) return(0); retavail = swapinfo.ksw_total * pagesize / 1024; return(retavail); #else return(swapTotal); # endif #elif defined(Q_OS_NETBSD) struct uvmexp_sysctl uvmexp; int STotal = 0; int pagesize = 1; int mib[2]; size_t ssize; mib[0] = CTL_VM; mib[1] = VM_UVMEXP; ssize = sizeof(uvmexp); if (sysctl(mib, 2, &uvmexp, &ssize, NULL, 0) != -1) { pagesize = uvmexp.pagesize; STotal = (pagesize*uvmexp.swpages) >> 10; } return STotal; #else TQRegExp rx( "SwapTotal:\\s*(\\d+)" ); rx.search( meminfo ); return ( rx.cap(1).toInt() ); #endif } int MemSensor::getSwapFree() { #ifdef Q_OS_FREEBSD # if defined(__FreeBSD_version) && __FreeBSD_version >= 500018 int n = -1; int pagesize = getpagesize(); int retfree = 0; if (kd != NULL) n = kvm_getswapinfo(kd, &swapinfo, 1, 0); if (n < 0 || swapinfo.ksw_total == 0) return(0); retfree = (swapinfo.ksw_total - swapinfo.ksw_used) * pagesize / 1024; return(retfree); # else return(swapTotal - swapUsed); # endif #elif defined(Q_OS_NETBSD) struct uvmexp_sysctl uvmexp; int STotal = 0; int SFree = 0; int SUsed = 0; int pagesize = 1; int mib[2]; size_t ssize; mib[0] = CTL_VM; mib[1] = VM_UVMEXP; ssize = sizeof(uvmexp); if (sysctl(mib,2,&uvmexp,&ssize,NULL,0) != -1) { pagesize = uvmexp.pagesize; STotal = (pagesize*uvmexp.swpages) >> 10; SUsed = (pagesize*uvmexp.swpginuse) >> 10; SFree = STotal - SUsed; } return SFree; #else TQRegExp rx( "SwapFree:\\s*(\\d+)" ); rx.search( meminfo ); return ( rx.cap(1).toInt() ); #endif } void MemSensor::readValues() { #if defined Q_OS_FREEBSD || defined(Q_OS_NETBSD) # if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) ksp.clearArguments(); ksp << "swapinfo"; ksp.start( TDEProcess::NotifyOnExit,KProcIO::Stdout); # endif #else TQFile file("/proc/meminfo"); TQString line; if ( file.open(IO_ReadOnly | IO_Translate) ) { TQTextStream t( &file ); // use a text stream meminfo = t.read(); file.close(); } #endif } #define SUB_FORMAT_STR(fstring, value) \ format.replace(TQRegExp(#fstring, false), TQString::number((int)(value))) void MemSensor::update() { readValues(); TQString format; SensorParams *sp; Meter *meter; TQObjectListIt it( *objList ); #if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) bool set = false; #endif int totalMem = getMemTotal(); int usedMem = totalMem - getMemFree(); int usedMemNoBuffers = usedMem - getBuffers() - getCached(); int totalSwap = getSwapTotal(); int usedSwap = totalSwap - getSwapFree(); while (it != 0) { sp = (SensorParams*)(*it); #if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) if ( (!MaxSet) && (totalSwap > 0) ) { setMaxValue(sp); bool set = true; } #endif meter = sp->getMeter(); format = sp->getParam("FORMAT"); if (format.length() == 0 ) { format = "%um"; } SUB_FORMAT_STR(%fmbp, (totalMem - usedMemNoBuffers) * 100.0 / totalMem); SUB_FORMAT_STR(%fmbg, (totalMem - usedMemNoBuffers) / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%fmb, (totalMem - usedMemNoBuffers) / 1024.0 + 0.5); SUB_FORMAT_STR(%fmp, (totalMem - usedMem) * 100.0 / totalMem); SUB_FORMAT_STR(%fmg, (totalMem - usedMem) / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%fm, (totalMem - usedMem) / 1024.0 + 0.5); SUB_FORMAT_STR(%umbp, usedMemNoBuffers * 100.0 / totalMem); SUB_FORMAT_STR(%umbg, usedMemNoBuffers / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%umb, usedMemNoBuffers / 1024.0 + 0.5); SUB_FORMAT_STR(%ump, usedMem * 100.0 / totalMem); SUB_FORMAT_STR(%umg, usedMem / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%um, usedMem / 1024.0 + 0.5); SUB_FORMAT_STR(%tmg, totalMem / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%tm, totalMem / 1024.0 + 0.5); SUB_FORMAT_STR(%fsp, (totalSwap - usedSwap) * 100.0 / totalSwap); SUB_FORMAT_STR(%fsg, (totalSwap - usedSwap) / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%fs, (totalSwap - usedSwap) / 1024.0 + 0.5); SUB_FORMAT_STR(%usp, usedSwap * 100.0 / totalSwap); SUB_FORMAT_STR(%usg, usedSwap / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%us, usedSwap / 1024.0 + 0.5); SUB_FORMAT_STR(%tsg, totalSwap / 1024.0 / 1024.0 + 1); SUB_FORMAT_STR(%ts, totalSwap / 1024.0 + 0.5); meter->setValue(format); ++it; } #if defined(Q_OS_FREEBSD) && !(defined(__FreeBSD_version) && __FreeBSD_version >= 500018) if (set) { MaxSet = true; } #endif } #undef SUB_FORMAT_STR void MemSensor::setMaxValue( SensorParams *sp ) { Meter *meter; meter = sp->getMeter(); TQString f; f = sp->getParam("FORMAT"); if (f.length() == 0 ) { f = "%um"; } else if (f.endsWith("p")) { meter->setMax(100); } else if (f == "%fm" || f == "%um" || f == "%fmb" || f == "%umb") { meter->setMax(getMemTotal() / 1024); } else if (f == "%fmg" || f == "%umg" || f == "%fmbg" || f == "%umbg") { meter->setMax(getMemTotal() / 1024 / 1024); } else if (f == "%fs" || f == "%us" || f == "%fsg" || f == "%usg") { meter->setMax(getSwapTotal() / 1024); } } #include "memsensor.moc"