Skip to content

Commit 61a1226

Browse files
committed
index: Extract logic from TxIndex into reusable base class.
1 parent e5af5fc commit 61a1226

File tree

2 files changed

+80
-53
lines changed

2 files changed

+80
-53
lines changed

src/index/txindex.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ static void FatalError(const char* fmt, const Args&... args)
2828
StartShutdown();
2929
}
3030

31-
TxIndex::TxIndex(std::unique_ptr<TxIndexDB> db) :
32-
m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr)
33-
{}
31+
TxIndex::TxIndex(std::unique_ptr<TxIndexDB> db) : m_db(std::move(db)) {}
3432

35-
TxIndex::~TxIndex()
33+
BaseIndex::~BaseIndex()
3634
{
3735
Interrupt();
3836
Stop();
@@ -49,11 +47,17 @@ bool TxIndex::Init()
4947
return false;
5048
}
5149

50+
return BaseIndex::Init();
51+
}
52+
53+
bool BaseIndex::Init()
54+
{
5255
CBlockLocator locator;
53-
if (!m_db->ReadBestBlock(locator)) {
56+
if (!GetDB().ReadBestBlock(locator)) {
5457
locator.SetNull();
5558
}
5659

60+
LOCK(cs_main);
5761
m_best_block_index = FindForkInGlobalIndex(chainActive, locator);
5862
m_synced = m_best_block_index.load() == chainActive.Tip();
5963
return true;
@@ -75,7 +79,7 @@ static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev)
7579
return chainActive.Next(chainActive.FindFork(pindex_prev));
7680
}
7781

78-
void TxIndex::ThreadSync()
82+
void BaseIndex::ThreadSync()
7983
{
8084
const CBlockIndex* pindex = m_best_block_index.load();
8185
if (!m_synced) {
@@ -145,17 +149,19 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
145149
return m_db->WriteTxs(vPos);
146150
}
147151

148-
bool TxIndex::WriteBestBlock(const CBlockIndex* block_index)
152+
BaseIndexDB& TxIndex::GetDB() const { return *m_db; }
153+
154+
bool BaseIndex::WriteBestBlock(const CBlockIndex* block_index)
149155
{
150156
LOCK(cs_main);
151-
if (!m_db->WriteBestBlock(chainActive.GetLocator(block_index))) {
157+
if (!GetDB().WriteBestBlock(chainActive.GetLocator(block_index))) {
152158
return error("%s: Failed to write locator to disk", __func__);
153159
}
154160
return true;
155161
}
156162

157-
void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
158-
const std::vector<CTransactionRef>& txn_conflicted)
163+
void BaseIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
164+
const std::vector<CTransactionRef>& txn_conflicted)
159165
{
160166
if (!m_synced) {
161167
return;
@@ -192,7 +198,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const C
192198
}
193199
}
194200

195-
void TxIndex::ChainStateFlushed(const CBlockLocator& locator)
201+
void BaseIndex::ChainStateFlushed(const CBlockLocator& locator)
196202
{
197203
if (!m_synced) {
198204
return;
@@ -225,12 +231,12 @@ void TxIndex::ChainStateFlushed(const CBlockLocator& locator)
225231
return;
226232
}
227233

228-
if (!m_db->WriteBestBlock(locator)) {
234+
if (!GetDB().WriteBestBlock(locator)) {
229235
error("%s: Failed to write locator to disk", __func__);
230236
}
231237
}
232238

233-
bool TxIndex::BlockUntilSyncedToCurrentChain()
239+
bool BaseIndex::BlockUntilSyncedToCurrentChain()
234240
{
235241
AssertLockNotHeld(cs_main);
236242

@@ -282,12 +288,12 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe
282288
return true;
283289
}
284290

285-
void TxIndex::Interrupt()
291+
void BaseIndex::Interrupt()
286292
{
287293
m_interrupt();
288294
}
289295

290-
void TxIndex::Start()
296+
void BaseIndex::Start()
291297
{
292298
// Need to register this ValidationInterface before running Init(), so that
293299
// callbacks are not missed if Init sets m_synced to true.
@@ -298,10 +304,10 @@ void TxIndex::Start()
298304
}
299305

300306
m_thread_sync = std::thread(&TraceThread<std::function<void()>>, "txindex",
301-
std::bind(&TxIndex::ThreadSync, this));
307+
std::bind(&BaseIndex::ThreadSync, this));
302308
}
303309

