diff options
author | Alex Morcos <morcos@chaincode.com> | 2015-03-26 13:52:10 -0400 |
---|---|---|
committer | Alex Morcos <morcos@chaincode.com> | 2015-11-18 12:03:50 -0500 |
commit | 072e2f864445bc6ef3b390255f08c9e8bec2ea94 (patch) | |
tree | b1781d992e08263efa1b03b5f00f8f9c08760ac2 /src/coins.cpp | |
parent | 73fa5e604356ab4182971376fd758b4680737b5a (diff) |
Alter assumptions in CCoinsViewCache::BatchWrite
Previously it would break if you flushed a parent cache while there was a child cache referring to it. This change will allow the flushing of parent caches.
Diffstat (limited to 'src/coins.cpp')
-rw-r--r-- | src/coins.cpp | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/coins.cpp b/src/coins.cpp index 96b336ce77..f0ea5c0459 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -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 |