MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / BatchWrite

Method BatchWrite

src/coins.cpp:189–258  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

187}
188
189void CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& in_block_hash)
190{
191 for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
192 if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries
193 continue;
194 }
195 auto [itUs, inserted]{cacheCoins.try_emplace(it->first)};
196 if (inserted) {
197 if (it->second.IsFresh() && it->second.coin.IsSpent()) {
198 cacheCoins.erase(itUs); // TODO fresh coins should have been removed at spend
199 } else {
200 // The parent cache does not have an entry, while the child cache does.
201 // Move the data up and mark it as dirty.
202 CCoinsCacheEntry& entry{itUs->second};
203 assert(entry.coin.DynamicMemoryUsage() == 0);
204 if (cursor.WillErase(*it)) {
205 // Since this entry will be erased,
206 // we can move the coin into us instead of copying it
207 entry.coin = std::move(it->second.coin);
208 } else {
209 entry.coin = it->second.coin;
210 }
211 CCoinsCacheEntry::SetDirty(*itUs, m_sentinel);
212 ++m_dirty_count;
213 cachedCoinsUsage += entry.coin.DynamicMemoryUsage();
214 // We can mark it FRESH in the parent if it was FRESH in the child
215 // Otherwise it might have just been flushed from the parent's cache
216 // and already exist in the grandparent
217 if (it->second.IsFresh()) CCoinsCacheEntry::SetFresh(*itUs, m_sentinel);
218 }
219 } else {
220 // Found the entry in the parent cache
221 if (it->second.IsFresh() && !itUs->second.coin.IsSpent()) {
222 // The coin was marked FRESH in the child cache, but the coin
223 // exists in the parent cache. If this ever happens, it means
224 // the FRESH flag was misapplied and there is a logic error in
225 // the calling code.
226 throw std::logic_error("FRESH flag misapplied to coin that exists in parent cache");
227 }
228
229 if (itUs->second.IsFresh() && it->second.coin.IsSpent()) {
230 // The grandparent cache does not have an entry, and the coin
231 // has been spent. We can just delete it from the parent cache.
232 Assume(TrySub(m_dirty_count, itUs->second.IsDirty()));
233 Assume(TrySub(cachedCoinsUsage, itUs->second.coin.DynamicMemoryUsage()));
234 cacheCoins.erase(itUs);
235 } else {
236 // A normal modification.
237 Assume(TrySub(cachedCoinsUsage, itUs->second.coin.DynamicMemoryUsage()));
238 if (cursor.WillErase(*it)) {
239 // Since this entry will be erased,
240 // we can move the coin into us instead of copying it
241 itUs->second.coin = std::move(it->second.coin);
242 } else {
243 itUs->second.coin = it->second.coin;
244 }
245 cachedCoinsUsage += itUs->second.coin.DynamicMemoryUsage();
246 if (!itUs->second.IsDirty()) {

Callers 2

FlushMethod · 0.45
SyncMethod · 0.45

Calls 10

TrySubFunction · 0.85
BeginMethod · 0.80
EndMethod · 0.80
NextAndMaybeEraseMethod · 0.80
WillEraseMethod · 0.80
IsDirtyMethod · 0.45
IsFreshMethod · 0.45
IsSpentMethod · 0.45
eraseMethod · 0.45
DynamicMemoryUsageMethod · 0.45

Tested by

no test coverage detected