@@ 7,6 7,7 @@
#include <filesystem>
#include <vector>
+#include <cassert>
#include <cstring>
#include <dirent.h>
@@ 69,6 70,7 @@ struct process_lookup_error: public std::runtime_error {
struct config {
fs::path dump_path{ "/var/lib/prelockdpp/dump.json" };
time_t interval_sec{ 5 };
+ bool lock_only_critical{ 0 };
};
struct sc_info {
@@ 135,6 137,7 @@ struct context {
config& cfg;
std::vector<int> pids;
+ std::string stat_buffer;
context(config& cfg): cfg{ cfg } {
start_time = std::chrono::steady_clock::now();
@@ 160,6 163,13 @@ struct context {
throw std::runtime_error{ concat("mlockall failed ", errno_) };
}
}
+ auto get_clock_time(clockid_t id) {
+ timespec t;
+ if (clock_gettime(id, &t)) {
+ throw errno_exception("ctx.get_clock_time failed", errno);
+ }
+ return t;
+ }
auto get_uptime() {
int fd = open("/proc/uptime", O_RDONLY);
if (fd == -1) {
@@ 231,9 241,28 @@ struct context {
}
return pids;
}
- auto get_uniq_id(int pid) {
+ void format_path_buf(auto & buf) {
+
+ }
+ auto get_uniq_id(const char* stat_path) {
+ using namespace std::string_view_literals;
try {
- throw std::runtime_error{ "Unimplemented" };
+ // TODO: can we do reading stat cheaper?
+ std::ifstream stat{ stat_path };
+ std::getline(stat, stat_buffer);
+
+ std::string_view stat_view{ stat_buffer };
+ if (stat_view.ends_with(" 0 0 0")) {
+ // ignore kthreads
+ return 0;
+ }
+ auto lparen_idx = stat_view.find('(');
+ auto rparen_idx = stat_view.rfind(')');
+ assert(lparen_idx != stat_view.npos && rparen_idx != stat_view.npos);
+ auto comm = stat_view.substr(lparen_idx + 1, rparen_idx - lparen_idx - 1);
+ std::cout << comm;
+
+ return 0;
} catch (const file_not_found_error&) {
return -1;
} catch (const process_lookup_error&) {
@@ 241,17 270,63 @@ struct context {
}
}
auto get_current_set() {
- timespec m0, p0;
- if (clock_gettime(CLOCK_MONOTONIC, &m0)) {
- throw errno_exception("clock_gettime(MONOTONIC) failed", errno);
+ using namespace std::string_view_literals;
+
+ auto m0 = get_clock_time(CLOCK_MONOTONIC);
+ auto p0 = get_clock_time(CLOCK_PROCESS_CPUTIME_ID);
+ auto uptime = get_uptime();
+
+ // FIXME: move to separate function
+ constexpr auto proc_path = "/proc/"sv;
+ constexpr auto stat_path = "/stat"sv;
+
+ constexpr auto buf_size
+ = proc_path.size()
+ + std::numeric_limits<int>::digits10
+ + stat_path.size()
+ + 2;
+
+ char path_buf[buf_size];
+ auto const pid_begin = std::copy(
+ proc_path.begin(),
+ proc_path.end(),
+ std::begin(path_buf)
+ );
+
+
+ DIR* proc_dir = opendir("/proc");
+ if (!proc_dir) {
+ throw errno_exception("opendir(/proc) failed", errno);
}
- if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &p0)) {
- throw errno_exception("clock_gettime(PROCESS_CPUTIME) failed", errno);
+ DEFER{ closedir(proc_dir); };
+ errno = 0;
+ while (dirent* entry = readdir(proc_dir)) {
+ DEFER{ errno = 0; };
+
+ if (entry->d_type != DT_DIR) {
+ continue;
+ }
+ auto name_end = entry->d_name + strlen(entry->d_name);
+ int pid;
+ auto [p, ec] = std::from_chars(entry->d_name, name_end, pid);
+ if (ec != std::errc() || p != name_end) {
+ continue;
+ }
+
+ auto const pid_end = std::copy(entry->d_name, name_end, pid_begin);
+ auto end = std::copy(stat_path.begin(), stat_path.end(), pid_end);
+ assert(end < std::end(path_buf));
+ *end = '\0';
+ ++end;
+
+ std::cout << pid << ' ';
+ get_uniq_id(path_buf);
+ std::cout << '\n';
}
- auto uptime = get_uptime();
- for (auto&& pid: get_pid_list()) {
- std::cout << pid << '\n';
+ if (errno) {
+ throw errno_exception("readdir(proc) failed", errno);
}
+
std::cout << "Uptime: " << uptime.tv_sec << '.' << uptime.tv_nsec << '\n';
}
@@ 259,6 334,7 @@ struct context {
struct lock_context {
int epoll_fd;
+ // FIXME: should we keep it?
epoll_event timer_event = { 0 };
epoll_event signal_event = { 0 };