diff --git a/data/config.ini b/data/config.ini index 948d4978..99ff30ca 100644 --- a/data/config.ini +++ b/data/config.ini @@ -30,6 +30,7 @@ data-dir= stake-wallet-name=stake-wallet testnet=true stake-wallet-refresh-interval-ms=50000 +stake-wallet-refresh-interval-random-factor=0 [ipfilter] ;; path to ipfilter rules file diff --git a/include/lib/graft/common/utils.h b/include/lib/graft/common/utils.h index 5c1e3f25..6fe439cc 100644 --- a/include/lib/graft/common/utils.h +++ b/include/lib/graft/common/utils.h @@ -12,8 +12,7 @@ std::string base64_encode(const std::string &data); template T random_number(T startRange, T endRange) { - std::random_device rd; - std::mt19937 mt(rd()); + static std::mt19937 mt(std::random_device{}()); std::uniform_int_distribution dist(startRange, endRange); return dist(mt); } diff --git a/include/lib/graft/handler_api.h b/include/lib/graft/handler_api.h index 6c9b0092..18cee9fe 100644 --- a/include/lib/graft/handler_api.h +++ b/include/lib/graft/handler_api.h @@ -13,8 +13,9 @@ class HandlerAPI public: virtual void sendUpstreamBlocking(Output& output, Input& input, std::string& err) = 0; virtual bool addPeriodicTask(const Router::Handler& h_worker, - std::chrono::milliseconds interval_ms, - std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max()) = 0; + std::chrono::milliseconds interval_ms, + std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max(), + double random_factor = 0) = 0; virtual request::system_info::Counter& runtimeSysInfo() = 0; virtual const ConfigOpts& configOpts() const = 0; }; diff --git a/include/lib/graft/task.h b/include/lib/graft/task.h index 6fc8f1ad..65f438bb 100644 --- a/include/lib/graft/task.h +++ b/include/lib/graft/task.h @@ -153,19 +153,23 @@ class PeriodicTask : public BaseTask PeriodicTask( TaskManager& manager, const Router::Handler3& h3, std::chrono::milliseconds timeout_ms, - std::chrono::milliseconds initial_timeout_ms + std::chrono::milliseconds initial_timeout_ms, + double random_factor = 0 ) : BaseTask(manager, Router::JobParams({Input(), Router::vars_t(), h3})) , m_timeout_ms(timeout_ms), m_initial_timeout_ms(initial_timeout_ms) + , m_random_factor(random_factor) { } - PeriodicTask(TaskManager& manager, const Router::Handler3& h3, std::chrono::milliseconds timeout_ms) - : PeriodicTask(manager, h3, timeout_ms, timeout_ms) + PeriodicTask(TaskManager& manager, const Router::Handler3& h3, + std::chrono::milliseconds timeout_ms, double random_factor = 0) + : PeriodicTask(manager, h3, timeout_ms, timeout_ms, random_factor) { } std::chrono::milliseconds m_timeout_ms; std::chrono::milliseconds m_initial_timeout_ms; + double m_random_factor; bool m_initial_run {true}; public: @@ -199,7 +203,9 @@ class TaskManager : private HandlerAPI void sendUpstream(BaseTaskPtr bt); void addPeriodicTask(const Router::Handler3& h3, - std::chrono::milliseconds interval_ms, std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max()); + std::chrono::milliseconds interval_ms, + std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max(), + double random_factor = 0); ////getters virtual mg_mgr* getMgMgr() = 0; @@ -220,7 +226,8 @@ class TaskManager : private HandlerAPI virtual void sendUpstreamBlocking(Output& output, Input& input, std::string& err) override; virtual bool addPeriodicTask(const Router::Handler& h_worker, std::chrono::milliseconds interval_ms, - std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max()) override; + std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max(), + double random_factor = 0 ) override; virtual request::system_info::Counter& runtimeSysInfo() override; virtual const ConfigOpts& configOpts() const override; @@ -282,7 +289,7 @@ class TaskManager : private HandlerAPI using PromiseItem = UpstreamTask::PromiseItem; using PromiseQueue = tp::MPMCBoundedQueue; - using PeridicTaskItem = std::tuple; + using PeridicTaskItem = std::tuple; using PeriodicTaskQueue = tp::MPMCBoundedQueue; std::unique_ptr m_promiseQueue; diff --git a/include/supernode/supernode.h b/include/supernode/supernode.h index 09e2003a..64c038ca 100644 --- a/include/supernode/supernode.h +++ b/include/supernode/supernode.h @@ -13,6 +13,7 @@ class Supernode : public GraftServer std::string data_dir; std::string stake_wallet_name; size_t stake_wallet_refresh_interval_ms; + double stake_wallet_refresh_interval_random_factor; // runtime parameters. // path to watch-only wallets (supernodes) std::string watchonly_wallets_path; diff --git a/src/lib/graft/task.cpp b/src/lib/graft/task.cpp index 768c45b9..af83d445 100644 --- a/src/lib/graft/task.cpp +++ b/src/lib/graft/task.cpp @@ -6,6 +6,7 @@ #include "lib/graft/handler_api.h" #include "lib/graft/expiring_list.h" #include "lib/graft/sys_info.h" +#include "lib/graft/common/utils.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "supernode.task" @@ -419,17 +420,18 @@ inline size_t TaskManager::next_pow2(size_t val) } bool TaskManager::addPeriodicTask(const Router::Handler& h_worker, - std::chrono::milliseconds interval_ms, - std::chrono::milliseconds initial_interval_ms) + std::chrono::milliseconds interval_ms, + std::chrono::milliseconds initial_interval_ms, + double random_factor) { if(io_thread) {//it is called from pre_action or post_action, and we can call requestAddPeriodicTask directly - addPeriodicTask({nullptr, h_worker, nullptr}, interval_ms, initial_interval_ms); + addPeriodicTask({nullptr, h_worker, nullptr}, interval_ms, initial_interval_ms, random_factor); return true; } else { - PeridicTaskItem item = std::make_tuple(Router::Handler3(nullptr, h_worker, nullptr), interval_ms, initial_interval_ms); + PeridicTaskItem item = std::make_tuple(Router::Handler3(nullptr, h_worker, nullptr), interval_ms, initial_interval_ms, random_factor); bool ok = m_periodicTaskQueue->push( std::move(item) ); if(!ok) return false; notifyJobReady(); @@ -457,7 +459,8 @@ void TaskManager::checkPeriodicTaskIO() Router::Handler3& h3 = std::get<0>(pti); std::chrono::milliseconds& interval_ms = std::get<1>(pti); std::chrono::milliseconds& initial_interval_ms = std::get<2>(pti); - addPeriodicTask(h3, interval_ms, initial_interval_ms); + double& random_factor = std::get<3>(pti); + addPeriodicTask(h3, interval_ms, initial_interval_ms, random_factor); } } @@ -816,11 +819,11 @@ void TaskManager::processOk(BaseTaskPtr bt) } void TaskManager::addPeriodicTask( - const Router::Handler3& h3, std::chrono::milliseconds interval_ms, std::chrono::milliseconds initial_interval_ms) + const Router::Handler3& h3, std::chrono::milliseconds interval_ms, std::chrono::milliseconds initial_interval_ms, double random_factor) { if(initial_interval_ms == std::chrono::milliseconds::max()) initial_interval_ms = interval_ms; - BaseTask* bt = BaseTask::Create(*this, h3, interval_ms, initial_interval_ms).get(); + BaseTask* bt = BaseTask::Create(*this, h3, interval_ms, initial_interval_ms, random_factor).get(); PeriodicTask* pt = dynamic_cast(bt); assert(pt); schedule(pt); @@ -976,9 +979,15 @@ void PeriodicTask::finalize() std::chrono::milliseconds PeriodicTask::getTimeout() { - auto ret = (m_initial_run) ? m_initial_timeout_ms : m_timeout_ms; - m_initial_run = false; - return ret; + if(m_initial_run) + { + m_initial_run = false; + return m_initial_timeout_ms; + } + if(m_random_factor < 0.0001) return m_timeout_ms; + using i_type = decltype(m_timeout_ms.count()); + i_type v = graft::utils::random_number(m_timeout_ms.count(), (i_type)(m_timeout_ms.count()*(1.0 + m_random_factor))); + return std::chrono::milliseconds(v); } ClientTask::ClientTask(ConnectionManager* connectionManager, mg_connection *client, Router::JobParams& prms) diff --git a/src/supernode/supernode.cpp b/src/supernode/supernode.cpp index fea1f5a8..4da8f793 100644 --- a/src/supernode/supernode.cpp +++ b/src/supernode/supernode.cpp @@ -51,6 +51,7 @@ bool Supernode::initConfigOption(int argc, const char** argv, ConfigOpts& config m_configEx.stake_wallet_refresh_interval_ms = server_conf.get("stake-wallet-refresh-interval-ms", consts::DEFAULT_STAKE_WALLET_REFRESH_INTERFAL_MS); m_configEx.testnet = server_conf.get("testnet", false); + m_configEx.stake_wallet_refresh_interval_random_factor = server_conf.get("stake-wallet-refresh-interval-random-factor", 0); return res; } @@ -137,7 +138,8 @@ void Supernode::startSupernodePeriodicTasks() getLooper().addPeriodicTask( graft::Router::Handler3(nullptr, graft::supernode::request::sendAnnounce, nullptr), std::chrono::milliseconds(m_configEx.stake_wallet_refresh_interval_ms), - std::chrono::milliseconds(initial_interval_ms) + std::chrono::milliseconds(initial_interval_ms), + m_configEx.stake_wallet_refresh_interval_random_factor ); } } diff --git a/test/sys_info.cpp b/test/sys_info.cpp index 3b18a41d..845a10bf 100644 --- a/test/sys_info.cpp +++ b/test/sys_info.cpp @@ -151,8 +151,9 @@ class HandlerAPIImpl : public graft::HandlerAPI public: virtual void sendUpstreamBlocking(Output& output, Input& input, std::string& err) override { } virtual bool addPeriodicTask(const Router::Handler& h_worker, - std::chrono::milliseconds interval_ms, - std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max()) override { } + std::chrono::milliseconds interval_ms, + std::chrono::milliseconds initial_interval_ms = std::chrono::milliseconds::max(), + double random_factor = 0) override { } virtual graft::request::system_info::Counter& runtimeSysInfo() override { return m_sic;