From 69ab14d91e67fdf242b00c83ab85ce280e55f6f4 Mon Sep 17 00:00:00 2001 From: Dion Ahmetaj Date: Wed, 15 Feb 2017 14:00:01 -0500 Subject: [PATCH] More robust battery status handling. Added an extra path to check for linux power supply status. Added ignore battery option. If set to true, then when we can't figure out the power status, we'll assume the system is plugged in. --- src/cryptonote_basic/miner.cpp | 77 +++++++++++++++++++------ src/cryptonote_basic/miner.h | 8 ++- src/daemon/command_parser_executor.cpp | 12 +++- src/daemon/command_server.cpp | 2 +- src/daemon/rpc_command_executor.cpp | 5 +- src/daemon/rpc_command_executor.h | 2 +- src/rpc/core_rpc_server.cpp | 2 +- src/rpc/core_rpc_server_commands_defs.h | 2 + 8 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 117c81878..bf1b057ee 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -41,6 +41,7 @@ #include "common/command_line.h" #include "string_coding.h" #include "storages/portable_storage_template_helper.h" +#include "boost/logic/tribool.hpp" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "miner" @@ -61,6 +62,7 @@ namespace cryptonote const command_line::arg_descriptor arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; const command_line::arg_descriptor arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; const command_line::arg_descriptor arg_bg_mining_enable = {"bg-mining-enable", "enable/disable background mining", true, true}; + const command_line::arg_descriptor arg_bg_mining_ignore_battery = {"bg-mining-ignore-battery", "if true, assumes plugged in when unable to query system power status", false, true}; const command_line::arg_descriptor arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true}; const command_line::arg_descriptor arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true}; const command_line::arg_descriptor arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specificy maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true}; @@ -181,6 +183,7 @@ namespace cryptonote command_line::add_arg(desc, arg_start_mining); command_line::add_arg(desc, arg_mining_threads); command_line::add_arg(desc, arg_bg_mining_enable); + command_line::add_arg(desc, arg_bg_mining_ignore_battery); command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds); command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage); command_line::add_arg(desc, arg_bg_mining_miner_target_percentage); @@ -230,6 +233,8 @@ namespace cryptonote // Let init set all parameters even if background mining is not enabled, they can start later with params set if(command_line::has_arg(vm, arg_bg_mining_enable)) set_is_background_mining_enabled( command_line::get_arg(vm, arg_bg_mining_enable) ); + if(command_line::has_arg(vm, arg_bg_mining_ignore_battery)) + set_ignore_battery( command_line::get_arg(vm, arg_bg_mining_ignore_battery) ); if(command_line::has_arg(vm, arg_bg_mining_min_idle_interval_seconds)) set_min_idle_seconds( command_line::get_arg(vm, arg_bg_mining_min_idle_interval_seconds) ); if(command_line::has_arg(vm, arg_bg_mining_idle_threshold_percentage)) @@ -254,7 +259,7 @@ namespace cryptonote return m_threads_total; } //----------------------------------------------------------------------------------------------------- - bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background) + bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background, bool ignore_battery) { m_mine_address = adr; m_threads_total = static_cast(threads_count); @@ -278,6 +283,7 @@ namespace cryptonote boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); set_is_background_mining_enabled(do_background); + set_ignore_battery(ignore_battery); for(size_t i = 0; i != threads_count; i++) { @@ -469,6 +475,11 @@ namespace cryptonote return m_is_background_mining_enabled; } //----------------------------------------------------------------------------------------------------- + bool miner::get_ignore_battery() const + { + return m_ignore_battery; + } + //----------------------------------------------------------------------------------------------------- /** * This has differing behaviour depending on if mining has been started/etc. * Note: add documentation @@ -482,6 +493,11 @@ namespace cryptonote return true; } //----------------------------------------------------------------------------------------------------- + void miner::set_ignore_battery(bool ignore_battery) + { + m_ignore_battery = ignore_battery; + } + //----------------------------------------------------------------------------------------------------- uint64_t miner::get_min_idle_seconds() const { return m_min_idle_seconds; @@ -575,7 +591,21 @@ namespace cryptonote continue; // if interrupted because stop called, loop should end .. } - bool on_ac_power = !on_battery_power(); + boost::tribool battery_powered(on_battery_power()); + bool on_ac_power = false; + if(indeterminate( battery_powered )) + { + // name could be better, only ignores battery requirement if we failed + // to get the status of the system + if( m_ignore_battery ) + { + on_ac_power = true; + } + } + else + { + on_ac_power = !battery_powered; + } if( m_is_background_mining_started ) { @@ -763,45 +793,54 @@ namespace cryptonote return (uint8_t)( ceil( (other * 1.f / total * 1.f) * 100) ); } //----------------------------------------------------------------------------------------------------- - bool miner::on_battery_power() + boost::logic::tribool miner::on_battery_power() { #ifdef _WIN32 SYSTEM_POWER_STATUS power_status; if ( GetSystemPowerStatus( &power_status ) != 0 ) { - return power_status.ACLineStatus != 1; + return boost::logic::tribool(power_status.ACLineStatus != 1); } #elif defined(__linux__) // i've only tested on UBUNTU, these paths might be different on other systems // need to figure out a way to make this more flexible - const std::string POWER_SUPPLY_STATUS_PATH = "/sys/class/power_supply/ACAD/online"; - - if( !epee::file_io_utils::is_file_exist(POWER_SUPPLY_STATUS_PATH) ) + std::string power_supply_path = ""; + const std::string POWER_SUPPLY_STATUS_PATHS[] = { - LOG_ERROR("'" << POWER_SUPPLY_STATUS_PATH << "' file does not exist, can't determine if on AC power"); - return false; + "/sys/class/power_supply/ACAD/online", + "/sys/class/power_supply/AC/online" + }; + + for(const std::string& path : POWER_SUPPLY_STATUS_PATHS) + { + if( epee::file_io_utils::is_file_exist(path) ) + { + power_supply_path = path; + break; + } + } + + if( power_supply_path.empty() ) + { + LOG_ERROR("Couldn't find battery/power status file, can't determine if plugged in!"); + return boost::logic::tribool(boost::logic::indeterminate);; } - std::ifstream power_stream(POWER_SUPPLY_STATUS_PATH); + std::ifstream power_stream(power_supply_path); if( power_stream.fail() ) { - LOG_ERROR("failed to open '" << POWER_SUPPLY_STATUS_PATH << "'"); - return false; + LOG_ERROR("failed to open '" << power_supply_path << "'"); + return boost::logic::tribool(boost::logic::indeterminate);; } - return power_stream.get() != '1'; + return boost::logic::tribool( (power_stream.get() != '1') ); #endif LOG_ERROR("couldn't query power status"); - return false; // shouldn't get here unless no support for querying battery status - // TODO: return enum with ability to signify failure in querying for power status - // and change bg-mining logic so that it stops. As @vtnerd states, with the current - // setup "If someone enabled background mining on a system that fails to grab ac - // status, it will just continually check with little hope of ever being resolved - // automagically". This is also the case for time/idle stats functions. + return boost::logic::tribool(boost::logic::indeterminate); } } diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index a66083ead..02987b9d9 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -31,6 +31,7 @@ #pragma once #include +#include #include #include "cryptonote_basic.h" #include "difficulty.h" @@ -67,7 +68,7 @@ namespace cryptonote static void init_options(boost::program_options::options_description& desc); bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height); bool on_block_chain_update(); - bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background = false); + bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background = false, bool ignore_battery = false); uint64_t get_speed() const; uint32_t get_threads_count() const; void send_stop_signal(); @@ -82,6 +83,7 @@ namespace cryptonote void resume(); void do_print_hashrate(bool do_hr); bool get_is_background_mining_enabled() const; + bool get_ignore_battery() const; uint64_t get_min_idle_seconds() const; bool set_min_idle_seconds(uint64_t min_idle_seconds); uint8_t get_idle_threshold() const; @@ -149,8 +151,10 @@ namespace cryptonote // background mining stuffs .. bool set_is_background_mining_enabled(bool is_background_mining_enabled); + void set_ignore_battery(bool ignore_battery); bool background_worker_thread(); std::atomic m_is_background_mining_enabled; + bool m_ignore_battery; boost::mutex m_is_background_mining_enabled_mutex; boost::condition_variable m_is_background_mining_enabled_cond; std::atomic m_is_background_mining_started; @@ -164,6 +168,6 @@ namespace cryptonote static bool get_system_times(uint64_t& total_time, uint64_t& idle_time); static bool get_process_time(uint64_t& total_time); static uint8_t get_percent_of_total(uint64_t some_time, uint64_t total_time); - static bool on_battery_power(); + static boost::logic::tribool on_battery_power(); }; } diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 8ed529737..e5fa5fece 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -272,12 +272,18 @@ bool t_command_parser_executor::start_mining(const std::vector& arg std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl; uint64_t threads_count = 1; bool do_background_mining = false; - if(args.size() > 3) + bool ignore_battery = false; + if(args.size() > 4) { return false; } - if(args.size() == 3) + if(args.size() == 4) + { + ignore_battery = args[3] == "true"; + } + + if(args.size() >= 3) { do_background_mining = args[2] == "true"; } @@ -288,7 +294,7 @@ bool t_command_parser_executor::start_mining(const std::vector& arg threads_count = (ok && 0 < threads_count) ? threads_count : 1; } - m_executor.start_mining(adr, threads_count, testnet, do_background_mining); + m_executor.start_mining(adr, threads_count, testnet, do_background_mining, ignore_battery); return true; } diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 4133b90d9..365a7d03b 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -96,7 +96,7 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "start_mining" , std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1) - , "Start mining for specified address, start_mining [] [do_background_mining], default 1 thread, no background mining" + , "Start mining for specified address, start_mining [] [do_background_mining] [ignore_battery], default 1 thread, no background mining" ); m_command_lookup.set_handler( "stop_mining" diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 00b349b15..219a7a1c4 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -929,13 +929,14 @@ bool t_rpc_command_executor::print_transaction_pool_stats() { return true; } -bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining = false) { +bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining, bool ignore_battery) { cryptonote::COMMAND_RPC_START_MINING::request req; cryptonote::COMMAND_RPC_START_MINING::response res; req.miner_address = cryptonote::get_account_address_as_str(testnet, address); req.threads_count = num_threads; req.do_background_mining = do_background_mining; - + req.ignore_battery = ignore_battery; + std::string fail_message = "Mining did not start"; if (m_is_rpc) diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index 5b7b76448..d9e874767 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -106,7 +106,7 @@ public: bool print_transaction_pool_stats(); - bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining); + bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining = false, bool ignore_battery = false); bool stop_mining(); diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 8165dacbc..cae6800b5 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -635,7 +635,7 @@ namespace cryptonote boost::thread::attributes attrs; attrs.set_stack_size(THREAD_STACK_SIZE); - if(!m_core.get_miner().start(adr, static_cast(req.threads_count), attrs, req.do_background_mining)) + if(!m_core.get_miner().start(adr, static_cast(req.threads_count), attrs, req.do_background_mining, req.ignore_battery)) { res.status = "Failed, mining not started"; LOG_PRINT_L0(res.status); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 3ab1ea175..8b744c26a 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -501,11 +501,13 @@ namespace cryptonote std::string miner_address; uint64_t threads_count; bool do_background_mining; + bool ignore_battery; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(miner_address) KV_SERIALIZE(threads_count) KV_SERIALIZE(do_background_mining) + KV_SERIALIZE(ignore_battery) END_KV_SERIALIZE_MAP() };