diff --git a/CMakeLists.txt b/CMakeLists.txt index a9577f28..e6c0948f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,40 @@ cmake_minimum_required(VERSION 3.10) +if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo) +endif(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + +if(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + message("==> The configuration is ${CMAKE_BUILD_TYPE}. Debug info will be extracted into separate files.") + + function (add_executable _name) + _add_executable(${ARGV}) + + if (TARGET ${_name}) + add_custom_command(TARGET ${_name} POST_BUILD + COMMAND echo "$: extracting debug info" + COMMAND ${CMAKE_COMMAND} -E chdir $ objcopy --only-keep-debug "$" "$.debug" + COMMAND ${CMAKE_COMMAND} -E chdir $ strip --strip-debug --strip-unneeded "$" + COMMAND ${CMAKE_COMMAND} -E chdir $ objcopy --add-gnu-debuglink="$.debug" "$" + ) + endif() + endfunction() + + function (add_library _name _type) + _add_library(${ARGV}) + + if (TARGET ${_name} AND ${_type} STREQUAL SHARED) + add_custom_command(TARGET ${_name} POST_BUILD + COMMAND echo "$: extracting debug info" + COMMAND ${CMAKE_COMMAND} -E chdir $ objcopy --only-keep-debug "$" "$.debug" + COMMAND ${CMAKE_COMMAND} -E chdir $ strip --strip-debug --strip-unneeded "$" + COMMAND ${CMAKE_COMMAND} -E chdir $ objcopy --add-gnu-debuglink="$.debug" "$" + ) + endif() + endfunction() + +endif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + project(graft_server) option(OPT_BUILD_TESTS "Build tests." OFF) 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/rta/DaemonRpcClient.h b/include/rta/DaemonRpcClient.h index c2fdfc03..82465cfd 100644 --- a/include/rta/DaemonRpcClient.h +++ b/include/rta/DaemonRpcClient.h @@ -45,7 +45,8 @@ namespace graft { class DaemonRpcClient { public: - DaemonRpcClient(const std::string &daemon_addr, const std::string &daemon_login, const std::string &daemon_pass); + DaemonRpcClient(const std::string &daemon_addr, const std::string &daemon_login, const std::string &daemon_pass, + boost::shared_ptr ios); virtual ~DaemonRpcClient(); bool get_tx_from_pool(const std::string &hash_str, cryptonote::transaction &out_tx); bool get_tx(const std::string &hash_str, cryptonote::transaction &out_tx, uint64_t &block_num, bool &mined); diff --git a/include/rta/fullsupernodelist.h b/include/rta/fullsupernodelist.h index 2210745e..6712cefa 100644 --- a/include/rta/fullsupernodelist.h +++ b/include/rta/fullsupernodelist.h @@ -30,7 +30,7 @@ class FullSupernodeList static constexpr int64_t AUTH_SAMPLE_HASH_HEIGHT = 20; // block number for calculating auth sample should be calculated as current block height - AUTH_SAMPLE_HASH_HEIGHT; static constexpr int64_t ANNOUNCE_TTL_SECONDS = 60 * 60; // if more than ANNOUNCE_TTL_SECONDS passed from last annouce - supernode excluded from auth sample selection - FullSupernodeList(const std::string &daemon_address, bool testnet = false); + FullSupernodeList(const std::string &daemon_address, boost::shared_ptr ios, bool testnet = false); ~FullSupernodeList(); /** * @brief add - adds supernode object to a list and owns it. caller doesn't need to delete an object diff --git a/include/rta/supernode.h b/include/rta/supernode.h index 52985959..67084dc0 100644 --- a/include/rta/supernode.h +++ b/include/rta/supernode.h @@ -243,6 +243,8 @@ class Supernode bool busy() const; + static boost::shared_ptr getIoService() { return m_ioservice; } + private: Supernode(bool testnet = false); 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/modules/cryptonode b/modules/cryptonode index d365c8e2..62df68b5 160000 --- a/modules/cryptonode +++ b/modules/cryptonode @@ -1 +1 @@ -Subproject commit d365c8e28a0449d1f3b2a19909788fc95833bb1b +Subproject commit 62df68b5012e5a790036b9b1d49f166c4cc3c88a 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/rta/DaemonRpcClient.cpp b/src/rta/DaemonRpcClient.cpp index ce7d1ba2..3f261f7c 100644 --- a/src/rta/DaemonRpcClient.cpp +++ b/src/rta/DaemonRpcClient.cpp @@ -38,8 +38,10 @@ using namespace std; namespace graft { -DaemonRpcClient::DaemonRpcClient(const std::string &daemon_addr, const std::string &daemon_login, const std::string &daemon_pass) - : m_rpc_timeout(std::chrono::seconds(30)) +DaemonRpcClient::DaemonRpcClient(const std::string &daemon_addr, const std::string &daemon_login, const std::string &daemon_pass, + boost::shared_ptr ios) + : m_http_client(ios) + , m_rpc_timeout(std::chrono::seconds(30)) { boost::shared_mutex mutex; diff --git a/src/rta/fullsupernodelist.cpp b/src/rta/fullsupernodelist.cpp index dc07624d..d233afb3 100644 --- a/src/rta/fullsupernodelist.cpp +++ b/src/rta/fullsupernodelist.cpp @@ -123,10 +123,10 @@ constexpr int32_t FullSupernodeList::TIERS, FullSupernodeList::ITEMS_PER_TIER, F constexpr int64_t FullSupernodeList::AUTH_SAMPLE_HASH_HEIGHT, FullSupernodeList::ANNOUNCE_TTL_SECONDS; #endif -FullSupernodeList::FullSupernodeList(const string &daemon_address, bool testnet) +FullSupernodeList::FullSupernodeList(const string &daemon_address, boost::shared_ptr ios, bool testnet) : m_daemon_address(daemon_address) , m_testnet(testnet) - , m_rpc_client(daemon_address, "", "") + , m_rpc_client(daemon_address, "", "", ios) , m_tp(new utils::ThreadPool()) { m_refresh_counter = 0; diff --git a/src/supernode/supernode.cpp b/src/supernode/supernode.cpp index fea1f5a8..52badce0 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; } @@ -102,7 +103,8 @@ void Supernode::prepareDataDir() // create fullsupernode list instance and put it into global context graft::FullSupernodeListPtr fsl = boost::make_shared( - m_configEx.cryptonode_rpc_address, m_configEx.testnet); + m_configEx.cryptonode_rpc_address, graft::Supernode::getIoService(), + m_configEx.testnet); fsl->add(supernode); @@ -137,7 +139,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/src/version.h.in b/src/version.h.in index 4f7b12cd..f5adea4b 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define GRAFT_SUPERNODE_VERSION_TAG "@VERSIONTAG@" -#define GRAFT_SUPERNODE_VERSION "0.4.1" +#define GRAFT_SUPERNODE_VERSION "0.4.2" #define GRAFT_SUPERNODE_RELEASE_NAME "" #define GRAFT_SUPERNODE_VERSION_FULL GRAFT_SUPERNODE_VERSION "-" GRAFT_SUPERNODE_VERSION_TAG diff --git a/test/graft_server_test.cpp b/test/graft_server_test.cpp index 50983b5e..63e13124 100644 --- a/test/graft_server_test.cpp +++ b/test/graft_server_test.cpp @@ -1256,7 +1256,7 @@ TEST_F(GraftServerTest, genericCallback) case graft::Status::None: { //find webhook endpoint - auto it = std::find_if(input.headers.begin(), input.headers.end(), [](auto& v)->bool { v.first == "X-Callback"; } ); + auto it = std::find_if(input.headers.begin(), input.headers.end(), [](auto& v)->bool { return v.first == "X-Callback"; } ); assert(it != input.headers.end()); std::string path = it->second; //"http://0.0.0.0:port/callback/" 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;