diff options
Diffstat (limited to 'cpp/src/IceGrid/PlatformInfo.cpp')
-rw-r--r-- | cpp/src/IceGrid/PlatformInfo.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/cpp/src/IceGrid/PlatformInfo.cpp b/cpp/src/IceGrid/PlatformInfo.cpp new file mode 100644 index 00000000000..347ea5f19db --- /dev/null +++ b/cpp/src/IceGrid/PlatformInfo.cpp @@ -0,0 +1,204 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2005 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceGrid/PlatformInfo.h> + +#if !defined(_WIN32) +# include <sys/utsname.h> +# if defined(__APPLE__) +# include <sys/sysctl.h> +# elif defined(__sun) +# include <sys/loadavg.h> +# elif defined(__hpux) +# include <sys/pstat.h> +# elif defined(_AIX) +# include <nlist.h> +# include <fcntl.h> +# endif +#endif + +using namespace std; +using namespace IceGrid; + +PlatformInfo::PlatformInfo() +{ + // + // Initialization of the necessary data structures to get the load average. + // +#if defined(_WIN32) + PDH_STATUS err = PdhOpenQuery(0, 0, &_query); + if(err != ERROR_SUCCESS) + { + Ice::SyscallException ex(__FILE__, __LINE__); + ex.error = err; + Ice::Warning out(_traceLevels->logger); + out << "can't open performance data query:\n" << ex; + } + err = PdhAddCounter(_query, "\\Processor(_Total)\\% Processor Time", 0, &_counter); + if(err != ERROR_SUCCESS) + { + Ice::SyscallException ex(__FILE__, __LINE__); + ex.error = err; + Ice::Warning out(_traceLevels->logger); + out << "can't add performance counter:\n" << ex; + } + _usages1.insert(_usages1.end(), 1 * 60 / 5, 0); // 1 sample every 5 seconds during 1 minutes. + _usages5.insert(_usages5.end(), 5 * 60 / 5, 0); // 1 sample every 5 seconds during 5 minutes. + _usages15.insert(_usages15.end(), 15 * 60 / 5, 0); // 1 sample every 5 seconds during 15 minutes. + _last1Total = 0; + _last5Total = 0; + _last15Total = 0; +#elif defined(_AIX) + struct nlist nl; + nl.n_name = "avenrun"; + nl.n_value = 0; + if(knlist(&nl, 1, sizeof(nl)) == 0) + { + _kmem = open("/dev/kmem", O_RDONLY); + + // + // Give up root permissions to minimize security risks, it's + // only needed to access /dev/kmem. + // + setuid(getuid()); + setgid(getgid()); + } + else + { + _kmem = -1; + } +#endif + + // + // Get the number of processors. + // +#if defined(__APPLE__) + static int ncpu[2] = { CTL_HW, HW_NCPU }; + size_t sz = sizeof(_info.nProcessors); + if(sysctl(ncpu, 2, &_info.nProcessors, &sz, 0, 0) == -1) + { + Ice::SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } +#else + _info.nProcessors = static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN)); +#endif + + // + // Get the rest of the node information. + // +#ifdef _WIN32 + _info.os = "Windows"; + _info.hostname = ""; // TODO + _info.release = ""; // TODO + _info.version = ""; // TODO + _info.machine = ""; // TODO +#else + struct utsname utsinfo; + uname(&utsinfo); + _info.os = utsinfo.sysname; + _info.hostname = utsinfo.nodename; + _info.release = utsinfo.release; + _info.version = utsinfo.version; + _info.machine = utsinfo.machine; +#endif +} + +PlatformInfo::~PlatformInfo() +{ +#ifdef _WIN32 + PdhCloseQuery(_query); +#elif defined(_AIX) + if(_kmem > 0) + { + close(_kmem); + } +#endif +} + +NodeInfo +PlatformInfo::getNodeInfo() const +{ + return _info; +} + +LoadInfo +PlatformInfo::getLoadInfo() +{ + LoadInfo info; + info.load1 = -1.0f; + info.load5 = -1.0f; + info.load15 = -1.0f; + +#if defined(_WIN32) + int usage = 100; + if(PdhCollectQueryData(_query) == ERROR_SUCCESS) + { + DWORD type; + PDH_FMT_COUNTERVALUE value; + PdhGetFormattedCounterValue(_counter, PDH_FMT_LONG, &type, &value); + usage = static_cast<int>(value.longValue); + } + + _last1Total += usage - _usages1.back(); + _last5Total += usage - _usages5.back(); + _last15Total += usage - _usages15.back(); + + _usages1.pop_back(); + _usages5.pop_back(); + _usages15.pop_back(); + _usages1.push_front(usage); + _usages5.push_front(usage); + _usages15.push_front(usage); + + info.load1 = static_cast<float>(_last1Total) / _usages1.size() / 100.0f; + info.load5 = static_cast<float>(_last5Total) / _usages5.size() / 100.0f; + info.load15 = static_cast<float>(_last15Total) / _usages15.size() / 100.0f; +#elif defined(__sun) || defined(__linux) || defined(__APPLE__) + // + // We use the load average divided by the number of + // processors to figure out if the machine is busy or + // not. The result is capped at 1.0f. + // + double loadAvg[3]; + if(getloadavg(loadAvg, 3) != -1) + { + info.load1 = static_cast<float>(loadAvg[0]); + info.load5 = static_cast<float>(loadAvg[1]); + info.load15 = static_cast<float>(loadAvg[2]); + } +#elif defined(__hpux) + struct pst_dynamic dynInfo; + if(pstat_getdynamic(&dynInfo, sizeof(dynInfo), 1, 0) >= 0) + { + info.load1 = dynInfo.psd_avg_1_min; + info.load5 = dynInfo.psd_avg_5_min; + info.load15 = dynInfo.psd_avg_15_min; + } +#elif defined(_AIX) + if(_kmem > 1) + { + long long avenrun[3]; + struct nlist nl; + nl.n_name = "avenrun"; + nl.n_value = 0; + if(knlist(&nl, 1, sizeof(nl)) == 0) + { + if(pread(_kmem, avenrun, sizeof(avenrun), nl.n_value) >= sizeof(avenrun)) + { + info.load1 = avenrun[0] / 65536.0f; + info.load5 = avenrun[1] / 65536.0f; + info.load15 = avenrun[2] / 65536.0f; + } + } + } +#endif + return info; +} |