From 61a1226d87d80234b2be123c5cad07534c318cfb Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 15 May 2018 14:47:37 -0700 Subject: index: Extract logic from TxIndex into reusable base class. --- src/index/txindex.cpp | 40 ++++++++++++---------- src/index/txindex.h | 93 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 80 insertions(+), 53 deletions(-) (limited to 'src/index') diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 3ff16b7664..90de0fde97 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -28,11 +28,9 @@ static void FatalError(const char* fmt, const Args&... args) StartShutdown(); } -TxIndex::TxIndex(std::unique_ptr db) : - m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr) -{} +TxIndex::TxIndex(std::unique_ptr db) : m_db(std::move(db)) {} -TxIndex::~TxIndex() +BaseIndex::~BaseIndex() { Interrupt(); Stop(); @@ -49,11 +47,17 @@ bool TxIndex::Init() return false; } + return BaseIndex::Init(); +} + +bool BaseIndex::Init() +{ CBlockLocator locator; - if (!m_db->ReadBestBlock(locator)) { + if (!GetDB().ReadBestBlock(locator)) { locator.SetNull(); } + LOCK(cs_main); m_best_block_index = FindForkInGlobalIndex(chainActive, locator); m_synced = m_best_block_index.load() == chainActive.Tip(); return true; @@ -75,7 +79,7 @@ static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev) return chainActive.Next(chainActive.FindFork(pindex_prev)); } -void TxIndex::ThreadSync() +void BaseIndex::ThreadSync() { const CBlockIndex* pindex = m_best_block_index.load(); if (!m_synced) { @@ -145,17 +149,19 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex) return m_db->WriteTxs(vPos); } -bool TxIndex::WriteBestBlock(const CBlockIndex* block_index) +BaseIndexDB& TxIndex::GetDB() const { return *m_db; } + +bool BaseIndex::WriteBestBlock(const CBlockIndex* block_index) { LOCK(cs_main); - if (!m_db->WriteBestBlock(chainActive.GetLocator(block_index))) { + if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) { return error("%s: Failed to write locator to disk", __func__); } return true; } -void TxIndex::BlockConnected(const std::shared_ptr& block, const CBlockIndex* pindex, - const std::vector& txn_conflicted) +void BaseIndex::BlockConnected(const std::shared_ptr& block, const CBlockIndex* pindex, + const std::vector& txn_conflicted) { if (!m_synced) { return; @@ -192,7 +198,7 @@ void TxIndex::BlockConnected(const std::shared_ptr& block, const C } } -void TxIndex::ChainStateFlushed(const CBlockLocator& locator) +void BaseIndex::ChainStateFlushed(const CBlockLocator& locator) { if (!m_synced) { return; @@ -225,12 +231,12 @@ void TxIndex::ChainStateFlushed(const CBlockLocator& locator) return; } - if (!m_db->WriteBestBlock(locator)) { + if (!GetDB().WriteBestBlock(locator)) { error("%s: Failed to write locator to disk", __func__); } } -bool TxIndex::BlockUntilSyncedToCurrentChain() +bool BaseIndex::BlockUntilSyncedToCurrentChain() { AssertLockNotHeld(cs_main); @@ -282,12 +288,12 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe return true; } -void TxIndex::Interrupt() +void BaseIndex::Interrupt() { m_interrupt(); } -void TxIndex::Start() +void BaseIndex::Start() { // Need to register this ValidationInterface before running Init(), so that // callbacks are not missed if Init sets m_synced to true. @@ -298,10 +304,10 @@ void TxIndex::Start() } m_thread_sync = std::thread(&TraceThread>, "txindex", - std::bind(&TxIndex::ThreadSync, this)); + std::bind(&BaseIndex::ThreadSync, this)); } -void TxIndex::Stop() +void BaseIndex::Stop() { UnregisterValidationInterface(this); diff --git a/src/index/txindex.h b/src/index/txindex.h index 4937bd64e9..f38d845998 100644 --- a/src/index/txindex.h +++ b/src/index/txindex.h @@ -15,39 +15,31 @@ class CBlockIndex; /** - * TxIndex is used to look up transactions included in the blockchain by hash. - * The index is written to a LevelDB database and records the filesystem - * location of each transaction by transaction hash. + * Base class for indices of blockchain data. This implements + * CValidationInterface and ensures blocks are indexed sequentially according + * to their position in the active chain. */ -class TxIndex final : public CValidationInterface +class BaseIndex : public CValidationInterface { private: - const std::unique_ptr m_db; - /// Whether the index is in sync with the main chain. The flag is flipped /// from false to true once, after which point this starts processing /// ValidationInterface notifications to stay in sync. - std::atomic m_synced; + std::atomic m_synced{false}; - /// The last block in the chain that the TxIndex is in sync with. - std::atomic m_best_block_index; + /// The last block in the chain that the index is in sync with. + std::atomic m_best_block_index{nullptr}; 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, 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. + /// Sync the index with the block index starting from the current best block. + /// Intended to be run in its own thread, m_thread_sync, and can be + /// interrupted with m_interrupt. Once the index 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. - bool WriteBlock(const CBlock& block, const CBlockIndex* pindex); - /// Write the current chain block locator to the DB. bool WriteBestBlock(const CBlockIndex* block_index); @@ -57,27 +49,25 @@ protected: void ChainStateFlushed(const CBlockLocator& locator) override; -public: - /// Constructs the TxIndex, which becomes available to be queried. - explicit TxIndex(std::unique_ptr db); + /// Initialize internal state from the database and block index. + virtual bool Init(); + /// Write update index entries for a newly connected block. + virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; } + + virtual BaseIndexDB& GetDB() const = 0; + +public: /// Destructor interrupts sync thread if running and blocks until it exits. - ~TxIndex(); + virtual ~BaseIndex(); - /// Blocks the current thread until the transaction index is caught up to - /// the current state of the block chain. This only blocks if the index has gotten in sync once - /// and only needs to process blocks in the ValidationInterface queue. If the index is catching - /// up from far behind, this method does not block and immediately returns false. + /// Blocks the current thread until the index is caught up to the current + /// state of the block chain. This only blocks if the index has gotten in + /// sync once and only needs to process blocks in the ValidationInterface + /// queue. If the index is catching up from far behind, this method does + /// not block and immediately returns false. bool BlockUntilSyncedToCurrentChain(); - /// Look up a transaction by hash. - /// - /// @param[in] tx_hash The hash of the transaction to be returned. - /// @param[out] block_hash The hash of the block the transaction is found in. - /// @param[out] tx The transaction itself. - /// @return true if transaction is found, false otherwise - bool FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const; - void Interrupt(); /// Start initializes the sync state and registers the instance as a @@ -88,6 +78,37 @@ public: void Stop(); }; +/** + * TxIndex is used to look up transactions included in the blockchain by hash. + * The index is written to a LevelDB database and records the filesystem + * location of each transaction by transaction hash. + */ +class TxIndex final : public BaseIndex +{ +private: + const std::unique_ptr m_db; + +protected: + /// Override base class init to migrate from old database. + bool Init() override; + + bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override; + + BaseIndexDB& GetDB() const override; + +public: + /// Constructs the index, which becomes available to be queried. + explicit TxIndex(std::unique_ptr db); + + /// Look up a transaction by hash. + /// + /// @param[in] tx_hash The hash of the transaction to be returned. + /// @param[out] block_hash The hash of the block the transaction is found in. + /// @param[out] tx The transaction itself. + /// @return true if transaction is found, false otherwise + bool FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const; +}; + /// The global transaction index, used in GetTransaction. May be null. extern std::unique_ptr g_txindex; -- cgit v1.2.3