aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-05-06 01:23:13 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-06-09 02:21:15 +0200
commit4e0eed88acdd41826868c151373068bfad18b84d (patch)
treef43eafcd165d6c4e3c8b0450c4b79275b18bf271 /src
parent77339e5aec4da99f727b80829f9697357b4cec45 (diff)
Allow ActivateBestChain to release its lock on cs_main
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp92
1 files changed, 55 insertions, 37 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 806f1c20db..860487dece 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2079,47 +2079,43 @@ static CBlockIndex* FindMostWorkChain() {
} while(true);
}
-// Try to activate to the most-work chain (thereby connecting it).
-bool ActivateBestChain(CValidationState &state) {
- LOCK(cs_main);
+// Try to make some progress towards making pindexMostWork the active block.
+static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork) {
+ AssertLockHeld(cs_main);
CBlockIndex *pindexOldTip = chainActive.Tip();
- bool fComplete = false;
- while (!fComplete) {
- CBlockIndex *pindexMostWork = FindMostWorkChain();
- CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
- fComplete = true;
-
- // Check whether we have something to do.
- if (pindexMostWork == NULL) break;
+ CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
- // Disconnect active blocks which are no longer in the best chain.
- while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
- if (!DisconnectTip(state))
- return false;
- }
+ // Disconnect active blocks which are no longer in the best chain.
+ while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
+ if (!DisconnectTip(state))
+ return false;
+ }
- // Build list of new blocks to connect.
- std::vector<CBlockIndex*> vpindexToConnect;
- vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1));
- while (pindexMostWork && pindexMostWork != pindexFork) {
- vpindexToConnect.push_back(pindexMostWork);
- pindexMostWork = pindexMostWork->pprev;
- }
+ // Build list of new blocks to connect.
+ std::vector<CBlockIndex*> vpindexToConnect;
+ vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1));
+ while (pindexMostWork && pindexMostWork != pindexFork) {
+ vpindexToConnect.push_back(pindexMostWork);
+ pindexMostWork = pindexMostWork->pprev;
+ }
- // Connect new blocks.
- BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
- if (!ConnectTip(state, pindexConnect)) {
- if (state.IsInvalid()) {
- // The block violates a consensus rule.
- if (!state.CorruptionPossible())
- InvalidChainFound(vpindexToConnect.back());
- fComplete = false;
- state = CValidationState();
- break;
- } else {
- // A system error occurred (disk space, database error, ...).
- return false;
- }
+ // Connect new blocks.
+ BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
+ if (!ConnectTip(state, pindexConnect)) {
+ if (state.IsInvalid()) {
+ // The block violates a consensus rule.
+ if (!state.CorruptionPossible())
+ InvalidChainFound(vpindexToConnect.back());
+ state = CValidationState();
+ break;
+ } else {
+ // A system error occurred (disk space, database error, ...).
+ return false;
+ }
+ } else {
+ if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
+ // We're in a better position than we were. Return temporarily to release the lock.
+ break;
}
}
}
@@ -2136,6 +2132,28 @@ bool ActivateBestChain(CValidationState &state) {
return true;
}
+bool ActivateBestChain(CValidationState &state) {
+ do {
+ boost::this_thread::interruption_point();
+
+ LOCK(cs_main);
+
+ // Check whether we're done (this could be avoided after the first run,
+ // but that's not worth optimizing.
+ CBlockIndex *pindexMostWork = FindMostWorkChain();
+ if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
+ return true;
+
+ if (!ActivateBestChainStep(state, pindexMostWork))
+ return false;
+
+ // Check whether we're done now.
+ if (pindexMostWork == chainActive.Tip())
+ return true;
+ } while(true);
+
+ return true;
+}
CBlockIndex* AddToBlockIndex(CBlockHeader& block)
{