00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef CASA_HOSTINFOLINUX_H
00026 #define CASA_HOSTINFOLINUX_H
00027
00028 # if defined(HOSTINFO_DO_IMPLEMENT)
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef _GNU_SOURCE
00040 #define _GNU_SOURCE
00041 #endif
00042 #include <sched.h>
00043 #include <string.h>
00044 #include <ctype.h>
00045 #include <sys/types.h>
00046 #include <sys/stat.h>
00047 #include <sys/vfs.h>
00048 #include <unistd.h>
00049 #include <fcntl.h>
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <fstream>
00053 #include <iostream>
00054 #include <string>
00055 #include <sstream>
00056 #include <vector>
00057 #include <limits>
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #if 0
00080 #include <linux/proc_fs.h>
00081 #else
00082 #define PROC_SUPER_MAGIC 0x9fa0
00083 #endif
00084
00085 #define PROCFS "/proc"
00086 #define CPUINFO "/proc/cpuinfo"
00087 #define MEMINFO "/proc/meminfo"
00088
00089 #define bytetok(x) (((x) + 512) >> 10)
00090
00091 namespace casacore {
00092
00093 class HostMachineInfo {
00094 friend class HostInfo;
00095
00096 HostMachineInfo( );
00097 void update_info( );
00098
00099 int valid;
00100 int cpus;
00101
00102 ptrdiff_t memory_total;
00103 ptrdiff_t memory_used;
00104 ptrdiff_t memory_free;
00105
00106 ptrdiff_t swap_total;
00107 ptrdiff_t swap_used;
00108 ptrdiff_t swap_free;
00109 };
00110
00111
00112
00113
00114 static inline char *
00115 skip_ws(const char *p)
00116 {
00117 while (isspace(*p)) p++;
00118 return (char *)p;
00119 }
00120
00121 static inline char *
00122 skip_token(const char *p)
00123 {
00124 while (isspace(*p)) p++;
00125 while (*p && !isspace(*p)) p++;
00126 return (char *)p;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 static inline size_t
00136 get_cgroup_limit(std::string group, std::string value, std::string sub_value="")
00137 {
00138 size_t result = std::numeric_limits<size_t>::max();
00139
00140 const std::string cgroup = std::string("/sys/fs/cgroup/") + group + "/";
00141
00142
00143 std::string line;
00144 std::ifstream ifs("/proc/self/cgroup", std::ifstream::in);
00145 std::string hierarchy;
00146 while (getline(ifs, line)) {
00147 std::stringstream ss(line);
00148 std::string token;
00149 std::vector<std::string> fields;
00150 while (getline(ss, token, ':')) {
00151 fields.push_back(token);
00152 }
00153 if (fields.size() % 3 != 0) {
00154 return result;
00155 }
00156 for (std::vector<std::string>::size_type i=1; i < fields.size(); i+=3) {
00157 if (fields[i].find(group) != std::string::npos) {
00158 hierarchy = fields[i + 1] + "/";
00159 }
00160 }
00161 }
00162 if (hierarchy.size() == 0) {
00163 return result;
00164 }
00165
00166 std::ifstream flimit((cgroup + hierarchy + value).c_str(), std::ifstream::in);
00167
00168 if (!flimit.is_open()) {
00169 flimit.open((cgroup + value).c_str(), std::ifstream::in);
00170 }
00171 if (flimit.is_open()) {
00172 if (!sub_value.empty()) {
00173
00174 while (getline(flimit, line)) {
00175 std::stringstream ss(line);
00176 std::string token;
00177 ss >> token;
00178 if (token == sub_value) {
00179 ss >> result;
00180 break;
00181 }
00182 }
00183 }
00184 else {
00185 flimit >> result;
00186 }
00187 }
00188 return result;
00189 }
00190
00191 HostMachineInfo::HostMachineInfo( ) : valid(1)
00192 {
00193 char buffer[4096+1];
00194 char *p;
00195
00196
00197 cpu_set_t cpuset;
00198 if (sched_getaffinity(0, sizeof(cpuset), &cpuset) == 0) {
00199 # ifdef CPU_COUNT
00200 cpus = CPU_COUNT(&cpuset);
00201 # else
00202 for (int i = 0; i < CPU_SETSIZE; i++) {
00203 if (CPU_ISSET(i, &cpuset)) {
00204 cpus++;
00205 }
00206 }
00207 # endif
00208 }
00209 else {
00210 #ifndef AIPS_CRAY_PGI
00211
00212 {
00213 struct statfs sb;
00214 if (statfs(PROCFS, &sb) < 0 || sb.f_type != PROC_SUPER_MAGIC)
00215 {
00216 fprintf( stderr, "proc filesystem not mounted on " PROCFS "\n" );
00217 valid = 0;
00218 return;
00219 }
00220 }
00221 #endif
00222
00223
00224 {
00225 cpus = 0;
00226 FILE *fptr = fopen(CPUINFO, "r");
00227 while ( (p = fgets( buffer, sizeof(buffer), fptr )) ) {
00228 if ( ! strncmp( p, "processor", 9 ) ) ++cpus;
00229 }
00230 fclose(fptr);
00231 }
00232 }
00233
00234 update_info();
00235 }
00236
00237 void HostMachineInfo::update_info( )
00238 {
00239 char buffer[4096+1];
00240 int fd, len;
00241
00242
00243 {
00244 char *p;
00245 int ret;
00246 unsigned long mem_total, mem_free, mem_cached, swp_total, swp_free;
00247
00248 fd = open(MEMINFO, O_RDONLY);
00249 len = read(fd, buffer, sizeof(buffer)-1);
00250 close(fd);
00251 buffer[len] = '\0';
00252
00253 p = strstr(buffer, "MemTotal:");
00254
00255 if ((ret = sscanf (p,"MemTotal: %lu kB\nMemFree: %lu kB\n",
00256 &mem_total, &mem_free)) != 2)
00257 cerr << "Error parsing MemTotal and MemFree in /proc/meminfo\n";
00258
00259 p = strstr (buffer, "Cached:");
00260 if ((ret = sscanf (p,"Cached: %lu kB\n", &mem_cached)) != 1)
00261 cerr << "Error parsing Cached in /proc/meminfo\n";
00262
00263
00264 size_t mem_max = get_cgroup_limit("memory", "memory.limit_in_bytes") / 1024;
00265 size_t mem_used = get_cgroup_limit("memory", "memory.stat", "total_rss") / 1024;
00266 memory_total = std::min((size_t)mem_total, mem_max);
00267
00268 if (mem_used != std::numeric_limits<size_t>::max() / 1024 &&
00269 mem_max != std::numeric_limits<size_t>::max() / 1024) {
00270 memory_free = mem_max - mem_used;
00271 }
00272 else {
00273 memory_free = (size_t)(mem_free + mem_cached);
00274 }
00275 memory_used = memory_total - memory_free;
00276
00277 p = strstr (buffer, "SwapTotal:");
00278 if ((ret = sscanf (p, "SwapTotal: %lu kB\nSwapFree: %lu kB\n",
00279 &swp_total, &swp_free)) != 2)
00280 cerr << "Error parsing SwapTotal and SwapFree in /proc/meminfo\n";
00281
00282
00283 size_t swp_max = get_cgroup_limit("memory", "memory.memsw.limit_in_bytes") / 1024;
00284 size_t swp_used = get_cgroup_limit("memory", "memory.stat", "total_swap") / 1024;
00285
00286 if (mem_max != std::numeric_limits<size_t>::max() / 1024) {
00287 swap_total = std::min((size_t)swp_total, swp_max - mem_max);
00288 }
00289 else {
00290 swap_total = swp_total;
00291 }
00292 if (swp_used != std::numeric_limits<size_t>::max() / 1024 &&
00293 swp_max != std::numeric_limits<size_t>::max() / 1024) {
00294 swap_free = swp_max - swp_used;
00295 }
00296 else {
00297 swap_free = swp_free;
00298 }
00299 swap_used = swap_total-swap_free;
00300
00301
00302 }
00303 }
00304
00305 }
00306
00307 # endif
00308
00309 #endif