Merge pull request #633 from crestfallnatwork/main

[fix] Made disks statvfs logic asynchronous.
This commit is contained in:
Jakob P. Liljenberg 2023-09-29 10:43:21 +02:00 committed by GitHub
commit 1f72e56c7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -29,6 +29,7 @@ tab-size = 4
#include <net/if.h> #include <net/if.h>
#include <arpa/inet.h> // for inet_ntop() #include <arpa/inet.h> // for inet_ntop()
#include <filesystem> #include <filesystem>
#include <future>
#if !(defined(STATIC_BUILD) && defined(__GLIBC__)) #if !(defined(STATIC_BUILD) && defined(__GLIBC__))
#include <pwd.h> #include <pwd.h>
@ -48,12 +49,17 @@ using std::numeric_limits;
using std::round; using std::round;
using std::streamsize; using std::streamsize;
using std::vector; using std::vector;
using std::future;
using std::async;
using std::pair;
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace rng = std::ranges; namespace rng = std::ranges;
using namespace Tools; using namespace Tools;
using namespace std::literals; // for operator""s using namespace std::literals; // for operator""s
using namespace std::chrono_literals;
//? --------------------------------------------------- FUNCTIONS ----------------------------------------------------- //? --------------------------------------------------- FUNCTIONS -----------------------------------------------------
namespace Cpu { namespace Cpu {
@ -939,6 +945,7 @@ namespace Mem {
auto only_physical = Config::getB("only_physical"); auto only_physical = Config::getB("only_physical");
auto zfs_hide_datasets = Config::getB("zfs_hide_datasets"); auto zfs_hide_datasets = Config::getB("zfs_hide_datasets");
auto& disks = mem.disks; auto& disks = mem.disks;
static unordered_flat_map<string, future<pair<disk_info, int>>> disks_stats_promises;
ifstream diskread; ifstream diskread;
vector<string> filter; vector<string> filter;
@ -1078,31 +1085,47 @@ namespace Mem {
diskread.close(); diskread.close();
//? Get disk/partition stats //? Get disk/partition stats
bool new_ignored = false; for (auto it = disks.begin(); it != disks.end(); ) {
for (auto& [mountpoint, disk] : disks) { auto &[mountpoint, disk] = *it;
if (std::error_code ec; not fs::exists(mountpoint, ec) or v_contains(ignore_list, mountpoint)) continue; if (v_contains(ignore_list, mountpoint)) {
struct statvfs vfs; it = disks.erase(it);
if (statvfs(mountpoint.c_str(), &vfs) < 0) {
Logger::warning("Failed to get disk/partition stats for mount \""+ mountpoint + "\" with statvfs error code: " + to_string(errno) + ". Ignoring...");
ignore_list.push_back(mountpoint);
new_ignored = true;
continue; continue;
} }
disk.total = vfs.f_blocks * vfs.f_frsize; if(auto promises_it = disks_stats_promises.find(mountpoint); promises_it != disks_stats_promises.end()){
disk.free = (free_priv ? vfs.f_bfree : vfs.f_bavail) * vfs.f_frsize; auto& promise = promises_it->second;
disk.used = disk.total - disk.free; if(promise.valid() &&
disk.used_percent = round((double)disk.used * 100 / disk.total); promise.wait_for(0s) == std::future_status::timeout) {
disk.free_percent = 100 - disk.used_percent; ++it;
} continue;
}
//? Remove any problematic disks added to the ignore_list auto promise_res = promises_it->second.get();
if (new_ignored) { if(promise_res.second != -1){
for (auto it = disks.begin(); it != disks.end();) { ignore_list.push_back(mountpoint);
if (v_contains(ignore_list, it->first)) Logger::warning("Failed to get disk/partition stats for mount \""+ mountpoint + "\" with statvfs error code: " + to_string(promise_res.second) + ". Ignoring...");
it = disks.erase(it); it = disks.erase(it);
else continue;
it++; }
auto &updated_stats = promise_res.first;
disk.total = updated_stats.total;
disk.free = updated_stats.free;
disk.used = updated_stats.used;
disk.used_percent = updated_stats.used_percent;
disk.free_percent = updated_stats.free_percent;
} }
disks_stats_promises[mountpoint] = async(std::launch::async, [mountpoint, &free_priv]() -> pair<disk_info, int> {
struct statvfs vfs;
disk_info disk;
if (statvfs(mountpoint.c_str(), &vfs) < 0) {
return pair{disk, errno};
}
disk.total = vfs.f_blocks * vfs.f_frsize;
disk.free = (free_priv ? vfs.f_bfree : vfs.f_bavail) * vfs.f_frsize;
disk.used = disk.total - disk.free;
disk.used_percent = round((double)disk.used * 100 / disk.total);
disk.free_percent = 100 - disk.used_percent;
return pair{disk, -1};
});
++it;
} }
//? Setup disks order in UI and add swap if enabled //? Setup disks order in UI and add swap if enabled