aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Posen <jim.posen@gmail.com>2018-05-15 14:47:37 -0700
committerJim Posen <jim.posen@gmail.com>2018-06-04 19:22:23 -0700
commit61a1226d87d80234b2be123c5cad07534c318cfb (patch)
treeff6c3c24c4216afdebbf53432699173d30b22e77
parente5af5fc6fb4658599b940d1d50853129b31b8766 (diff)
index: Extract logic from TxIndex into reusable base class.
-rw-r--r--src/index/txindex.cpp40
-rw-r--r--src/index/txindex.h93
2 files changed, 80 insertions, 53 deletions
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<TxIndexDB> db) :
- m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr)
-{}
+TxIndex::TxIndex(std::unique_ptr<TxIndexDB> 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<const CBlock>& block, const CBlockIndex* pindex,
- const std::vector<CTransactionRef>& txn_conflicted)
+void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
+ const std::vector<CTransactionRef>& txn_conflicted)
{
if (!m_synced) {
return;
@@ -192,7 +198,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& 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<std::function<void()>>, "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<TxIndexDB> 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<bool> m_synced;
+ std::atomic<bool> m_synced{false};
- /// The last block in the chain that the TxIndex is in sync with.
- std::atomic<const CBlockIndex*> m_best_block_index;
+ /// The last block in the chain that the index is in sync with.
+ std::atomic<const CBlockIndex*> 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<TxIndexDB> 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<TxIndexDB> 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<TxIndexDB> 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<TxIndex> g_txindex;