Skip to content

Commit

Permalink
Add cgroup controllers parser
Browse files Browse the repository at this point in the history
  • Loading branch information
dtrugman committed Jul 12, 2021
1 parent 5586e04 commit 77acf9c
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/pfs/parsers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ std::pair<std::string, bool> parse_filesystems_line(const std::string& line);
std::pair<std::string, size_t> parse_meminfo_line(const std::string& line);

zone parse_buddyinfo_line(const std::string& line);
cgroup_controller parse_cgroup_controller_line(const std::string& line);
load_average parse_loadavg_line(const std::string& line);
uptime parse_uptime_line(const std::string& line);
module parse_modules_line(const std::string& line);
Expand Down
2 changes: 2 additions & 0 deletions include/pfs/procfs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class procfs final
public: // System API
std::vector<zone> get_buddyinfo() const;

std::vector<cgroup_controller> get_cgroups() const;

std::string get_cmdline() const;

std::unordered_map<std::string, bool> get_filesystems() const;
Expand Down
8 changes: 8 additions & 0 deletions include/pfs/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,14 @@ struct netlink_socket
}
};

struct cgroup_controller
{
std::string subsys_name;
unsigned hierarchy;
unsigned num_cgroups;
bool enabled;
};

} // namespace pfs

#endif // PFS_TYPES_HPP
3 changes: 3 additions & 0 deletions sample/enum_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ int enum_system(std::vector<std::string>&& args)

auto version_signature = pfs.get_version_signature();
print(version_signature);

auto controllers = pfs.get_cgroups();
print(controllers);
}
catch (const std::runtime_error& ex)
{
Expand Down
11 changes: 11 additions & 0 deletions sample/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,14 @@ inline std::ostream& operator<<(std::ostream& out, const pfs::fd& fd)
out << "target[" << fd.get_target() << "] ";
return out;
}

inline std::ostream& operator<<(std::ostream& out,
const pfs::cgroup_controller& controller)
{
out << std::boolalpha;
out << "subsys_name[" << controller.subsys_name << "] ";
out << "hierarchy[" << controller.hierarchy << "] ";
out << "num_cgroups[" << controller.num_cgroups << "] ";
out << "enabled[" << controller.enabled << "] ";
return out;
}
102 changes: 102 additions & 0 deletions src/parsers/cgroup_controller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2020-present Daniel Trugman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "pfs/parsers.hpp"
#include "pfs/utils.hpp"

namespace pfs {
namespace impl {
namespace parsers {

cgroup_controller parse_cgroup_controller_line(const std::string& line)
{
// Some examples:
// clang-format off
// #subsys_name hierarchy num_cgroups enabled
// cpuset 6 1 1
// cpu 5 33 1
// cpuacct 5 33 1
// blkio 7 33 1
// memory 8 76 1
// devices 12 33 1
// freezer 3 1 1
// net_cls 2 1 1
// perf_event 11 1 1
// net_prio 2 1 1
// hugetlb 10 1 1
// pids 4 38 1
// rdma 9 1 1
// clang-format on

enum token
{
SUBSYS_NAME = 0,
HIERARCHY = 1,
NUM_CGROUPS = 2,
ENABLED = 3,
COUNT
};

static const char DELIM = '\t';

auto tokens = utils::split(line, DELIM);
if (tokens.size() != COUNT)
{
throw parser_error(
"Corrupted cgroup controller line - Unexpected tokens count", line);
}

try
{
cgroup_controller controller;

controller.subsys_name = tokens[SUBSYS_NAME];

utils::stot(tokens[HIERARCHY], controller.hierarchy);

utils::stot(tokens[NUM_CGROUPS], controller.num_cgroups);

if (tokens[ENABLED] == "0")
{
controller.enabled = false;
}
else if (tokens[ENABLED] == "1")
{
controller.enabled = true;
}
else
{
throw parser_error(
"Corrupted cgroup controller line - Unexpected enabled value",
tokens[ENABLED]);
}

return controller;
}
catch (const std::invalid_argument& ex)
{
throw parser_error("Corrupted cgroup controller - Invalid argument",
line);
}
catch (const std::out_of_range& ex)
{
throw parser_error("Corrupted cgroup controller - Out of range", line);
}
}

} // namespace parsers
} // namespace impl
} // namespace pfs
13 changes: 13 additions & 0 deletions src/procfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ std::vector<zone> procfs::get_buddyinfo() const
return output;
}

std::vector<cgroup_controller> procfs::get_cgroups() const
{
static const size_t HEADER_LINES = 1;

static const std::string CGROUPS_FILE("cgroups");
auto path = _root + CGROUPS_FILE;

std::vector<cgroup_controller> output;
parsers::parse_lines(path, std::back_inserter(output),
parsers::parse_cgroup_controller_line, HEADER_LINES);
return output;
}

std::string procfs::get_cmdline() const
{
static const std::string CMDLINE_FILE("cmdline");
Expand Down
49 changes: 49 additions & 0 deletions test/cgroup_controller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include <sstream>

#include "catch.hpp"
#include "test_utils.hpp"

#include "pfs/parsers.hpp"

using namespace pfs::impl::parsers;

TEST_CASE("Parse corrupted cgroup controller", "[procfs][cgroup]")
{
// Missing last token (enabled)
std::string line = "devices 12 33";

REQUIRE_THROWS_AS(parse_cgroup_controller_line(line), pfs::parser_error);
}

TEST_CASE("Parse cgroup controller", "[procfs][cgroup]")
{
pfs::cgroup_controller expected;

SECTION("Enabled")
{
expected.subsys_name = "perf_event";
expected.hierarchy = 11;
expected.num_cgroups = 1;
expected.enabled = true;
}

SECTION("Disabled")
{
expected.subsys_name = "hugetlb";
expected.hierarchy = 0;
expected.num_cgroups = 1;
expected.enabled = false;
}

std::ostringstream line;
line << expected.subsys_name << '\t';
line << expected.hierarchy << '\t';
line << expected.num_cgroups << '\t';
line << (expected.enabled ? '1' : '0');

auto controller = parse_cgroup_controller_line(line.str());
REQUIRE(controller.subsys_name == expected.subsys_name);
REQUIRE(controller.hierarchy == expected.hierarchy);
REQUIRE(controller.num_cgroups == expected.num_cgroups);
REQUIRE(controller.enabled == expected.enabled);
}

0 comments on commit 77acf9c

Please sign in to comment.