diff --git a/debian/changelog b/debian/changelog index 46f9b7c..a6ba768 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -fancon (0.23.6) focal; urgency=low +fancon (0.23.7) hirsute; urgency=low * Initial release. Closes: #00000 diff --git a/src/Client.cpp b/src/Client.cpp index 7b10a75..ef3589d 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -49,7 +49,7 @@ void fc::Client::run(Args &args) { sysinfo(args.sysinfo.value); } else if (Util::is_atty() && !exists(args.config.value)) { // Offer test - cout << log::fmt_green << "Test devices & generate a config? (y/n): "; + cout << log::fmt_green << "Test devices & generate a config? (y/n): " << log::fmt_reset; char answer; std::cin >> answer; if (answer == 'y') { @@ -117,7 +117,7 @@ void fc::Client::status() { if (s.status() != FanStatus::FanStatus_Status_DISABLED) extras << setw(4) << s.rpm() << "rpm, " << setw(3) << s.pwm() << "pwm"; - cout << setw(longest_label) << s.label() << ": " << extras.rdbuf() << " " + cout << setw(longest_label) << s.label() << ": " << extras.rdbuf()->str() << " " << setw(longest_status) << status_text(s.status()) << endl; } } @@ -177,6 +177,10 @@ void fc::Client::test(const string &flabel, bool forced) { auto reader = client->Test(&context, req); fc_pb::TestResponse resp; while (reader->Read(&resp)) { + if (resp.status() == -1) { + LOG(llvl::error) << flabel << ": test failed"; + break; + } LOG(llvl::info) << flabel << ": " << resp.status() << "%"; } diff --git a/src/Controller.cpp b/src/Controller.cpp index 660c4e7..c0faadf 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -16,7 +16,7 @@ fc::Controller::Controller(path conf_path_) : config_path(move(conf_path_)) { fc::Controller::~Controller() { disable_all(); } FanStatus fc::Controller::status(const string &flabel) { - const lock_guard lg(tasks_mutex[flabel]); + const auto lock = lock_task_read(flabel); const auto it = tasks.find(flabel); if (it == tasks.end()) return FanStatus::FanStatus_Status_DISABLED; @@ -26,57 +26,51 @@ FanStatus fc::Controller::status(const string &flabel) { } void fc::Controller::enable(fc::FanInterface &f, bool enable_all_dell) { - tasks_mutex[f.label].lock(); - if (tasks.count(f.label) > 0) + const auto lock = lock_task_write(f.label); + if (tasks.contains(f.label) || !f.try_enable() || !f.is_configured(true)) return; // Dell fans can only be enabled/disabled togther - if (f.type() == DevType::DELL && enable_all_dell) { - tasks_mutex[f.label].unlock(); - return enable_dell_fans(); - } - - if (!f.pre_start_check()) - return; + if (f.type() == DevType::DELL && enable_all_dell) + enable_dell_fans(f.label); tasks.emplace(f.label, [this, &f](bool &run) { + LOG(llvl::trace) << f.label << ": enabled"; while (run) { notify_status_observers(f.label); f.update(); } + f.disable_control(); }); - - LOG(llvl::trace) << f.label << ": enabled"; - tasks_mutex[f.label].unlock(); } void fc::Controller::enable_all() { for (auto &[key, f] : devices.fans) { - if (!tasks.contains(f->label)) - enable(*f); + enable(*f, false); } } void fc::Controller::disable(const string &flabel, bool disable_all_dell) { - tasks_mutex[flabel].lock(); - const auto it = tasks.find(flabel); - if (it == tasks.end()) - return; + { + const auto lock = lock_task_write(flabel); + if (!tasks.contains(flabel)) + return; - // Dell fans can only be enabled/disabled togther - if (devices.fans.at(flabel)->type() == DevType::DELL && disable_all_dell) { - tasks_mutex[flabel].unlock(); - return disable_dell_fans(); + tasks.erase(flabel); } - - tasks.erase(flabel); - if (const auto fit = devices.fans.find(flabel); fit != devices.fans.end()) + if (const auto fit = devices.fans.find(flabel); fit != devices.fans.end()) { fit->second->disable_control(); + // Dell fans can only be enabled/disabled togther + if (fit->second->type() == DevType::DELL && disable_all_dell) + disable_dell_fans(flabel); + } else { + LOG(llvl::error) << flabel << ": disable failed - couldn't find"; + } + LOG(llvl::trace) << flabel << ": disabled"; notify_status_observers(flabel); - tasks_mutex[flabel].unlock(); } void fc::Controller::disable_all() { @@ -113,6 +107,7 @@ void fc::Controller::reload(bool just_started) { void fc::Controller::recover() { // Re-enable control for all running tasks for (const auto &[flabel, t] : tasks) { + const auto lock = lock_task_read(flabel); const auto it = devices.fans.find(flabel); if (it != devices.fans.end()) it->second->enable_control(); @@ -131,51 +126,66 @@ void fc::Controller::test(fc::FanInterface &fan, bool forced, bool blocking, if (fan.ignore || (fan.tested() && !forced)) return; - // If a test is already running for the device then just join onto it - if (auto it = tasks.find(fan.label); it != tasks.end() && it->second.is_testing()) { - // Add test_status observers to existing test_status - for (const auto &cb : test_status->observers) - it->second.test_status->register_observer(cb, true); - if (blocking) - it->second.join(); - return; - } - - // Remove any running thread before testing - tasks.erase(fan.label); - auto test_func = [&] { - // Test fan, then remove thread from map LOG(llvl::info) << fan << ": testing"; - fan.test(*test_status); - LOG(llvl::info) << fan << ": test complete"; - const thread t([&] { tasks.erase(fan.label); }); + const bool success = fan.test(*test_status); + // Test has completed + LOG(llvl::info) << fan << ": test " << (success ? "complete" : "failed"); { - // Only write to file when no other fan are still testing - lock_guard lg(test_mutex); - if (tests_running() == 0) - to_file(false); + const auto lock = lock_task_read(fan.label); + tasks.find(fan.label)->second.test_status.reset(); } - enable(fan); + // Only write to file when no other fan are still testing + if (tests_running() == 0) + to_file(false); + + // Remove the test thread we're on, and start another enable thread + thread([&] { + { + const auto lock = lock_task_write(fan.label); + tasks.erase(fan.label); + } + enable(fan); + }).detach(); }; - const auto[it, success] = tasks.try_emplace(fan.label, move(test_func), test_status); + // If a test is already running for the device then just join onto it + { + const auto lock = lock_task_write(fan.label); + if (auto it = tasks.find(fan.label); it != tasks.end() && it->second.is_testing()) { + // Add test_status observers to existing test_status + for (const auto &cb : test_status->observers) + it->second.test_status->register_observer(cb, true); + if (blocking) + it->second.join(); + return; + } - if (!success) - test(fan, forced, blocking, test_status); + // Remove any running thread before testing + tasks.erase(fan.label); + + const auto &[it, success] = tasks.emplace(std::piecewise_construct, std::forward_as_tuple(fan.label), + std::forward_as_tuple(move(test_func), test_status)); + if (!success) { + LOG(llvl::error) << "Failed to start test - " << fan.label; + return; + } + } notify_status_observers(fan.label); - if (blocking) + + const auto lock = lock_task_read(fan.label); + if (auto it = tasks.find(fan.label); blocking && it != tasks.end()) it->second.join(); } -size_t fc::Controller::tests_running() const { - const auto f = [](const size_t sum, const auto &p) { +size_t fc::Controller::tests_running() { + const lock_guard lg(test_mutex); + return std::accumulate(tasks.begin(), tasks.end(), 0, [](const size_t sum, const auto &p) { return sum + int(p.second.is_testing()); - }; - return std::accumulate(tasks.begin(), tasks.end(), 0, f); + }); } void fc::Controller::set_devices(const fc_pb::Devices &devices_) { @@ -187,11 +197,16 @@ void fc::Controller::set_devices(const fc_pb::Devices &devices_) { } void fc::Controller::from(const fc_pb::ControllerConfig &c) { - update_interval = milliseconds(c.update_interval()); dynamic = c.dynamic(); smoothing_intervals = c.smoothing_intervals(); top_stickiness_intervals = c.top_stickiness_intervals(); temp_averaging_intervals = c.temp_averaging_intervals(); + + if (c.update_interval() > 0) { + update_interval = milliseconds(c.update_interval()); + } else { + LOG(llvl::warning) << "Update interval must be > 0; using default"; + } } void fc::Controller::to(fc_pb::Controller &c) const { @@ -207,26 +222,28 @@ void fc::Controller::to(fc_pb::ControllerConfig &c) const { c.set_temp_averaging_intervals(temp_averaging_intervals); } -void fc::Controller::enable_dell_fans() { +void fc::Controller::enable_dell_fans(const optional except_flabel) { for (const auto &[fl, f] : devices.fans) { - if (f->type() == DevType::DELL) + if (f->type() == DevType::DELL && (!except_flabel || fl != *except_flabel)) enable(*f, false); } } -void fc::Controller::disable_dell_fans() { +void fc::Controller::disable_dell_fans(const optional except_flabel) { for (const auto &[fl, f] : devices.fans) { - if (f->type() == DevType::DELL) + if (f->type() == DevType::DELL && (!except_flabel || fl != *except_flabel)) disable(fl, false); } } -bool fc::Controller::is_testing(const string &flabel) const { +bool fc::Controller::is_testing(const string &flabel) { + const auto lock = lock_task_read(flabel); const auto it = tasks.find(flabel); return it != tasks.end() && it->second.is_testing(); } optional fc::Controller::read_config() { + const lock_guard config_lg(config_mutex); if (!exists(config_path)) return nullopt; @@ -266,6 +283,13 @@ void fc::Controller::merge(Devices &d, bool replace_on_match, bool deep_cmp) { } }; + // Ensure all Dell fans are enabled if a single one has, but let them be merged first + bool dell_fan_enabled = false; + const auto enable_fan = [&](FanInterface &fan) { + enable(fan, false); + dell_fan_enabled |= fan.type() == fc_pb::DELL; + }; + m(d.fans, devices.fans, [&](auto &old_it, const string &old_key, const string &new_key, auto &dev) { // On match; re-insert device as the key may have changed const auto re_insert = [&] { @@ -274,19 +298,31 @@ void fc::Controller::merge(Devices &d, bool replace_on_match, bool deep_cmp) { }; const FanStatus fstatus = status(old_key); if (fstatus == FanStatus::FanStatus_Status_DISABLED) { - re_insert(); + const bool previously_configured = old_it->second->is_configured(false); + auto[it, success] = re_insert(); + // Try enable if the old device was unconfigured + if (!previously_configured && it->second->is_configured(false)) + enable_fan(*it->second); + } else if (fstatus == FanStatus::FanStatus_Status_ENABLED) { disable(old_it->first, false); auto[it, success] = re_insert(); - enable(*it->second, true); + enable_fan(*it->second); + } else if (fstatus == FanStatus::FanStatus_Status_TESTING) { const auto test_status = tasks.find(old_key)->second.test_status; disable(old_key, false); auto[it, success] = re_insert(); test(*it->second, true, false, test_status); + + } else { + LOG(llvl::error) << "Unhandled fan status on merge: " << fstatus; } }); + if (dell_fan_enabled) + enable_dell_fans(); + m(d.sensors, devices.sensors, [&](auto &old_it, [[maybe_unused]] const string &old_key, const string &new_key, auto &dev) { // On match; re-insert device as the key may have changed @@ -315,6 +351,7 @@ void fc::Controller::remove_devices_not_in(std::initializer_list config_lg(config_mutex); if (backup && exists(config_path)) { const path backup_path = config_path.string() + "-" + date_time_now(); fs::rename(config_path, backup_path); @@ -329,7 +366,7 @@ void fc::Controller::to_file(bool backup) { printer.SetUseShortRepeatedPrimitives(true); printer.PrintToString(c, &out_s); - std::ofstream ofs(config_path); + std::ofstream ofs; ofs.exceptions(); try { ofs.open(config_path); @@ -347,7 +384,7 @@ void fc::Controller::update_config_write_time() { config_write_time = fs::last_write_time(config_path); } -bool fc::Controller::config_file_modified() const { +bool fc::Controller::config_file_modified() { if (!exists(config_path)) return false; @@ -357,12 +394,13 @@ bool fc::Controller::config_file_modified() const { thread fc::Controller::spawn_watcher() { return thread([this] { update_config_write_time(); - while (true) { + + for (; true; sleep_for(update_interval)) { + const lock_guard config_lg(config_mutex); if (config_file_modified()) { update_config_write_time(); reload(); } - sleep_for(update_interval); } }); } @@ -400,3 +438,11 @@ string fc::Controller::date_time_now() { << "-" << tm.tm_min; return ss.str(); } + +shared_lock fc::Controller::lock_task_read(const string &flabel) { + return shared_lock(tasks_mutex[flabel]); +} + +unique_lock fc::Controller::lock_task_write(const string &flabel) { + return unique_lock(tasks_mutex[flabel]); +} diff --git a/src/Controller.hpp b/src/Controller.hpp index e21a871..b3fdfe2 100644 --- a/src/Controller.hpp +++ b/src/Controller.hpp @@ -15,6 +15,7 @@ #include #include #include +#include using fc::FanInterface; using fc::FanTask; @@ -22,9 +23,14 @@ using std::find_if; using std::future; using std::istringstream; using std::list; +using std::shared_mutex; +using std::shared_lock; +using std::unique_lock; + using FanStatus = fc_pb::FanStatus_Status; using DevicesCallback = function; using StatusCallback = function; +using tasks_mutex_t = shared_mutex; namespace fc { extern milliseconds update_interval; @@ -40,8 +46,8 @@ class Controller { Devices devices; map tasks; - map tasks_mutex; - mutex test_mutex; + map tasks_mutex; + mutex test_mutex, config_mutex; list device_observers; list status_observers; Util::RemovableMutex device_observers_mutex, status_observers_mutex; @@ -56,7 +62,7 @@ class Controller { void nv_init(); void test(fc::FanInterface &fan, bool forced, bool blocking, shared_ptr> test_status); - size_t tests_running() const; + size_t tests_running(); void set_devices(const fc_pb::Devices &devices_); void from(const fc_pb::ControllerConfig &c); @@ -68,20 +74,22 @@ class Controller { optional watcher; fs::file_time_type config_write_time; - void enable_dell_fans(); - void disable_dell_fans(); - bool is_testing(const string &flabel) const; + void enable_dell_fans(const optional except_flabel = nullopt); + void disable_dell_fans(const optional except_flabel = nullopt); + bool is_testing(const string &flabel); optional read_config(); void merge(Devices &old_it, bool replace_on_match, bool deep_cmp = false); void remove_devices_not_in( std::initializer_list> list_of_devices); void to_file(bool backup); void update_config_write_time(); - bool config_file_modified() const; + bool config_file_modified(); thread spawn_watcher(); void notify_devices_observers(); void notify_status_observers(const string &flabel); static string date_time_now(); + shared_lock lock_task_read(const string &flabel); + unique_lock lock_task_write(const string &flabel); }; } // namespace fc diff --git a/src/FanInterface.cpp b/src/FanInterface.cpp index f674e96..60d41b8 100644 --- a/src/FanInterface.cpp +++ b/src/FanInterface.cpp @@ -55,26 +55,37 @@ bool fc::FanInterface::tested() const { return (PWM_MIN <= start_pwm && start_pwm <= PWM_MAX) && !rpm_to_pwm.empty(); } -bool fc::FanInterface::pre_start_check() { +bool fc::FanInterface::try_enable() { if (ignore) { LOG(llvl::debug) << *this << ": ignored"; - } else if (const bool ce = temp_to_rpm.empty(), se = !sensor, - si = (sensor && sensor->ignore); - ce || se || si) { - LOG(llvl::warning) << *this << ": skipping - " - << Util::join({{ce, "curve not configured"}, - {se, "sensor not configured"}, - {si, "sensor ignored"}}); } else if (!enable_control()) { LOG(llvl::error) << *this << ": failed to enable"; + disable_control(); } else { return true; } - disable_control(); return false; } +bool fc::FanInterface::is_configured(bool log) const { + const bool ce = temp_to_rpm.empty(), se = !sensor, si = (sensor && sensor->ignore); + const bool configured = !(ce || se || si); + if (!configured && log) { + LOG(llvl::warning) << *this << ": skipping - " + << Util::join({{ce, "curve not configured"}, + {se, "sensor not configured"}, + {si, "sensor ignored"}}); + } + + return configured; +} + +bool fc::FanInterface::set_pwm(Pwm pwm) { + LOG(llvl::trace) << *this << ": " << pwm << fc::log::flush; + return true; +} + Pwm fc::FanInterface::find_closest_pwm(Rpm rpm) { // Find RPM closest to rpm const auto ge_it = rpm_to_pwm.lower_bound(rpm); // >= rpm @@ -148,35 +159,34 @@ void fc::FanInterface::sleep_for_interval() const { sleep_for((interval.count() > 0) ? interval : fc::update_interval); } -void fc::FanInterface::test(ObservableNumber &status) { +bool fc::FanInterface::test(ObservableNumber &status) { const Pwm pre_pwm = get_pwm(); // Fail early if can't write enable mode or pwm - const bool ec = enable_control(), spt = set_pwm_test(); - if (!ec || !spt) { + if (!enable_control() || !set_pwm_test()) { LOG(llvl::error) << *this << ": failed to take control"; disable_control(); - status += 100; - return; + status = -1; + return false; } - // 100 (%) should be added to status over the series of tests - status = 0; Pwm_to_Rpm_Map pwm_to_rpm; + status = 0; test_stopped(pwm_to_rpm); - status += 10; + status += 20; test_start(pwm_to_rpm); status += 30; test_running_min(pwm_to_rpm); - status += 30; + status += 25; test_mapping(pwm_to_rpm); - status += 30; + status = 100; rpm_to_pwm_from(pwm_to_rpm); // Restore pre-test Rpm set_pwm(pre_pwm); + return true; } optional fc::FanInterface::set_stabilised_pwm(const Pwm pwm) { @@ -186,24 +196,29 @@ optional fc::FanInterface::set_stabilised_pwm(const Pwm pwm) { // Rpm must not increase more than 5% twice consecutively to be 'stable' Rpm cur = get_rpm(), prev = 0; uint reached = 0; - while (reached <= 4) { + while (reached <= 3) { sleep_for_interval(); if (get_pwm() != pwm) return nullopt; prev = cur; cur = get_rpm(); - reached = ((cur - prev) <= (0.05 * cur)) ? reached + 1 : 0; + reached = (abs(static_cast(cur - prev)) <= (fc::STABILISED_THRESHOLD * cur)) ? reached + 1 : 0; } return cur; } bool fc::FanInterface::set_pwm_test() { - for (int i = 0; i < 3; ++i) { - const Pwm target = (get_pwm() != PWM_MIN) ? PWM_MIN : PWM_MAX; - if (set_stabilised_pwm(target).has_value()) + const Pwm target = (get_pwm() != PWM_MIN) ? PWM_MIN : PWM_MAX; + if (!set_pwm(target)) + return false; + + for (int i = 0; i < 10; ++i, sleep_for_interval()) { + if (get_pwm() == target) return true; +// if (set_stabilised_pwm(target).has_value()) +// return true; } return false; } @@ -357,8 +372,8 @@ void fc::FanInterface::temp_to_rpm_from(const string &src) { if (rpm_to_pwm.empty()) // Fan needs to be tested first return; - const optional min_temp = sensor->min_temp(), - max_temp = sensor->max_temp(); + const optional min_temp = sensor ? sensor->min_temp() : nullopt, + max_temp = sensor ? sensor->max_temp() : nullopt; string::const_iterator start_it = src.begin(), next_it = src.end(); std::smatch m; diff --git a/src/FanInterface.hpp b/src/FanInterface.hpp index 077f8f2..55d8c0b 100644 --- a/src/FanInterface.hpp +++ b/src/FanInterface.hpp @@ -30,6 +30,7 @@ enum class ControllerState; extern ControllerState controller_state; const Pwm PWM_MIN = 0, PWM_MAX = 255; +const double STABILISED_THRESHOLD = 0.1; Pwm clamp_pwm(Pwm pwm); @@ -43,9 +44,10 @@ class FanInterface { bool ignore{false}; void update(); - virtual void test(ObservableNumber &status); + virtual bool test(ObservableNumber &status); bool tested() const; - bool pre_start_check(); + bool try_enable(); + bool is_configured(bool log) const; virtual bool enable_control() = 0; virtual bool disable_control() = 0; @@ -76,7 +78,7 @@ class FanInterface { int top_stickiness_rem_intervals{0}; } smoothing; - virtual bool set_pwm(const Pwm pwm) = 0; + virtual bool set_pwm(const Pwm pwm); Pwm find_closest_pwm(Rpm rpm); bool recover_control(); Rpm smooth_rpm(const Rpm rpm); diff --git a/src/FanSysfs.cpp b/src/FanSysfs.cpp index 9f0aa13..606188d 100644 --- a/src/FanSysfs.cpp +++ b/src/FanSysfs.cpp @@ -39,9 +39,9 @@ bool fc::FanSysfs::disable_control() { return true; } -void fc::FanSysfs::test(ObservableNumber &status) { +bool fc::FanSysfs::test(ObservableNumber &status) { test_driver_enable_flag(); - fc::FanInterface::test(status); + return fc::FanInterface::test(status); } void fc::FanSysfs::from(const fc_pb::Fan &f, const SensorMap &sensor_map) { @@ -77,12 +77,10 @@ string fc::FanSysfs::hw_id() const { return pwm_path.c_str(); } DevType fc::FanSysfs::type() const { return DevType::SYS; } bool fc::FanSysfs::set_pwm(const Pwm pwm) { - if (!Util::write(pwm_path, pwm)) - return FanInterface::recover_control(); + if (!Util::write(pwm_path, pwm) && !FanInterface::recover_control()) + return false; - LOG(llvl::trace) << *this << ": " << pwm << fc::log::flush; - - return true; + return FanInterface::set_pwm(pwm); } Pwm fc::FanSysfs::get_pwm() const { diff --git a/src/FanSysfs.hpp b/src/FanSysfs.hpp index a900da4..919e726 100644 --- a/src/FanSysfs.hpp +++ b/src/FanSysfs.hpp @@ -15,7 +15,7 @@ class FanSysfs : public FanInterface { FanSysfs(string label_, const path &adapter_path_, SysfsID id_); ~FanSysfs() override; - void test(ObservableNumber &status) override; + bool test(ObservableNumber &status) override; bool enable_control() override; bool disable_control() override; Pwm get_pwm() const override; diff --git a/src/NvidiaDevices.cpp b/src/NvidiaDevices.cpp index 6e11e12..2333f2c 100644 --- a/src/NvidiaDevices.cpp +++ b/src/NvidiaDevices.cpp @@ -71,10 +71,10 @@ Pwm fc::FanNV::get_pwm() const { bool fc::FanNV::set_pwm(const Pwm pwm) { // Attempt to recover control of the device if the write fails - if (!xnvlib->pwm_percent.write(id, pwm_to_percent(pwm))) - return FanInterface::recover_control(); + if (!xnvlib->pwm_percent.write(id, pwm_to_percent(pwm)) && !FanInterface::recover_control()) + return false; - return true; + return FanInterface::set_pwm(pwm); } bool fc::FanNV::enable_control() { diff --git a/src/NvidiaUtil.cpp b/src/NvidiaUtil.cpp index e72b3f6..2e5027e 100644 --- a/src/NvidiaUtil.cpp +++ b/src/NvidiaUtil.cpp @@ -92,10 +92,8 @@ void NV::X11Display::init_display() { // If not found, attempt to find xauth, and or display from running X11 server bool found_xauth = getenv("XAUTHORITY") != nullptr; if (dsp.empty() || !found_xauth) { - if (dsp.empty()) - LOG(llvl::debug) << "Guessing X11 env var $DISPLAY, consider setting"; - if (!found_xauth) - LOG(llvl::debug) << "Guessing X11 env var $XAUTHORITY, consider setting"; + LOG(llvl::debug) << "X11 env var " << Util::join({{dsp.empty(), "$DISPLAY"}, {!found_xauth, "$XAUTHORITY"}}) + << " not set. Set if NVIDIA control isn't working"; redi::ipstream ips( "echo \"$(ps wwaux 2>/dev/null | grep -wv PID | grep -v grep)\" " @@ -211,8 +209,7 @@ bool NV::LibXNvCtrl::check_support() { // Enable fan control coolbit if start from a TTY - so user knows to reboot if (Util::is_atty() && enable_fan_control_coolbit()) { - LOG(llvl::warning) - << "Enabling NVIDIA fan control coolbits flag, restart for NV support"; + LOG(llvl::warning) << "Enabling NVIDIA fan control coolbits flag, restart for NV support"; return false; } @@ -261,8 +258,7 @@ bool NV::LibXNvCtrl::enable_fan_control_coolbit() { const auto scb = string("nvidia-xconfig -a --cool-bits=") + to_string(newv); if (system(scb.c_str()) != 0) - LOG(llvl::error) - << "Failed to write coolbits value, nvidia fan control may fail!"; + LOG(llvl::error) << "Failed to write coolbits value, nvidia fan control may fail!"; return true; } diff --git a/src/Service.cpp b/src/Service.cpp index e78651b..c6a64ef 100644 --- a/src/Service.cpp +++ b/src/Service.cpp @@ -206,6 +206,7 @@ Status fc::Service::Test([[maybe_unused]] ServerContext *context, writer->WriteLast(resp, grpc::WriteOptions()); else writer->Write(resp); +// writer->Write(resp); }; controller.test(*it->second, e->forced(), true, diff --git a/src/Util.hpp b/src/Util.hpp index b7b027b..8c2d214 100644 --- a/src/Util.hpp +++ b/src/Util.hpp @@ -64,11 +64,11 @@ using std::vector; namespace fc::Util { static const string SERVICE_ADDR = "0.0.0.0:5820"; -template optional postfix_num(const string_view &s); +template optional postfix_num(const string_view &s); optional read_line(const path &fpath, bool failed = false); -template optional read(const path &fpath, bool failed = false); -template bool write(const path &fpath, T val, bool failed = false); -template string map_str(std::map m); +template optional read(const path &fpath, bool failed = false); +template bool write(const path &fpath, T val, bool failed = false); +template string map_str(std::map m); string join(std::initializer_list> args, string join_with = " & "); bool is_root(); @@ -76,9 +76,9 @@ bool is_atty(); std::chrono::high_resolution_clock::time_point deadline(long ms); bool deep_equal(const google::protobuf::Message &m1, const google::protobuf::Message &m2); -template optional from_string(const string &s); +template optional from_string(const string &s); -template class ObservableNumber { +template class ObservableNumber { public: explicit ObservableNumber(T &&value) : value(value) {} ObservableNumber(function f, T &&value = 0); @@ -97,7 +97,7 @@ template class ObservableNumber { mutex update_mutex; }; -template class ScopedCounter { +template class ScopedCounter { public: explicit ScopedCounter(T &counter, bool increment = true) : counter(counter), increment(increment) { @@ -124,24 +124,24 @@ class RemovableMutex { // TEMPLATE DEFINITIONS // //----------------------// -template optional fc::Util::postfix_num(const string_view &s) { +template optional fc::Util::postfix_num(const string_view &s) { bool found = false; const auto beg = std::find_if_not(s.rbegin(), s.rend(), [&](const char &c) { return (std::isdigit(c)) ? (found = true) : !found; }); T res; - const auto [p, ec] = std::from_chars(beg.base(), s.data() + s.size(), res); + const auto[p, ec] = std::from_chars(beg.base(), s.data() + s.size(), res); return (ec == std::errc()) ? optional(res) : nullopt; } -template T from(std::istream &is) { +template T from(std::istream &is) { T ret; is >> ret; return ret; } -template +template optional fc::Util::read(const path &fpath, bool failed) { const auto retry = [&fpath, &failed] { return (!failed && exists(fpath)) ? read(fpath, true) : std::nullopt; @@ -160,7 +160,7 @@ optional fc::Util::read(const path &fpath, bool failed) { return ret; } -template +template bool fc::Util::write(const path &fpath, T val, bool failed) { std::ofstream ofs(fpath.string()); if (!ofs) { @@ -183,7 +183,7 @@ bool fc::Util::write(const path &fpath, T val, bool failed) { return true; } -template +template string fc::Util::map_str(const std::map m) { std::stringstream ss; for (auto it = m.begin(); it != m.end();) { @@ -194,20 +194,20 @@ string fc::Util::map_str(const std::map m) { return ss.str(); } -template optional fc::Util::from_string(const string &s) { +template optional fc::Util::from_string(const string &s) { T val; - const auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val); + const auto[p, ec] = std::from_chars(s.data(), s.data() + s.size(), val); return (ec == std::errc()) ? optional(val) : nullopt; } -template +template fc::Util::ObservableNumber::ObservableNumber(function f, T &&value) : value(value) { register_observer(f, false); } -template +template void fc::Util::ObservableNumber::register_observer( std::function callback, bool call_on_register) { if (call_on_register) @@ -215,12 +215,12 @@ void fc::Util::ObservableNumber::register_observer( observers.emplace_back(move(callback)); } -template void fc::Util::ObservableNumber::notify_observers() { +template void fc::Util::ObservableNumber::notify_observers() { for (auto &f : observers) f(value); } -template +template fc::Util::ObservableNumber & fc::Util::ObservableNumber::operator+=(const T &other) { const lock_guard lock(update_mutex); @@ -229,7 +229,7 @@ fc::Util::ObservableNumber::operator+=(const T &other) { return *this; } -template +template fc::Util::ObservableNumber & fc::Util::ObservableNumber::operator=(T other) { const lock_guard lock(update_mutex);