Permalink
Browse files

Merge pull request #5967

072e2f8 Alter assumptions in CCoinsViewCache::BatchWrite (Alex Morcos)
  • Loading branch information...
laanwj committed Nov 27, 2015
2 parents 9a3e1a5 + 072e2f8 commit 05d591839fe1fefb0cf359083bce87cb128f75a6
Showing with 28 additions and 7 deletions.
  1. +12 −7 src/coins.cpp
  2. +16 −0 src/test/coins_tests.cpp
View
@@ -160,18 +160,23 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
if (itUs == cacheCoins.end()) {
- if (!it->second.coins.IsPruned()) {
- // The parent cache does not have an entry, while the child
- // cache does have (a non-pruned) one. Move the data up, and
- // mark it as fresh (if the grandparent did have it, we
- // would have pulled it in at first GetCoins).
- assert(it->second.flags & CCoinsCacheEntry::FRESH);
+ // The parent cache does not have an entry, while the child does
+ // We can ignore it if it's both FRESH and pruned in the child
+ if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coins.IsPruned())) {
+ // Otherwise we will need to create it in the parent
+ // and move the data up and mark it as dirty
CCoinsCacheEntry& entry = cacheCoins[it->first];
entry.coins.swap(it->second.coins);
cachedCoinsUsage += entry.coins.DynamicMemoryUsage();
- entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
+ entry.flags = CCoinsCacheEntry::DIRTY;
+ // We can mark it FRESH in the parent if it was FRESH in the child
+ // Otherwise it might have just been flushed from the parent's cache
+ // and already exist in the grandparent
+ if (it->second.flags & CCoinsCacheEntry::FRESH)
+ entry.flags |= CCoinsCacheEntry::FRESH;
}
} else {
+ // Found the entry in the parent cache
if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
// The grandparent does not have an entry, and the child is
// modified and being pruned. This means we can just delete
View
@@ -164,14 +164,23 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
}
}
+ if (insecure_rand() % 100 == 0) {
+ // Every 100 iterations, flush an intermediate cache
+ if (stack.size() > 1 && insecure_rand() % 2 == 0) {
+ unsigned int flushIndex = insecure_rand() % (stack.size() - 1);
+ stack[flushIndex]->Flush();
+ }
+ }
if (insecure_rand() % 100 == 0) {
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && insecure_rand() % 2 == 0) {
+ //Remove the top cache
stack.back()->Flush();
delete stack.back();
stack.pop_back();
}
if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) {
+ //Add a new cache
CCoinsView* tip = &base;
if (stack.size() > 0) {
tip = stack.back();
@@ -304,6 +313,13 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
}
}
+ if (insecure_rand() % 100 == 0) {
+ // Every 100 iterations, flush an intermediate cache
+ if (stack.size() > 1 && insecure_rand() % 2 == 0) {
+ unsigned int flushIndex = insecure_rand() % (stack.size() - 1);
+ stack[flushIndex]->Flush();
+ }
+ }
if (insecure_rand() % 100 == 0) {
// Every 100 iterations, change the cache stack.
if (stack.size() > 0 && insecure_rand() % 2 == 0) {

0 comments on commit 05d5918

Please sign in to comment.