From 70d510d93c08a168407f55c932ab09c644dea3b8 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 8 Dec 2017 10:52:42 -0800 Subject: [PATCH] [index] Allow TxIndex sync thread to be interrupted. --- src/index/txindex.cpp | 16 ++++++++++++++++ src/index/txindex.h | 14 +++++++++++--- src/threadinterrupt.cpp | 2 ++ src/threadinterrupt.h | 1 + 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 56966021a90..82798fbcc1c 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -30,6 +30,12 @@ TxIndex::TxIndex(std::unique_ptr db) : m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr) {} +TxIndex::~TxIndex() +{ + Interrupt(); + Stop(); +} + bool TxIndex::Init() { LOCK(cs_main); @@ -76,6 +82,11 @@ void TxIndex::ThreadSync() int64_t last_log_time = 0; int64_t last_locator_write_time = 0; while (true) { + if (m_interrupt) { + WriteBestBlock(pindex); + return; + } + { LOCK(cs_main); const CBlockIndex* pindex_next = NextSyncBlock(pindex); @@ -222,6 +233,11 @@ bool TxIndex::FindTx(const uint256& txid, CDiskTxPos& pos) const return m_db->ReadTxPos(txid, pos); } +void TxIndex::Interrupt() +{ + m_interrupt(); +} + void TxIndex::Start() { // Need to register this ValidationInterface before running Init(), so that diff --git a/src/index/txindex.h b/src/index/txindex.h index 35d58d5b656..633aee46ceb 100644 --- a/src/index/txindex.h +++ b/src/index/txindex.h @@ -6,6 +6,7 @@ #define BITCOIN_INDEX_TXINDEX_H #include +#include #include #include #include @@ -31,14 +32,16 @@ private: std::atomic m_best_block_index; std::thread m_thread_sync; + CThreadInterrupt m_interrupt; /// Initialize internal state from the database and block index. bool Init(); /// Sync the tx index with the block index starting from the current best - /// block. Intended to be run in its own thread, m_thread_sync. Once the - /// txindex gets in sync, the m_synced flag is set and the BlockConnected - /// ValidationInterface callback takes over and the sync thread exits. + /// block. Intended to be run in its own thread, m_thread_sync, and can be + /// interrupted with m_interrupt. Once the txindex gets in sync, the + /// m_synced flag is set and the BlockConnected ValidationInterface callback + /// takes over and the sync thread exits. void ThreadSync(); /// Write update index entries for a newly connected block. @@ -57,9 +60,14 @@ public: /// Constructs the TxIndex, which becomes available to be queried. explicit TxIndex(std::unique_ptr db); + /// Destructor interrupts sync thread if running and blocks until it exits. + ~TxIndex(); + /// Look up the on-disk location of a transaction by hash. bool FindTx(const uint256& txid, CDiskTxPos& pos) const; + void Interrupt(); + /// Start initializes the sync state and registers the instance as a /// ValidationInterface so that it stays in sync with blockchain updates. void Start(); diff --git a/src/threadinterrupt.cpp b/src/threadinterrupt.cpp index 5d932091cbb..7da4e136ef5 100644 --- a/src/threadinterrupt.cpp +++ b/src/threadinterrupt.cpp @@ -5,6 +5,8 @@ #include +CThreadInterrupt::CThreadInterrupt() : flag(false) {} + CThreadInterrupt::operator bool() const { return flag.load(std::memory_order_acquire); diff --git a/src/threadinterrupt.h b/src/threadinterrupt.h index 54e31028089..d373e3c371e 100644 --- a/src/threadinterrupt.h +++ b/src/threadinterrupt.h @@ -18,6 +18,7 @@ class CThreadInterrupt { public: + CThreadInterrupt(); explicit operator bool() const; void operator()(); void reset();