304-
void TxIndex::Stop()
310+
void BaseIndex::Stop()
305311
{
306312
UnregisterValidationInterface(this);
307313

src/index/txindex.h

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,31 @@
1515
class CBlockIndex;
1616

1717
/**
18-
* TxIndex is used to look up transactions included in the blockchain by hash.
19-
* The index is written to a LevelDB database and records the filesystem
20-
* location of each transaction by transaction hash.
18+
* Base class for indices of blockchain data. This implements
19+
* CValidationInterface and ensures blocks are indexed sequentially according
20+
* to their position in the active chain.
2121
*/
22-
class TxIndex final : public CValidationInterface
22+
class BaseIndex : public CValidationInterface
2323
{
2424
private:
25-
const std::unique_ptr<TxIndexDB> m_db;
26-
2725
/// Whether the index is in sync with the main chain. The flag is flipped
2826
/// from false to true once, after which point this starts processing
2927
/// ValidationInterface notifications to stay in sync.
30-
std::atomic<bool> m_synced;
28+
std::atomic<bool> m_synced{false};
3129

32-
/// The last block in the chain that the TxIndex is in sync with.
33-
std::atomic<const CBlockIndex*> m_best_block_index;
30+
/// The last block in the chain that the index is in sync with.
31+
std::atomic<const CBlockIndex*> m_best_block_index{nullptr};
3432

3533
std::thread m_thread_sync;
3634
CThreadInterrupt m_interrupt;
3735

38-
/// Initialize internal state from the database and block index.
39-
bool Init();
40-
41-
/// Sync the tx index with the block index starting from the current best
42-
/// block. Intended to be run in its own thread, m_thread_sync, and can be
43-
/// interrupted with m_interrupt. Once the txindex gets in sync, the
44-
/// m_synced flag is set and the BlockConnected ValidationInterface callback
45-
/// takes over and the sync thread exits.
36+
/// Sync the index with the block index starting from the current best block.
37+
/// Intended to be run in its own thread, m_thread_sync, and can be
38+
/// interrupted with m_interrupt. Once the index gets in sync, the m_synced
39+
/// flag is set and the BlockConnected ValidationInterface callback takes
40+
/// over and the sync thread exits.
4641
void ThreadSync();
4742

48-
/// Write update index entries for a newly connected block.
49-
bool WriteBlock(const CBlock& block, const CBlockIndex* pindex);
50-
5143
/// Write the current chain block locator to the DB.
5244
bool WriteBestBlock(const CBlockIndex* block_index);
5345

@@ -57,27 +49,25 @@ class TxIndex final : public CValidationInterface
5749

5850
void ChainStateFlushed(const CBlockLocator& locator) override;
5951

60-
public:
61-
/// Constructs the TxIndex, which becomes available to be queried.
62-
explicit TxIndex(std::unique_ptr<TxIndexDB> db);
52+
/// Initialize internal state from the database and block index.
53+
virtual bool Init();
6354

55+
/// Write update index entries for a newly connected block.
56+
virtual bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) { return true; }
57+
58+
virtual BaseIndexDB& GetDB() const = 0;
59+
60+
public:
6461
/// Destructor interrupts sync thread if running and blocks until it exits.
65-
~TxIndex();
62+
virtual ~BaseIndex();
6663

67-
/// Blocks the current thread until the transaction index is caught up to
68-
/// the current state of the block chain. This only blocks if the index has gotten in sync once
69-
/// and only needs to process blocks in the ValidationInterface queue. If the index is catching
70-
/// up from far behind, this method does not block and immediately returns false.
64+
/// Blocks the current thread until the index is caught up to the current
65+
/// state of the block chain. This only blocks if the index has gotten in
66+
/// sync once and only needs to process blocks in the ValidationInterface
67+
/// queue. If the index is catching up from far behind, this method does
68+
/// not block and immediately returns false.
7169
bool BlockUntilSyncedToCurrentChain();
7270

73-
/// Look up a transaction by hash.
74-
///
75-
/// @param[in] tx_hash The hash of the transaction to be returned.
76-
/// @param[out] block_hash The hash of the block the transaction is found in.
77-
/// @param[out] tx The transaction itself.
78-
/// @return true if transaction is found, false otherwise
79-
bool FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const;
80-
8171
void Interrupt();
8272

8373
/// Start initializes the sync state and registers the instance as a
@@ -88,6 +78,37 @@ class TxIndex final : public CValidationInterface
8878
void Stop();
8979
};
9080

81+
/**
82+
* TxIndex is used to look up transactions included in the blockchain by hash.
83+
* The index is written to a LevelDB database and records the filesystem
84+
* location of each transaction by transaction hash.
85+
*/
86+
class TxIndex final : public BaseIndex
87+
{
88+
private:
89+
const std::unique_ptr<TxIndexDB> m_db;
90+
91+
protected:
92+
/// Override base class init to migrate from old database.
93+
bool Init() override;
94+
95+
bool WriteBlock(const CBlock& block, const CBlockIndex* pindex) override;
96+
97+
BaseIndexDB& GetDB() const override;
98+
99+
public:
100+
/// Constructs the index, which becomes available to be queried.
101+
explicit TxIndex(std::unique_ptr<TxIndexDB> db);
102+
103+
/// Look up a transaction by hash.
104+
///
105+
/// @param[in] tx_hash The hash of the transaction to be returned.
106+
/// @param[out] block_hash The hash of the block the transaction is found in.
107+
/// @param[out] tx The transaction itself.
108+
/// @return true if transaction is found, false otherwise
109+
bool FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRef& tx) const;
110+
};
111+
91112
/// The global transaction index, used in GetTransaction. May be null.
92113
extern std::unique_ptr<TxIndex> g_txindex;
93114

0 commit comments

Comments
 (0)