mirror of https://github.com/oxen-io/oxen-core.git
Replace once_a_time_seconds; send proofs faster
This replaces the horrible, horrible, badly misused templated once_a_time_seconds and once_a_time_milliseconds with a `periodic_task` that works the same way but takes parameters as constructor arguments instead of template parameters. It also makes various small improvements: - uses std::chrono::steady_clock instead of ifdef'ing platform dependent timer code. - takes a std::chrono duration rather than a template integer and scaling parameter. - timers can be reset to trigger on the next invocation, and this is thread-safe. - timer intervals can be changed at run-time. This all then gets used to reset the proof timer immediately upon receiving a ping (initially or after expiring) from storage server and lokinet so that we send proofs out faster.
This commit is contained in:
parent
6e436c29b7
commit
f3fdcb1fbc
|
@ -32,9 +32,8 @@
|
|||
|
||||
#include <list>
|
||||
#include <numeric>
|
||||
#include <boost/timer/timer.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
|
||||
#include "misc_os_dependent.h"
|
||||
#include "syncobj.h"
|
||||
|
@ -230,57 +229,38 @@ namespace math_helper
|
|||
}
|
||||
|
||||
}
|
||||
template<uint64_t scale, int default_interval, bool start_immediate = true>
|
||||
class once_a_time
|
||||
{
|
||||
uint64_t get_time() const
|
||||
|
||||
// Periodic timer that gatekeeps calling of a job to a minimum interval after the previous job
|
||||
// finished. Only the reset() call is thread-safe; everything else should be confined to the
|
||||
// owning thread.
|
||||
class periodic_task {
|
||||
public:
|
||||
explicit periodic_task(std::chrono::microseconds interval, bool start_immediate = true)
|
||||
: m_interval{interval}, m_last_worked_time{std::chrono::steady_clock::now()}, m_trigger_now{start_immediate}
|
||||
{}
|
||||
|
||||
template <class functor_t>
|
||||
void do_call(functor_t functr)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME fileTime;
|
||||
GetSystemTimeAsFileTime(&fileTime);
|
||||
unsigned __int64 present = 0;
|
||||
present |= fileTime.dwHighDateTime;
|
||||
present = present << 32;
|
||||
present |= fileTime.dwLowDateTime;
|
||||
present /= 10; // mic-sec
|
||||
return present;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
#endif
|
||||
if (m_trigger_now || std::chrono::steady_clock::now() - m_last_worked_time > m_interval)
|
||||
{
|
||||
functr();
|
||||
m_last_worked_time = std::chrono::steady_clock::now();
|
||||
m_trigger_now = false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
once_a_time():m_interval(default_interval * scale)
|
||||
{
|
||||
m_last_worked_time = 0;
|
||||
if(!start_immediate)
|
||||
m_last_worked_time = get_time();
|
||||
}
|
||||
// Makes the next task attempt run the job, regardless of the time since the last job. Atomic.
|
||||
void reset() { m_trigger_now = true; }
|
||||
// Returns the current interval
|
||||
std::chrono::microseconds interval() const { return m_interval; }
|
||||
// Changes the current interval
|
||||
void interval(std::chrono::microseconds us) { m_interval = us; }
|
||||
|
||||
template<class functor_t>
|
||||
bool do_call(functor_t functr)
|
||||
{
|
||||
uint64_t current_time = get_time();
|
||||
|
||||
if(current_time - m_last_worked_time > m_interval)
|
||||
{
|
||||
bool res = functr();
|
||||
m_last_worked_time = get_time();
|
||||
return res;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_last_worked_time;
|
||||
uint64_t m_interval;
|
||||
};
|
||||
|
||||
template<int default_interval, bool start_immediate = true>
|
||||
class once_a_time_seconds: public once_a_time<1000000, default_interval, start_immediate> {};
|
||||
template<int default_interval, bool start_immediate = true>
|
||||
class once_a_time_milliseconds: public once_a_time<1000, default_interval, start_immediate> {};
|
||||
private:
|
||||
std::chrono::microseconds m_interval;
|
||||
std::chrono::steady_clock::time_point m_last_worked_time;
|
||||
std::atomic<bool> m_trigger_now;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1952,6 +1952,10 @@ namespace cryptonote
|
|||
}
|
||||
return true;
|
||||
}
|
||||
void core::reset_proof_interval()
|
||||
{
|
||||
m_check_uptime_proof_interval.reset();
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
void core::do_uptime_proof_call()
|
||||
{
|
||||
|
@ -1969,14 +1973,14 @@ namespace cryptonote
|
|||
next_proof_time += UPTIME_PROOF_FREQUENCY_IN_SECONDS - UPTIME_PROOF_TIMER_SECONDS/2;
|
||||
|
||||
if ((uint64_t) std::time(nullptr) < next_proof_time)
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (!check_external_ping(m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME, "the storage server"))
|
||||
{
|
||||
MGINFO_RED(
|
||||
"Failed to submit uptime proof: have not heard from the storage server recently. Make sure that it "
|
||||
"is running! It is required to run alongside the Loki daemon");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
uint8_t hf_version = get_blockchain_storage().get_current_hard_fork_version();
|
||||
if (!check_external_ping(m_last_lokinet_ping, LOKINET_PING_LIFETIME, "Lokinet"))
|
||||
|
@ -1986,7 +1990,7 @@ namespace cryptonote
|
|||
MGINFO_RED(
|
||||
"Failed to submit uptime proof: have not heard from lokinet recently. Make sure that it "
|
||||
"is running! It is required to run alongside the Loki daemon");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1997,14 +2001,12 @@ namespace cryptonote
|
|||
}
|
||||
|
||||
submit_uptime_proof();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset the interval so that we're ready when we register, OR if we get deregistered this primes us up for re-registration in the same session
|
||||
m_check_uptime_proof_interval = {};
|
||||
m_check_uptime_proof_interval.reset();
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <ctime>
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
@ -56,6 +57,8 @@ DISABLE_VS_WARNINGS(4355)
|
|||
#include "common/loki_integration_test_hooks.h"
|
||||
namespace cryptonote
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
struct test_options {
|
||||
std::vector<std::pair<uint8_t, uint64_t>> hard_forks;
|
||||
size_t long_term_block_weight_window;
|
||||
|
@ -893,6 +896,12 @@ namespace cryptonote
|
|||
*/
|
||||
bool submit_uptime_proof();
|
||||
|
||||
/** Called to signal that a significant service node application ping has arrived (either the
|
||||
* first, or the first after a long time). This triggers a check and attempt to send an uptime
|
||||
* proof soon (i.e. at the next idle loop).
|
||||
*/
|
||||
void reset_proof_interval();
|
||||
|
||||
/*
|
||||
* @brief get the blockchain pruning seed
|
||||
*
|
||||
|
@ -1098,16 +1107,16 @@ namespace cryptonote
|
|||
|
||||
cryptonote_protocol_stub m_protocol_stub; //!< cryptonote protocol stub instance
|
||||
|
||||
epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; //!< interval for manual storing of Blockchain, if enabled
|
||||
epee::math_helper::once_a_time_seconds<60*60*2, true> m_fork_moaner; //!< interval for checking HardFork status
|
||||
epee::math_helper::once_a_time_seconds<60*2, false> m_txpool_auto_relayer; //!< interval for checking re-relaying txpool transactions
|
||||
epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions
|
||||
epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space
|
||||
epee::math_helper::once_a_time_seconds<UPTIME_PROOF_TIMER_SECONDS, true> m_check_uptime_proof_interval; //!< interval for checking our own uptime proof
|
||||
epee::math_helper::once_a_time_seconds<90, false> m_block_rate_interval; //!< interval for checking block rate
|
||||
epee::math_helper::once_a_time_seconds<60*60*5, true> m_blockchain_pruning_interval; //!< interval for incremental blockchain pruning
|
||||
epee::math_helper::once_a_time_seconds<60*2, false> m_service_node_vote_relayer;
|
||||
epee::math_helper::once_a_time_seconds<60*60, false> m_sn_proof_cleanup_interval;
|
||||
epee::math_helper::periodic_task m_store_blockchain_interval{12h, false}; //!< interval for manual storing of Blockchain, if enabled
|
||||
epee::math_helper::periodic_task m_fork_moaner{2h}; //!< interval for checking HardFork status
|
||||
epee::math_helper::periodic_task m_txpool_auto_relayer{2min, false}; //!< interval for checking re-relaying txpool transactions
|
||||
epee::math_helper::periodic_task m_check_updates_interval{12h}; //!< interval for checking for new versions
|
||||
epee::math_helper::periodic_task m_check_disk_space_interval{10min}; //!< interval for checking for disk space
|
||||
epee::math_helper::periodic_task m_check_uptime_proof_interval{std::chrono::seconds{UPTIME_PROOF_TIMER_SECONDS}}; //!< interval for checking our own uptime proof
|
||||
epee::math_helper::periodic_task m_block_rate_interval{90s, false}; //!< interval for checking block rate
|
||||
epee::math_helper::periodic_task m_blockchain_pruning_interval{5h}; //!< interval for incremental blockchain pruning
|
||||
epee::math_helper::periodic_task m_service_node_vote_relayer{2min, false};
|
||||
epee::math_helper::periodic_task m_sn_proof_cleanup_interval{1h, false};
|
||||
|
||||
std::atomic<bool> m_starter_message_showed; //!< has the "daemon will sync now" message been shown?
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <boost/program_options.hpp>
|
||||
#include <boost/logic/tribool_fwd.hpp>
|
||||
#include <atomic>
|
||||
#include "cryptonote_basic/blobdatatype.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
#include "cryptonote_basic/verification_context.h"
|
||||
#include "cryptonote_basic/difficulty.h"
|
||||
|
@ -43,6 +44,7 @@
|
|||
|
||||
namespace cryptonote
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
struct i_miner_handler
|
||||
{
|
||||
|
@ -149,9 +151,9 @@ namespace cryptonote
|
|||
i_miner_handler* m_phandler;
|
||||
Blockchain* m_pbc;
|
||||
account_public_address m_mine_address;
|
||||
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
|
||||
epee::math_helper::periodic_task m_update_block_template_interval{5s};
|
||||
epee::math_helper::periodic_task m_update_merge_hr_interval{2s};
|
||||
epee::math_helper::periodic_task m_autodetect_interval{1s};
|
||||
std::vector<blobdata> m_extra_messages;
|
||||
miner_config m_config;
|
||||
std::string m_config_folder_path;
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace cryptonote
|
|||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
//! tuple of <deregister, transaction fee, receive time> for organization
|
||||
typedef std::pair<std::tuple<bool, double, std::time_t>, crypto::hash> tx_by_fee_and_receive_time_entry;
|
||||
|
||||
|
@ -713,7 +715,7 @@ namespace cryptonote
|
|||
|
||||
//TODO: this time should be a named constant somewhere, not hard-coded
|
||||
//! interval on which to check for stale/"stuck" transactions
|
||||
epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval;
|
||||
epee::math_helper::periodic_task m_remove_stuck_tx_interval{30s};
|
||||
|
||||
//TODO: look into doing this better
|
||||
//!< container for transactions organized by fee per size and receive time
|
||||
|
|
|
@ -57,6 +57,7 @@ DISABLE_VS_WARNINGS(4355)
|
|||
|
||||
namespace cryptonote
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
template<class t_core>
|
||||
class t_cryptonote_protocol_handler: public i_cryptonote_protocol
|
||||
|
@ -180,9 +181,9 @@ namespace cryptonote
|
|||
std::atomic<bool> m_no_sync;
|
||||
boost::mutex m_sync_lock;
|
||||
block_queue m_block_queue;
|
||||
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;
|
||||
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
|
||||
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
|
||||
epee::math_helper::periodic_task m_idle_peer_kicker{30s};
|
||||
epee::math_helper::periodic_task m_standby_checker{100ms};
|
||||
epee::math_helper::periodic_task m_sync_search_checker{101s};
|
||||
std::atomic<unsigned int> m_max_out_peers;
|
||||
tools::PerformanceTimer m_sync_timer, m_add_timer;
|
||||
uint64_t m_last_add_end_time;
|
||||
|
|
|
@ -61,6 +61,7 @@ DISABLE_VS_WARNINGS(4355)
|
|||
|
||||
namespace nodetool
|
||||
{
|
||||
using namespace std::literals;
|
||||
struct proxy
|
||||
{
|
||||
proxy()
|
||||
|
@ -440,11 +441,11 @@ namespace nodetool
|
|||
t_payload_net_handler& m_payload_handler;
|
||||
peerlist_storage m_peerlist_storage;
|
||||
|
||||
epee::math_helper::once_a_time_seconds<P2P_DEFAULT_HANDSHAKE_INTERVAL> m_peer_handshake_idle_maker_interval;
|
||||
epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval;
|
||||
epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
|
||||
epee::math_helper::once_a_time_seconds<60> m_gray_peerlist_housekeeping_interval;
|
||||
epee::math_helper::once_a_time_seconds<3600, false> m_incoming_connections_interval;
|
||||
epee::math_helper::periodic_task m_peer_handshake_idle_maker_interval{std::chrono::seconds{P2P_DEFAULT_HANDSHAKE_INTERVAL}};
|
||||
epee::math_helper::periodic_task m_connections_maker_interval{1s};
|
||||
epee::math_helper::periodic_task m_peerlist_store_interval{30min};
|
||||
epee::math_helper::periodic_task m_gray_peerlist_housekeeping_interval{1min};
|
||||
epee::math_helper::periodic_task m_incoming_connections_interval{1h};
|
||||
|
||||
uint64_t m_last_stat_request_time;
|
||||
std::list<epee::net_utils::network_address> m_priority_peers;
|
||||
|
|
|
@ -3035,6 +3035,8 @@ namespace cryptonote
|
|||
struct version_printer { const std::array<int, 3> &v; };
|
||||
std::ostream &operator<<(std::ostream &o, const version_printer &vp) { return o << vp.v[0] << '.' << vp.v[1] << '.' << vp.v[2]; }
|
||||
|
||||
// Handles a ping. Returns true if the ping was significant (i.e. first ping after startup, or
|
||||
// after the ping had expired).
|
||||
template <typename Response>
|
||||
bool handle_ping(const std::array<int, 3> &cur_version, const std::array<int, 3> &required, const char *name, std::atomic<std::time_t> &update, time_t lifetime, Response &res)
|
||||
{
|
||||
|
@ -3044,15 +3046,16 @@ namespace cryptonote
|
|||
res.status = status.str();
|
||||
MERROR(res.status);
|
||||
} else {
|
||||
auto now = std::time(nullptr);
|
||||
if (update + lifetime < now) // Print loudly for the first ping after startup/expiry
|
||||
MGINFO_GREEN("Received ping from " << name << " " << version_printer{cur_version});
|
||||
else
|
||||
MDEBUG("Accepted ping from " << name << " " << version_printer{cur_version});
|
||||
update = now;
|
||||
res.status = "OK";
|
||||
auto now = std::time(nullptr);
|
||||
auto old = update.exchange(now);
|
||||
if (old + lifetime < now) { // Print loudly for the first ping after startup/expiry
|
||||
MGINFO_GREEN("Received ping from " << name << " " << version_printer{cur_version});
|
||||
return true;
|
||||
}
|
||||
MDEBUG("Accepted ping from " << name << " " << version_printer{cur_version});
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3062,8 +3065,10 @@ namespace cryptonote
|
|||
epee::json_rpc::error&,
|
||||
const connection_context*)
|
||||
{
|
||||
return handle_ping({req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
|
||||
"Storage Server", m_core.m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME, res);
|
||||
if (handle_ping({req.version_major, req.version_minor, req.version_patch}, service_nodes::MIN_STORAGE_SERVER_VERSION,
|
||||
"Storage Server", m_core.m_last_storage_server_ping, STORAGE_SERVER_PING_LIFETIME, res))
|
||||
m_core.reset_proof_interval();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_lokinet_ping(const COMMAND_RPC_LOKINET_PING::request& req,
|
||||
|
@ -3071,7 +3076,10 @@ namespace cryptonote
|
|||
epee::json_rpc::error&,
|
||||
const connection_context*)
|
||||
{
|
||||
return handle_ping(req.version, service_nodes::MIN_LOKINET_VERSION, "Lokinet", m_core.m_last_lokinet_ping, LOKINET_PING_LIFETIME, res);
|
||||
if (handle_ping(req.version, service_nodes::MIN_LOKINET_VERSION,
|
||||
"Lokinet", m_core.m_last_lokinet_ping, LOKINET_PING_LIFETIME, res))
|
||||
m_core.reset_proof_interval();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_staking_requirement(const COMMAND_RPC_GET_STAKING_REQUIREMENT::request& req, COMMAND_RPC_GET_STAKING_REQUIREMENT::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
|
||||
|
|
Loading…
Reference in New Issue