-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsystem_info.cpp
137 lines (113 loc) · 3.76 KB
/
system_info.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2019, The Jackson Laboratory, Bar Harbor, Maine - all rights reserved
#include <string>
#include <fstream>
#include <limits>
#include <sys/sysinfo.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include "system_info.h"
SysInfo::SysInfo(void)
{
Sample();
char buffer[1024];
gethostname(buffer, sizeof(buffer));
hostname_ = std::string(buffer);
// get the amount of physical RAM -- this won't change so we don't need to update
mem_total_ = system_info.totalram * system_info.mem_unit / 1024;
// get the release. We use the first line of /etc/nv_tegra_release if it is available
// and accessible, otherwise we fall back to using the Linux Kernel release string
std::ifstream release_file("/etc/nv_tegra_release");
if (release_file) {
std::getline(release_file, this->release_);
} else {
struct utsname buf;
if (uname(&buf) != 0) {
// nv_tegra_release wasn't available and we were unable to get the Kernel
// release string. Report an unknown release
this->release_ = std::string("UNKNOWN");
} else {
this->release_ = std::string(buf.release);
}
}
}
/*
* this method is intended to be called periodically to update memory available,
* disk available, system load, etc
*/
void SysInfo::Sample(void)
{
sysinfo(&system_info);
UpdateMemInfo();
// convert the integer value sysinfo gives us to the floating point number we expect
load_ = system_info.loads[0] / (float)(1 << SI_LOAD_SHIFT);
// update disk information
for(auto m : mount_points) {
struct statvfs buf;
DiskInfo di;
if (statvfs(m.c_str(), &buf) == 0) {
di.capacity = BlocksToMb(buf.f_blocks, buf.f_frsize);
di.available = BlocksToMb(buf.f_bavail, buf.f_bsize);
} else {
// TODO handle the error case. for now we just return zero for capacity/available
di.capacity = 0;
di.available = 0;
}
disk_information[m] = di;
}
}
/*
* This method uses /proc/meminfo to get an updated view of memory usage. This is more
* accurate than using the information returned by sysinfo, because Linux will use
* free memory for disk caching. To sysinfo this appears to be used, but the kernel will
* free it as soon as it is needed by another program so it should be included in the
* reported available memory.
*/
void SysInfo::UpdateMemInfo()
{
std::string token;
std::ifstream file("/proc/meminfo");
mem_available_ = 0;
while(file >> token) {
if(token == "MemAvailable:") {
unsigned long mem;
if(file >> mem) {
mem_available_ = mem;
}
}
// ignore rest of the line
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
void SysInfo::AddMount(std::string mount)
{
// TODO check that mount point exists before registering, otherwise throw exception
mount_points.insert(mount);
}
void SysInfo::ClearMounts()
{
mount_points.clear();
disk_information.clear();
}
std::vector<std::string> SysInfo::registered_mounts()
{
// return a vector instead of the set we're using internally
std::vector<std::string> v(mount_points.begin(), mount_points.end());
return v;
}
DiskInfo SysInfo::disk_info(const std::string mount)
{
DiskInfo di;
auto it = disk_information.find(mount);
assert(it != disk_information.end());
di.capacity = it->second.capacity;
di.available = it->second.available;
return di;
}
unsigned long SysInfo::BlocksToMb(fsblkcnt_t blocks, unsigned long bsize)
{
// convert number of filesystem blocks into a size in mB
return blocks * bsize / (1048576);
}