common/util: use ifstream to read from /proc files

refactor `collect_sys_info()` to use ifstream, getline and boost string
helpers to read and parse the /proc/meminfo and /proc/cpuinfo. for
better readability, and it's less error-prone.

Related-To: https://tracker.ceph.com/issues/43306
Signed-off-by: Kefu Chai <kchai@redhat.com>
This commit is contained in:
Kefu Chai 2020-01-14 16:47:41 +08:00
parent b127d6d32e
commit ecddb1dd24

View File

@ -13,7 +13,8 @@
*/
#include <sys/utsname.h>
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include "include/compat.h"
#include "include/util.h"
@ -240,53 +241,41 @@ void collect_sys_info(map<string, string> *m, CephContext *cct)
}
#else
// memory
FILE *f = fopen(PROCPREFIX "/proc/meminfo", "r");
if (f) {
char buf[100];
while (!feof(f)) {
char *line = fgets(buf, sizeof(buf), f);
if (!line)
break;
char key[40];
long long value;
int r = sscanf(line, "%39s %lld", key, &value);
if (r == 2) {
if (strcmp(key, "MemTotal:") == 0)
(*m)["mem_total_kb"] = boost::lexical_cast<string>(value);
else if (strcmp(key, "SwapTotal:") == 0)
(*m)["mem_swap_kb"] = boost::lexical_cast<string>(value);
if (std::ifstream f{PROCPREFIX "/proc/meminfo"}; !f.fail()) {
for (std::string line; std::getline(f, line); ) {
std::vector<string> parts;
boost::split(parts, line, boost::is_any_of(":\t "), boost::token_compress_on);
if (parts.size() != 3) {
continue;
}
if (parts[0] == "MemTotal") {
(*m)["mem_total_kb"] = parts[1];
} else if (parts[0] == "SwapTotal") {
(*m)["mem_swap_kb"] = parts[1];
}
}
fclose(f);
}
uint64_t cgroup_limit;
if (get_cgroup_memory_limit(&cgroup_limit) == 0 &&
cgroup_limit > 0) {
(*m)["mem_cgroup_limit"] = boost::lexical_cast<string>(cgroup_limit);
(*m)["mem_cgroup_limit"] = std::to_string(cgroup_limit);
}
// processor
f = fopen(PROCPREFIX "/proc/cpuinfo", "r");
if (f) {
char buf[1024];
while (!feof(f)) {
char *line = fgets(buf, sizeof(buf), f);
if (!line)
break;
if (strncmp(line, "model name", 10) == 0) {
char *c = strchr(buf, ':');
c++;
while (*c == ' ')
++c;
char *nl = c;
while (*nl != '\n')
++nl;
*nl = '\0';
(*m)["cpu"] = c;
if (std::ifstream f{PROCPREFIX "/proc/cpuinfo"}; !f.fail()) {
for (std::string line; std::getline(f, line); ) {
std::vector<string> parts;
boost::split(parts, line, boost::is_any_of(":"));
if (parts.size() != 2) {
continue;
}
boost::trim(parts[0]);
boost::trim(parts[1]);
if (parts[0] == "model name") {
(*m)["cpu"] = parts[1];
break;
}
}
fclose(f);
}
#endif
// distro info