Merge pull request #1737

69ab14d9 More robust battery status handling. (Dion Ahmetaj)
This commit is contained in:
Riccardo Spagni 2017-02-21 11:16:08 +02:00
commit d2059dfab2
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
8 changed files with 81 additions and 29 deletions

View file

@ -41,6 +41,7 @@
#include "common/command_line.h" #include "common/command_line.h"
#include "string_coding.h" #include "string_coding.h"
#include "storages/portable_storage_template_helper.h" #include "storages/portable_storage_template_helper.h"
#include "boost/logic/tribool.hpp"
#undef MONERO_DEFAULT_LOG_CATEGORY #undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "miner" #define MONERO_DEFAULT_LOG_CATEGORY "miner"
@ -61,6 +62,7 @@ namespace cryptonote
const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true};
const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true};
const command_line::arg_descriptor<bool> arg_bg_mining_enable = {"bg-mining-enable", "enable/disable background mining", true, true}; const command_line::arg_descriptor<bool> arg_bg_mining_enable = {"bg-mining-enable", "enable/disable background mining", true, true};
const command_line::arg_descriptor<bool> 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<uint64_t> 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<uint64_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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}; const command_line::arg_descriptor<uint8_t> 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_start_mining);
command_line::add_arg(desc, arg_mining_threads); 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_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_min_idle_interval_seconds);
command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage); command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage);
command_line::add_arg(desc, arg_bg_mining_miner_target_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 // 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)) if(command_line::has_arg(vm, arg_bg_mining_enable))
set_is_background_mining_enabled( command_line::get_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)) 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) ); 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)) if(command_line::has_arg(vm, arg_bg_mining_idle_threshold_percentage))
@ -254,7 +259,7 @@ namespace cryptonote
return m_threads_total; 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_mine_address = adr;
m_threads_total = static_cast<uint32_t>(threads_count); m_threads_total = static_cast<uint32_t>(threads_count);
@ -278,6 +283,7 @@ namespace cryptonote
boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
set_is_background_mining_enabled(do_background); set_is_background_mining_enabled(do_background);
set_ignore_battery(ignore_battery);
for(size_t i = 0; i != threads_count; i++) for(size_t i = 0; i != threads_count; i++)
{ {
@ -469,6 +475,11 @@ namespace cryptonote
return m_is_background_mining_enabled; 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. * This has differing behaviour depending on if mining has been started/etc.
* Note: add documentation * Note: add documentation
@ -482,6 +493,11 @@ namespace cryptonote
return true; return true;
} }
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
void miner::set_ignore_battery(bool ignore_battery)
{
m_ignore_battery = ignore_battery;
}
//-----------------------------------------------------------------------------------------------------
uint64_t miner::get_min_idle_seconds() const uint64_t miner::get_min_idle_seconds() const
{ {
return m_min_idle_seconds; return m_min_idle_seconds;
@ -575,7 +591,21 @@ namespace cryptonote
continue; // if interrupted because stop called, loop should end .. 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 ) if( m_is_background_mining_started )
{ {
@ -763,45 +793,54 @@ namespace cryptonote
return (uint8_t)( ceil( (other * 1.f / total * 1.f) * 100) ); 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 #ifdef _WIN32
SYSTEM_POWER_STATUS power_status; SYSTEM_POWER_STATUS power_status;
if ( GetSystemPowerStatus( &power_status ) != 0 ) if ( GetSystemPowerStatus( &power_status ) != 0 )
{ {
return power_status.ACLineStatus != 1; return boost::logic::tribool(power_status.ACLineStatus != 1);
} }
#elif defined(__linux__) #elif defined(__linux__)
// i've only tested on UBUNTU, these paths might be different on other systems // 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 // need to figure out a way to make this more flexible
const std::string POWER_SUPPLY_STATUS_PATH = "/sys/class/power_supply/ACAD/online"; std::string power_supply_path = "";
const std::string POWER_SUPPLY_STATUS_PATHS[] =
if( !epee::file_io_utils::is_file_exist(POWER_SUPPLY_STATUS_PATH) )
{ {
LOG_ERROR("'" << POWER_SUPPLY_STATUS_PATH << "' file does not exist, can't determine if on AC power"); "/sys/class/power_supply/ACAD/online",
return false; "/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() ) if( power_stream.fail() )
{ {
LOG_ERROR("failed to open '" << POWER_SUPPLY_STATUS_PATH << "'"); LOG_ERROR("failed to open '" << power_supply_path << "'");
return false; return boost::logic::tribool(boost::logic::indeterminate);;
} }
return power_stream.get() != '1'; return boost::logic::tribool( (power_stream.get() != '1') );
#endif #endif
LOG_ERROR("couldn't query power status"); LOG_ERROR("couldn't query power status");
return false; // shouldn't get here unless no support for querying battery status return boost::logic::tribool(boost::logic::indeterminate);
// 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.
} }
} }

View file

@ -31,6 +31,7 @@
#pragma once #pragma once
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/logic/tribool_fwd.hpp>
#include <atomic> #include <atomic>
#include "cryptonote_basic.h" #include "cryptonote_basic.h"
#include "difficulty.h" #include "difficulty.h"
@ -67,7 +68,7 @@ namespace cryptonote
static void init_options(boost::program_options::options_description& desc); 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 set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
bool on_block_chain_update(); 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; uint64_t get_speed() const;
uint32_t get_threads_count() const; uint32_t get_threads_count() const;
void send_stop_signal(); void send_stop_signal();
@ -82,6 +83,7 @@ namespace cryptonote
void resume(); void resume();
void do_print_hashrate(bool do_hr); void do_print_hashrate(bool do_hr);
bool get_is_background_mining_enabled() const; bool get_is_background_mining_enabled() const;
bool get_ignore_battery() const;
uint64_t get_min_idle_seconds() const; uint64_t get_min_idle_seconds() const;
bool set_min_idle_seconds(uint64_t min_idle_seconds); bool set_min_idle_seconds(uint64_t min_idle_seconds);
uint8_t get_idle_threshold() const; uint8_t get_idle_threshold() const;
@ -149,8 +151,10 @@ namespace cryptonote
// background mining stuffs .. // background mining stuffs ..
bool set_is_background_mining_enabled(bool is_background_mining_enabled); bool set_is_background_mining_enabled(bool is_background_mining_enabled);
void set_ignore_battery(bool ignore_battery);
bool background_worker_thread(); bool background_worker_thread();
std::atomic<bool> m_is_background_mining_enabled; std::atomic<bool> m_is_background_mining_enabled;
bool m_ignore_battery;
boost::mutex m_is_background_mining_enabled_mutex; boost::mutex m_is_background_mining_enabled_mutex;
boost::condition_variable m_is_background_mining_enabled_cond; boost::condition_variable m_is_background_mining_enabled_cond;
std::atomic<bool> m_is_background_mining_started; std::atomic<bool> 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_system_times(uint64_t& total_time, uint64_t& idle_time);
static bool get_process_time(uint64_t& total_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 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();
}; };
} }

