Skip to content

Commit 94b4f8b

Browse files
author
Jim Posen
committed
[index] TxIndex initial sync thread.
TxIndex starts up a background thread to get in sync with the block index before blocks are processed through the ValidationInterface.
1 parent 34d68bf commit 94b4f8b

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

src/index/txindex.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <chainparams.h>
56
#include <index/txindex.h>
67
#include <init.h>
78
#include <tinyformat.h>
@@ -10,6 +11,9 @@
1011
#include <validation.h>
1112
#include <warnings.h>
1213

14+
constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds
15+
constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds
16+
1317
template<typename... Args>
1418
static void FatalError(const char* fmt, const Args&... args)
1519
{
@@ -47,6 +51,75 @@ bool TxIndex::Init()
4751
return true;
4852
}
4953

54+
static const CBlockIndex* NextSyncBlock(const CBlockIndex* pindex_prev)
55+
{
56+
AssertLockHeld(cs_main);
57+
58+
if (!pindex_prev) {
59+
return chainActive.Genesis();
60+
}
61+
62+
const CBlockIndex* pindex = chainActive.Next(pindex_prev);
63+
if (pindex) {
64+
return pindex;
65+
}
66+
67+
return chainActive.Next(chainActive.FindFork(pindex_prev));
68+
}
69+
70+
void TxIndex::ThreadSync()
71+
{
72+
const CBlockIndex* pindex = m_best_block_index.load();
73+
if (!m_synced) {
74+
auto& consensus_params = Params().GetConsensus();
75+
76+
int64_t last_log_time = 0;
77+
int64_t last_locator_write_time = 0;
78+
while (true) {
79+
{
80+
LOCK(cs_main);
81+
const CBlockIndex* pindex_next = NextSyncBlock(pindex);
82+
if (!pindex_next) {
83+
WriteBestBlock(pindex);
84+
m_best_block_index = pindex;
85+
m_synced = true;
86+
break;
87+
}
88+
pindex = pindex_next;
89+
}
90+
91+
int64_t current_time = GetTime();
92+
if (last_log_time + SYNC_LOG_INTERVAL < current_time) {
93+
LogPrintf("Syncing txindex with block chain from height %d\n", pindex->nHeight);
94+
last_log_time = current_time;
95+
}
96+
97+
if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < current_time) {
98+
WriteBestBlock(pindex);
99+
last_locator_write_time = current_time;
100+
}
101+
102+
CBlock block;
103+
if (!ReadBlockFromDisk(block, pindex, consensus_params)) {
104+
FatalError("%s: Failed to read block %s from disk",
105+
__func__, pindex->GetBlockHash().ToString());
106+
return;
107+
}
108+
if (!WriteBlock(block, pindex)) {
109+
FatalError("%s: Failed to write block %s to tx index database",
110+
__func__, pindex->GetBlockHash().ToString());
111+
return;
112+
}
113+
}
114+
}
115+
116+
if (pindex) {
117+
LogPrintf("txindex is enabled at height %d\n", pindex->nHeight);
118+
} else {
119+
LogPrintf("txindex is enabled\n");
120+
}
121+
}
122+
50123
bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
51124
{
52125
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
@@ -59,6 +132,15 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
59132
return m_db->WriteTxs(vPos);
60133
}
61134

135+
bool TxIndex::WriteBestBlock(const CBlockIndex* block_index)
136+
{
137+
LOCK(cs_main);
138+
if (!m_db->WriteBestBlock(chainActive.GetLocator(block_index))) {
139+
return error("%s: Failed to write locator to disk", __func__);
140+
}
141+
return true;
142+
}
143+
62144
void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
63145
const std::vector<CTransactionRef>& txn_conflicted)
64146
{
@@ -149,9 +231,16 @@ void TxIndex::Start()
149231
FatalError("%s: txindex failed to initialize", __func__);
150232
return;
151233
}
234+
235+
m_thread_sync = std::thread(&TraceThread<std::function<void()>>, "txindex",
236+
std::bind(&TxIndex::ThreadSync, this));
152237
}
153238

154239
void TxIndex::Stop()
155240
{
156241
UnregisterValidationInterface(this);
242+
243+
if (m_thread_sync.joinable()) {
244+
m_thread_sync.join();
245+
}
157246
}

src/index/txindex.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,23 @@ class TxIndex final : public CValidationInterface
3030
/// The last block in the chain that the TxIndex is in sync with.
3131
std::atomic<const CBlockIndex*> m_best_block_index;
3232

33+
std::thread m_thread_sync;
34+
3335
/// Initialize internal state from the database and block index.
3436
bool Init();
3537

38+
/// Sync the tx index with the block index starting from the current best
39+
/// block. Intended to be run in its own thread, m_thread_sync. Once the
40+
/// txindex gets in sync, the m_synced flag is set and the BlockConnected
41+
/// ValidationInterface callback takes over and the sync thread exits.
42+
void ThreadSync();
43+
3644
/// Write update index entries for a newly connected block.
3745
bool WriteBlock(const CBlock& block, const CBlockIndex* pindex);
3846

47+
/// Write the current chain block locator to the DB.
48+
bool WriteBestBlock(const CBlockIndex* block_index);
49+
3950
protected:
4051
void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex,
4152
const std::vector<CTransactionRef>& txn_conflicted) override;

0 commit comments

Comments
 (0)