Changeset View
Changeset View
Standalone View
Standalone View
src/index/txindex.cpp
Show First 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | if (!m_synced) { | ||||
m_synced = true; | m_synced = true; | ||||
break; | break; | ||||
} | } | ||||
pindex = pindex_next; | pindex = pindex_next; | ||||
} | } | ||||
int64_t current_time = GetTime(); | int64_t current_time = GetTime(); | ||||
if (last_log_time + SYNC_LOG_INTERVAL < current_time) { | if (last_log_time + SYNC_LOG_INTERVAL < current_time) { | ||||
LogPrintf("Syncing txindex with block chain from height %d\n", | LogPrintf("Syncing %s with block chain from height %d\n", | ||||
pindex->nHeight); | GetName(), pindex->nHeight); | ||||
last_log_time = current_time; | last_log_time = current_time; | ||||
} | } | ||||
if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < | if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL < | ||||
current_time) { | current_time) { | ||||
WriteBestBlock(pindex); | WriteBestBlock(pindex); | ||||
last_locator_write_time = current_time; | last_locator_write_time = current_time; | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindex, config)) { | if (!ReadBlockFromDisk(block, pindex, config)) { | ||||
FatalError("%s: Failed to read block %s from disk", __func__, | FatalError("%s: Failed to read block %s from disk", __func__, | ||||
pindex->GetBlockHash().ToString()); | pindex->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
if (!WriteBlock(block, pindex)) { | if (!WriteBlock(block, pindex)) { | ||||
FatalError("%s: Failed to write block %s to tx index database", | FatalError("%s: Failed to write block %s to index database", | ||||
__func__, pindex->GetBlockHash().ToString()); | __func__, pindex->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (pindex) { | if (pindex) { | ||||
LogPrintf("txindex is enabled at height %d\n", pindex->nHeight); | LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight); | ||||
} else { | } else { | ||||
LogPrintf("txindex is enabled\n"); | LogPrintf("%s is enabled\n", GetName()); | ||||
} | } | ||||
} | } | ||||
bool TxIndex::WriteBlock(const CBlock &block, const CBlockIndex *pindex) { | bool TxIndex::WriteBlock(const CBlock &block, const CBlockIndex *pindex) { | ||||
CDiskTxPos pos(pindex->GetBlockPos(), | CDiskTxPos pos(pindex->GetBlockPos(), | ||||
GetSizeOfCompactSize(block.vtx.size())); | GetSizeOfCompactSize(block.vtx.size())); | ||||
std::vector<std::pair<uint256, CDiskTxPos>> vPos; | std::vector<std::pair<uint256, CDiskTxPos>> vPos; | ||||
vPos.reserve(block.vtx.size()); | vPos.reserve(block.vtx.size()); | ||||
Show All 37 Lines | if (!best_block_index) { | ||||
// the the sync thread catches up and sets m_synced. Consider the case | // the the sync thread catches up and sets m_synced. Consider the case | ||||
// where there is a reorg and the blocks on the stale branch are in the | // where there is a reorg and the blocks on the stale branch are in the | ||||
// ValidationInterface queue backlog even after the sync thread has | // ValidationInterface queue backlog even after the sync thread has | ||||
// caught up to the new chain tip. In this unlikely event, log a warning | // caught up to the new chain tip. In this unlikely event, log a warning | ||||
// and let the queue clear. | // and let the queue clear. | ||||
if (best_block_index->GetAncestor(pindex->nHeight - 1) != | if (best_block_index->GetAncestor(pindex->nHeight - 1) != | ||||
pindex->pprev) { | pindex->pprev) { | ||||
LogPrintf("%s: WARNING: Block %s does not connect to an ancestor " | LogPrintf("%s: WARNING: Block %s does not connect to an ancestor " | ||||
"of known best chain (tip=%s); not updating txindex\n", | "of known best chain (tip=%s); not updating index\n", | ||||
__func__, pindex->GetBlockHash().ToString(), | __func__, pindex->GetBlockHash().ToString(), | ||||
best_block_index->GetBlockHash().ToString()); | best_block_index->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
if (WriteBlock(*block, pindex)) { | if (WriteBlock(*block, pindex)) { | ||||
m_best_block_index = pindex; | m_best_block_index = pindex; | ||||
} else { | } else { | ||||
FatalError("%s: Failed to write block %s to txindex", __func__, | FatalError("%s: Failed to write block %s to index", __func__, | ||||
pindex->GetBlockHash().ToString()); | pindex->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
void BaseIndex::ChainStateFlushed(const CBlockLocator &locator) { | void BaseIndex::ChainStateFlushed(const CBlockLocator &locator) { | ||||
if (!m_synced) { | if (!m_synced) { | ||||
return; | return; | ||||
Show All 17 Lines | void BaseIndex::ChainStateFlushed(const CBlockLocator &locator) { | ||||
// catches up and sets m_synced. Consider the case where there is a reorg | // catches up and sets m_synced. Consider the case where there is a reorg | ||||
// and the blocks on the stale branch are in the ValidationInterface queue | // and the blocks on the stale branch are in the ValidationInterface queue | ||||
// backlog even after the sync thread has caught up to the new chain tip. In | // backlog even after the sync thread has caught up to the new chain tip. In | ||||
// this unlikely event, log a warning and let the queue clear. | // this unlikely event, log a warning and let the queue clear. | ||||
const CBlockIndex *best_block_index = m_best_block_index.load(); | const CBlockIndex *best_block_index = m_best_block_index.load(); | ||||
if (best_block_index->GetAncestor(locator_tip_index->nHeight) != | if (best_block_index->GetAncestor(locator_tip_index->nHeight) != | ||||
locator_tip_index) { | locator_tip_index) { | ||||
LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known " | LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known " | ||||
"best chain (tip=%s); not writing txindex locator\n", | "best chain (tip=%s); not writing index locator\n", | ||||
__func__, locator_tip_hash.ToString(), | __func__, locator_tip_hash.ToString(), | ||||
best_block_index->GetBlockHash().ToString()); | best_block_index->GetBlockHash().ToString()); | ||||
return; | return; | ||||
} | } | ||||
if (!GetDB().WriteBestBlock(locator)) { | if (!GetDB().WriteBestBlock(locator)) { | ||||
error("%s: Failed to write locator to disk", __func__); | error("%s: Failed to write locator to disk", __func__); | ||||
} | } | ||||
Show All 12 Lines | if (!m_synced) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CBlockIndex *chain_tip = chainActive.Tip(); | const CBlockIndex *chain_tip = chainActive.Tip(); | ||||
const CBlockIndex *best_block_index = m_best_block_index.load(); | const CBlockIndex *best_block_index = m_best_block_index.load(); | ||||
if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) { | if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) { | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
LogPrintf("%s: txindex is catching up on block notifications\n", __func__); | LogPrintf("%s: %s is catching up on block notifications\n", __func__, | ||||
GetName()); | |||||
SyncWithValidationInterfaceQueue(); | SyncWithValidationInterfaceQueue(); | ||||
return true; | return true; | ||||
} | } | ||||
bool TxIndex::FindTx(const uint256 &tx_hash, uint256 &block_hash, | bool TxIndex::FindTx(const uint256 &tx_hash, uint256 &block_hash, | ||||
CTransactionRef &tx) const { | CTransactionRef &tx) const { | ||||
CDiskTxPos postx; | CDiskTxPos postx; | ||||
if (!m_db->ReadTxPos(tx_hash, postx)) { | if (!m_db->ReadTxPos(tx_hash, postx)) { | ||||
Show All 23 Lines | void BaseIndex::Interrupt() { | ||||
m_interrupt(); | m_interrupt(); | ||||
} | } | ||||
void BaseIndex::Start() { | void BaseIndex::Start() { | ||||
// Need to register this ValidationInterface before running Init(), so that | // Need to register this ValidationInterface before running Init(), so that | ||||
// callbacks are not missed if Init sets m_synced to true. | // callbacks are not missed if Init sets m_synced to true. | ||||
RegisterValidationInterface(this); | RegisterValidationInterface(this); | ||||
if (!Init()) { | if (!Init()) { | ||||
FatalError("%s: txindex failed to initialize", __func__); | FatalError("%s: %s failed to initialize", __func__, GetName()); | ||||
return; | return; | ||||
} | } | ||||
m_thread_sync = std::thread(&TraceThread<std::function<void()>>, "txindex", | m_thread_sync = std::thread(&TraceThread<std::function<void()>>, GetName(), | ||||
std::bind(&BaseIndex::ThreadSync, this)); | std::bind(&BaseIndex::ThreadSync, this)); | ||||
} | } | ||||
void BaseIndex::Stop() { | void BaseIndex::Stop() { | ||||
UnregisterValidationInterface(this); | UnregisterValidationInterface(this); | ||||
if (m_thread_sync.joinable()) { | if (m_thread_sync.joinable()) { | ||||
m_thread_sync.join(); | m_thread_sync.join(); | ||||
} | } | ||||
} | } |