Changeset View
Changeset View
Standalone View
Standalone View
src/index/base.cpp
Show All 35 Lines | |||||
bool BaseIndex::DB::ReadBestBlock(CBlockLocator &locator) const { | bool BaseIndex::DB::ReadBestBlock(CBlockLocator &locator) const { | ||||
bool success = Read(DB_BEST_BLOCK, locator); | bool success = Read(DB_BEST_BLOCK, locator); | ||||
if (!success) { | if (!success) { | ||||
locator.SetNull(); | locator.SetNull(); | ||||
} | } | ||||
return success; | return success; | ||||
} | } | ||||
bool BaseIndex::DB::WriteBestBlock(const CBlockLocator &locator) { | void BaseIndex::DB::WriteBestBlock(CDBBatch &batch, | ||||
return Write(DB_BEST_BLOCK, locator); | const CBlockLocator &locator) { | ||||
batch.Write(DB_BEST_BLOCK, locator); | |||||
} | } | ||||
BaseIndex::~BaseIndex() { | BaseIndex::~BaseIndex() { | ||||
Interrupt(); | Interrupt(); | ||||
Stop(); | Stop(); | ||||
} | } | ||||
bool BaseIndex::Init() { | bool BaseIndex::Init() { | ||||
Show All 32 Lines | void BaseIndex::ThreadSync() { | ||||
const CBlockIndex *pindex = m_best_block_index.load(); | const CBlockIndex *pindex = m_best_block_index.load(); | ||||
if (!m_synced) { | if (!m_synced) { | ||||
auto &consensus_params = GetConfig().GetChainParams().GetConsensus(); | auto &consensus_params = GetConfig().GetChainParams().GetConsensus(); | ||||
int64_t last_log_time = 0; | int64_t last_log_time = 0; | ||||
int64_t last_locator_write_time = 0; | int64_t last_locator_write_time = 0; | ||||
while (true) { | while (true) { | ||||
if (m_interrupt) { | if (m_interrupt) { | ||||
WriteBestBlock(pindex); | m_best_block_index = pindex; | ||||
// No need to handle errors in Commit. If it fails, the error | |||||
// will be already be logged. The best way to recover is to | |||||
// continue, as index cannot be corrupted by a missed commit to | |||||
// disk for an advanced index state. | |||||
Commit(); | |||||
return; | return; | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CBlockIndex *pindex_next = NextSyncBlock(pindex); | const CBlockIndex *pindex_next = NextSyncBlock(pindex); | ||||
if (!pindex_next) { | if (!pindex_next) { | ||||
WriteBestBlock(pindex); | |||||
m_best_block_index = pindex; | m_best_block_index = pindex; | ||||
m_synced = true; | m_synced = true; | ||||
// No need to handle errors in Commit. See rationale above. | |||||
Commit(); | |||||
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 %s with block chain from height %d\n", | LogPrintf("Syncing %s with block chain from height %d\n", | ||||
GetName(), 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); | m_best_block_index = pindex; | ||||
last_locator_write_time = current_time; | last_locator_write_time = current_time; | ||||
// No need to handle errors in Commit. See rationale above. | |||||
Commit(); | |||||
} | } | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindex, consensus_params)) { | if (!ReadBlockFromDisk(block, pindex, consensus_params)) { | ||||
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 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("%s is enabled at height %d\n", GetName(), pindex->nHeight); | LogPrintf("%s is enabled at height %d\n", GetName(), pindex->nHeight); | ||||
} else { | } else { | ||||
LogPrintf("%s is enabled\n", GetName()); | LogPrintf("%s is enabled\n", GetName()); | ||||
} | } | ||||
} | } | ||||
bool BaseIndex::WriteBestBlock(const CBlockIndex *block_index) { | bool BaseIndex::Commit() { | ||||
LOCK(cs_main); | CDBBatch batch(GetDB()); | ||||
if (!GetDB().WriteBestBlock(::ChainActive().GetLocator(block_index))) { | if (!CommitInternal(batch) || !GetDB().WriteBatch(batch)) { | ||||
return error("%s: Failed to write locator to disk", __func__); | return error("%s: Failed to commit latest %s state", __func__, | ||||
GetName()); | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool BaseIndex::CommitInternal(CDBBatch &batch) { | |||||
LOCK(cs_main); | |||||
GetDB().WriteBestBlock(batch, | |||||
::ChainActive().GetLocator(m_best_block_index)); | |||||
return true; | |||||
} | |||||
void BaseIndex::BlockConnected( | void BaseIndex::BlockConnected( | ||||
const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, | const std::shared_ptr<const CBlock> &block, const CBlockIndex *pindex, | ||||
const std::vector<CTransactionRef> &txn_conflicted) { | const std::vector<CTransactionRef> &txn_conflicted) { | ||||
if (!m_synced) { | if (!m_synced) { | ||||
return; | return; | ||||
} | } | ||||
const CBlockIndex *best_block_index = m_best_block_index.load(); | const CBlockIndex *best_block_index = m_best_block_index.load(); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | 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 index 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)) { | // No need to handle errors in Commit. If it fails, the error will be | ||||
error("%s: Failed to write locator to disk", __func__); | // already be logged. The best way to recover is to continue, as index | ||||
} | // cannot be corrupted by a missed commit to disk for an advanced index | ||||
// state. | |||||
Commit(); | |||||
} | } | ||||
bool BaseIndex::BlockUntilSyncedToCurrentChain() { | bool BaseIndex::BlockUntilSyncedToCurrentChain() { | ||||
AssertLockNotHeld(cs_main); | AssertLockNotHeld(cs_main); | ||||
if (!m_synced) { | if (!m_synced) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 42 Lines • Show Last 20 Lines |