Merge #19056: rpc: Make gettxoutsetinfo/GetUTXOStats interruptible

fa756928c3 rpc: Make gettxoutsetinfo/GetUTXOStats interruptible (MarcoFalke)
fa7fc5a8e0 rpc: factor out RpcInterruptionPoint from dumptxoutset (MarcoFalke)

Pull request description:

  Make it interruptible, so that shutdown doesn't block for up to one hour.

  Fixes (partially) #13217

ACKs for top commit:
  Empact:
    Code Review ACK fa756928c3
  laanwj:
    Code review ACK fa756928c3

Tree-SHA512: 298261e0ff7d79fab542b8f6828cc0ac451cbafe396d5f0816c9d36437faba1330f5c4cb2a25c5540e202bfb9783da6ec858bd453056ce488d21e36335d3d42c
This commit is contained in:
MarcoFalke
2020-05-26 07:32:14 -04:00
5 changed files with 18 additions and 9 deletions

View File

@@ -996,7 +996,7 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
::ChainstateActive().ForceFlushStateToDisk();
CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
if (GetUTXOStats(coins_view, stats)) {
if (GetUTXOStats(coins_view, stats, RpcInterruptionPoint)) {
ret.pushKV("height", (int64_t)stats.nHeight);
ret.pushKV("bestblock", stats.hashBlock.GetHex());
ret.pushKV("transactions", (int64_t)stats.nTransactions);
@@ -1974,6 +1974,7 @@ bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>&
Coin coin;
if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false;
if (++count % 8192 == 0) {
RpcInterruptionPoint();
if (should_abort) {
// allow to abort the scan via the abort reference
return false;
@@ -2317,7 +2318,7 @@ UniValue dumptxoutset(const JSONRPCRequest& request)
::ChainstateActive().ForceFlushStateToDisk();
if (!GetUTXOStats(&::ChainstateActive().CoinsDB(), stats)) {
if (!GetUTXOStats(&::ChainstateActive().CoinsDB(), stats, RpcInterruptionPoint)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
}
@@ -2335,9 +2336,7 @@ UniValue dumptxoutset(const JSONRPCRequest& request)
unsigned int iter{0};
while (pcursor->Valid()) {
if (iter % 5000 == 0 && !IsRPCRunning()) {
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
}
if (iter % 5000 == 0) RpcInterruptionPoint();
++iter;
if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
afile << key;

View File

@@ -11,9 +11,9 @@
#include <util/strencodings.h>
#include <util/system.h>
#include <boost/signals2/signal.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/signals2/signal.hpp>
#include <memory> // for unique_ptr
#include <unordered_map>
@@ -309,6 +309,11 @@ bool IsRPCRunning()
return g_rpc_running;
}
void RpcInterruptionPoint()
{
if (!IsRPCRunning()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
}
void SetRPCWarmupStatus(const std::string& newStatus)
{
LOCK(cs_rpcWarmup);

View File

@@ -9,10 +9,10 @@
#include <amount.h>
#include <rpc/request.h>
#include <functional>
#include <map>
#include <stdint.h>
#include <string>
#include <functional>
#include <univalue.h>
@@ -29,6 +29,9 @@ namespace RPCServer
/** Query whether RPC is running */
bool IsRPCRunning();
/** Throw JSONRPCError if RPC is not running */
void RpcInterruptionPoint();
/**
* Set the RPC warmup status. When this is done, all RPC calls will error out
* immediately with RPC_IN_WARMUP.