rpc: add a flush_cache RPC

This allows flushing internal caches (for now, the bad tx cache,
which will allow debugging a stuck monerod after it has failed to
verify a transaction in a block, since it would otherwise not try
again, making subsequent log changes pointless)
This commit is contained in:
moneromooo-monero 2019-10-22 15:28:08 +00:00
parent 960c215801
commit a4dc575ccb
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
11 changed files with 103 additions and 7 deletions

View file

@ -1911,6 +1911,14 @@ namespace cryptonote
return true; return true;
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
void core::flush_bad_txs_cache()
{
bad_semantics_txes_lock.lock();
for (int idx = 0; idx < 2; ++idx)
bad_semantics_txes[idx].clear();
bad_semantics_txes_lock.unlock();
}
//-----------------------------------------------------------------------------------------------
bool core::update_blockchain_pruning() bool core::update_blockchain_pruning()
{ {
return m_blockchain_storage.update_blockchain_pruning(); return m_blockchain_storage.update_blockchain_pruning();

View file

@ -839,6 +839,11 @@ namespace cryptonote
*/ */
bool has_block_weights(uint64_t height, uint64_t nblocks) const; bool has_block_weights(uint64_t height, uint64_t nblocks) const;
/**
* @brief flushes the bad txs cache
*/
void flush_bad_txs_cache();
private: private:
/** /**

View file

@ -844,4 +844,16 @@ bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::stri
args_count > 2 ? args[2] : std::string()); args_count > 2 ? args[2] : std::string());
} }
bool t_command_parser_executor::flush_cache(const std::vector<std::string>& args)
{
if (args.empty())
goto show_list;
if (args[0] == "bad-txs")
return m_executor.flush_cache(true);
show_list:
std::cout << "Cache type needed: bad-txs" << std::endl;
return true;
}
} // namespace daemonize } // namespace daemonize

View file

@ -154,6 +154,8 @@ public:
bool print_net_stats(const std::vector<std::string>& args); bool print_net_stats(const std::vector<std::string>& args);
bool set_bootstrap_daemon(const std::vector<std::string>& args); bool set_bootstrap_daemon(const std::vector<std::string>& args);
bool flush_cache(const std::vector<std::string>& args);
}; };
} // namespace daemonize } // namespace daemonize

View file

@ -322,6 +322,12 @@ t_command_server::t_command_server(
, "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n" , "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced.\n"
"Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching" "Use 'auto' to enable automatic public nodes discovering and bootstrap daemon switching"
); );
m_command_lookup.set_handler(
"flush_cache"
, std::bind(&t_command_parser_executor::flush_cache, &m_parser, p::_1)
, "flush_cache bad-txs"
, "Flush the specified cache(s)."
);
} }
bool t_command_server::process_command_str(const std::string& cmd) bool t_command_server::process_command_str(const std::string& cmd)

View file

@ -2373,6 +2373,34 @@ bool t_rpc_command_executor::set_bootstrap_daemon(
return true; return true;
} }
bool t_rpc_command_executor::flush_cache(bool bad_txs)
{
cryptonote::COMMAND_RPC_FLUSH_CACHE::request req;
cryptonote::COMMAND_RPC_FLUSH_CACHE::response res;
std::string fail_message = "Unsuccessful";
epee::json_rpc::error error_resp;
req.bad_txs = bad_txs;
if (m_is_rpc)
{
if (!m_rpc_client->json_rpc_request(req, res, "flush_cache", fail_message.c_str()))
{
return true;
}
}
else
{
if (!m_rpc_server->on_flush_cache(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
return true;
}
bool t_rpc_command_executor::rpc_payments() bool t_rpc_command_executor::rpc_payments()
{ {
cryptonote::COMMAND_RPC_ACCESS_DATA::request req; cryptonote::COMMAND_RPC_ACCESS_DATA::request req;

View file

@ -169,6 +169,8 @@ public:
const std::string &password); const std::string &password);
bool rpc_payments(); bool rpc_payments();
bool flush_cache(bool bad_txs);
}; };
} // namespace daemonize } // namespace daemonize

View file

@ -2995,10 +2995,18 @@ namespace cryptonote
return true; return true;
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_flush_cache(const COMMAND_RPC_FLUSH_CACHE::request& req, COMMAND_RPC_FLUSH_CACHE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(flush_cache);
if (req.bad_txs)
m_core.flush_bad_txs_cache();
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx) bool core_rpc_server::on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{ {
RPC_TRACKER(rpc_access_submit_nonce); RPC_TRACKER(rpc_access_submit_nonce);
bool r; bool r;
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_SUBMIT_NONCE>(invoke_http_mode::JON, "rpc_access_submit_nonce", req, res, r)) if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_ACCESS_SUBMIT_NONCE>(invoke_http_mode::JON, "rpc_access_submit_nonce", req, res, r))
return r; return r;

View file

@ -174,6 +174,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG) MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG)
MAP_JON_RPC_WE("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION) MAP_JON_RPC_WE("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION)
MAP_JON_RPC_WE_IF("prune_blockchain", on_prune_blockchain, COMMAND_RPC_PRUNE_BLOCKCHAIN, !m_restricted) MAP_JON_RPC_WE_IF("prune_blockchain", on_prune_blockchain, COMMAND_RPC_PRUNE_BLOCKCHAIN, !m_restricted)
MAP_JON_RPC_WE_IF("flush_cache", on_flush_cache, COMMAND_RPC_FLUSH_CACHE, !m_restricted)
MAP_JON_RPC_WE("rpc_access_info", on_rpc_access_info, COMMAND_RPC_ACCESS_INFO) MAP_JON_RPC_WE("rpc_access_info", on_rpc_access_info, COMMAND_RPC_ACCESS_INFO)
MAP_JON_RPC_WE("rpc_access_submit_nonce",on_rpc_access_submit_nonce, COMMAND_RPC_ACCESS_SUBMIT_NONCE) MAP_JON_RPC_WE("rpc_access_submit_nonce",on_rpc_access_submit_nonce, COMMAND_RPC_ACCESS_SUBMIT_NONCE)
MAP_JON_RPC_WE("rpc_access_pay", on_rpc_access_pay, COMMAND_RPC_ACCESS_PAY) MAP_JON_RPC_WE("rpc_access_pay", on_rpc_access_pay, COMMAND_RPC_ACCESS_PAY)
@ -247,6 +248,7 @@ namespace cryptonote
bool on_get_txpool_backlog(const COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_get_txpool_backlog(const COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_output_distribution(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_get_output_distribution(const COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request& req, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_prune_blockchain(const COMMAND_RPC_PRUNE_BLOCKCHAIN::request& req, COMMAND_RPC_PRUNE_BLOCKCHAIN::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_prune_blockchain(const COMMAND_RPC_PRUNE_BLOCKCHAIN::request& req, COMMAND_RPC_PRUNE_BLOCKCHAIN::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_flush_cache(const COMMAND_RPC_FLUSH_CACHE::request& req, COMMAND_RPC_FLUSH_CACHE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_info(const COMMAND_RPC_ACCESS_INFO::request& req, COMMAND_RPC_ACCESS_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_rpc_access_info(const COMMAND_RPC_ACCESS_INFO::request& req, COMMAND_RPC_ACCESS_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_rpc_access_submit_nonce(const COMMAND_RPC_ACCESS_SUBMIT_NONCE::request& req, COMMAND_RPC_ACCESS_SUBMIT_NONCE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_rpc_access_pay(const COMMAND_RPC_ACCESS_PAY::request& req, COMMAND_RPC_ACCESS_PAY::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL); bool on_rpc_access_pay(const COMMAND_RPC_ACCESS_PAY::request& req, COMMAND_RPC_ACCESS_PAY::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);

View file

@ -2554,4 +2554,27 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response; typedef epee::misc_utils::struct_init<response_t> response;
}; };
struct COMMAND_RPC_FLUSH_CACHE
{
struct request_t
{
bool bad_txs;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(bad_txs, false)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
} }

View file

@ -516,16 +516,16 @@ class Daemon(object):
} }
return self.rpc.send_json_rpc_request(prune_blockchain) return self.rpc.send_json_rpc_request(prune_blockchain)
def get_block_rate(self, seconds = [3600]): def flush_cache(self, bad_txs = False):
get_block_rate = { flush_cache = {
'method': 'get_block_rate', 'method': 'flush_cache',
'params': { 'params': {
'seconds': seconds, 'bad_txs': bad_txs,
}, },
'jsonrpc': '2.0', 'jsonrpc': '2.0',
'id': '0' 'id': '0'
} }
return self.rpc.send_json_rpc_request(get_block_rate) return self.rpc.send_json_rpc_request(flush_cache)
def rpc_access_info(self, client): def rpc_access_info(self, client):
rpc_access_info = { rpc_access_info = {