View file

@ -272,12 +272,18 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl; std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl;
uint64_t threads_count = 1; uint64_t threads_count = 1;
bool do_background_mining = false; bool do_background_mining = false;
if(args.size() > 3) bool ignore_battery = false;
if(args.size() > 4)
{ {
return false; 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"; do_background_mining = args[2] == "true";
} }
@ -288,7 +294,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
threads_count = (ok && 0 < threads_count) ? threads_count : 1; 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; return true;
} }

View file

@ -96,7 +96,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler( m_command_lookup.set_handler(
"start_mining" "start_mining"
, std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1) , std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)
, "Start mining for specified address, start_mining <addr> [<threads>] [do_background_mining], default 1 thread, no background mining" , "Start mining for specified address, start_mining <addr> [<threads>] [do_background_mining] [ignore_battery], default 1 thread, no background mining"
); );
m_command_lookup.set_handler( m_command_lookup.set_handler(
"stop_mining" "stop_mining"

View file

@ -929,13 +929,14 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
return true; 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::request req;
cryptonote::COMMAND_RPC_START_MINING::response res; cryptonote::COMMAND_RPC_START_MINING::response res;
req.miner_address = cryptonote::get_account_address_as_str(testnet, address); req.miner_address = cryptonote::get_account_address_as_str(testnet, address);
req.threads_count = num_threads; req.threads_count = num_threads;
req.do_background_mining = do_background_mining; req.do_background_mining = do_background_mining;
req.ignore_battery = ignore_battery;
std::string fail_message = "Mining did not start"; std::string fail_message = "Mining did not start";
if (m_is_rpc) if (m_is_rpc)

View file

@ -106,7 +106,7 @@ public:
bool print_transaction_pool_stats(); 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(); bool stop_mining();

View file

@ -635,7 +635,7 @@ namespace cryptonote
boost::thread::attributes attrs; boost::thread::attributes attrs;
attrs.set_stack_size(THREAD_STACK_SIZE); attrs.set_stack_size(THREAD_STACK_SIZE);
if(!m_core.get_miner().start(adr, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining)) if(!m_core.get_miner().start(adr, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining, req.ignore_battery))
{ {
res.status = "Failed, mining not started"; res.status = "Failed, mining not started";
LOG_PRINT_L0(res.status); LOG_PRINT_L0(res.status);

View file

@ -501,11 +501,13 @@ namespace cryptonote
std::string miner_address; std::string miner_address;
uint64_t threads_count; uint64_t threads_count;
bool do_background_mining; bool do_background_mining;
bool ignore_battery;
BEGIN_KV_SERIALIZE_MAP() BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(miner_address) KV_SERIALIZE(miner_address)
KV_SERIALIZE(threads_count) KV_SERIALIZE(threads_count)
KV_SERIALIZE(do_background_mining) KV_SERIALIZE(do_background_mining)
KV_SERIALIZE(ignore_battery)
END_KV_SERIALIZE_MAP() END_KV_SERIALIZE_MAP()
}; };