Merge pull request #930 from sipa/minireorg

Limit the impact of reorganisations on the database (fix #925)
pull/941/head
Gregory Maxwell 13 years ago
commit 89cccc83f8

@ -1457,6 +1457,32 @@ runCommand(std::string strCommand)
printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr); printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr);
} }
bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew)
{
assert(pindexNew->pprev == pindexBest);
uint256 hash = GetHash();
// Adding to current best branch
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash))
{
txdb.TxnAbort();
InvalidChainFound(pindexNew);
return false;
}
if (!txdb.TxnCommit())
return error("SetBestChain() : TxnCommit failed");
// Add to current best branch
pindexNew->pprev->pnext = pindexNew;
// Delete redundant memory transactions
BOOST_FOREACH(CTransaction& tx, vtx)
tx.RemoveFromMemoryPool();
return true;
}
bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
{ {
uint256 hash = GetHash(); uint256 hash = GetHash();
@ -1471,32 +1497,50 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
} }
else if (hashPrevBlock == hashBestChain) else if (hashPrevBlock == hashBestChain)
{ {
// Adding to current best branch if (!SetBestChainInner(txdb, pindexNew))
if (!ConnectBlock(txdb, pindexNew) || !txdb.WriteHashBestChain(hash)) return error("SetBestChain() : SetBestChainInner failed");
}
else
{
// the first block in the new chain that will cause it to become the new best chain
CBlockIndex *pindexIntermediate = pindexNew;
// list of blocks that need to be connected afterwards
std::vector<CBlockIndex*> vpindexSecondary;
// Reorganize is costly in terms of db load, as it works in a single db transaction.
// Try to limit how much needs to be done inside
while (pindexIntermediate->pprev && pindexIntermediate->pprev->bnChainWork > pindexBest->bnChainWork)
{ {
txdb.TxnAbort(); vpindexSecondary.push_back(pindexIntermediate);
InvalidChainFound(pindexNew); pindexIntermediate = pindexIntermediate->pprev;
return error("SetBestChain() : ConnectBlock failed");
} }
if (!txdb.TxnCommit())
return error("SetBestChain() : TxnCommit failed");
// Add to current best branch if (!vpindexSecondary.empty())
pindexNew->pprev->pnext = pindexNew; printf("Postponing %i reconnects\n", vpindexSecondary.size());
// Delete redundant memory transactions // Switch to new best branch
BOOST_FOREACH(CTransaction& tx, vtx) if (!Reorganize(txdb, pindexIntermediate))
tx.RemoveFromMemoryPool();
}
else
{
// New best branch
if (!Reorganize(txdb, pindexNew))
{ {
txdb.TxnAbort(); txdb.TxnAbort();
InvalidChainFound(pindexNew); InvalidChainFound(pindexNew);
return error("SetBestChain() : Reorganize failed"); return error("SetBestChain() : Reorganize failed");
} }
// Connect futher blocks
BOOST_REVERSE_FOREACH(CBlockIndex *pindex, vpindexSecondary)
{
CBlock block;
if (!block.ReadFromDisk(pindex))
{
printf("SetBestChain() : ReadFromDisk failed\n");
break;
}
txdb.TxnBegin();
// errors now are not fatal, we still did a reorganisation to a new chain in a valid way
if (!block.SetBestChainInner(txdb, pindex))
break;
}
} }
// Update best block in wallet (so we can detect restored wallets) // Update best block in wallet (so we can detect restored wallets)

@ -1030,6 +1030,9 @@ public:
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
bool CheckBlock() const; bool CheckBlock() const;
bool AcceptBlock(); bool AcceptBlock();
private:
bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew);
}; };

Loading…
Cancel
Save