* Update the on-disk chain state. * The caches and indexes are flushed depending on the mode we're called with * if they're too large, if it's been a while since the last write, * or always and in all cases if we're in prune mode and are deleting files. */
| 2536 | * or always and in all cases if we're in prune mode and are deleting files. |
| 2537 | */ |
| 2538 | bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) { |
| 2539 | LOCK2(cs_main, cs_LastBlockFile); |
| 2540 | static int64_t nLastWrite = 0; |
| 2541 | static int64_t nLastFlush = 0; |
| 2542 | static int64_t nLastSetChain = 0; |
| 2543 | std::set<int> setFilesToPrune; |
| 2544 | bool fFlushForPrune = false; |
| 2545 | try { |
| 2546 | if (fPruneMode && fCheckForPruning) { |
| 2547 | FindFilesToPrune(setFilesToPrune); |
| 2548 | fCheckForPruning = false; |
| 2549 | if (!setFilesToPrune.empty()) { |
| 2550 | fFlushForPrune = true; |
| 2551 | if (!fHavePruned) { |
| 2552 | pblocktree->WriteFlag("prunedblockfiles", true); |
| 2553 | fHavePruned = true; |
| 2554 | } |
| 2555 | } |
| 2556 | } |
| 2557 | int64_t nNow = GetTimeMicros(); |
| 2558 | // Avoid writing/flushing immediately after startup. |
| 2559 | if (nLastWrite == 0) { |
| 2560 | nLastWrite = nNow; |
| 2561 | } |
| 2562 | if (nLastFlush == 0) { |
| 2563 | nLastFlush = nNow; |
| 2564 | } |
| 2565 | if (nLastSetChain == 0) { |
| 2566 | nLastSetChain = nNow; |
| 2567 | } |
| 2568 | size_t cacheSize = pcoinsTip->DynamicMemoryUsage(); |
| 2569 | // The cache is large and close to the limit, but we have time now (not in the middle of a block processing). |
| 2570 | bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize * (10.0/9) > nCoinCacheUsage; |
| 2571 | // The cache is over the limit, we have to write now. |
| 2572 | bool fCacheCritical = mode == FLUSH_STATE_IF_NEEDED && cacheSize > nCoinCacheUsage; |
| 2573 | // It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash. |
| 2574 | bool fPeriodicWrite = mode == FLUSH_STATE_PERIODIC && nNow > nLastWrite + (int64_t)DATABASE_WRITE_INTERVAL * 1000000; |
| 2575 | // It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage. |
| 2576 | bool fPeriodicFlush = mode == FLUSH_STATE_PERIODIC && nNow > nLastFlush + (int64_t)DATABASE_FLUSH_INTERVAL * 1000000; |
| 2577 | // Combine all conditions that result in a full cache flush. |
| 2578 | bool fDoFullFlush = (mode == FLUSH_STATE_ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune; |
| 2579 | // Write blocks and block index to disk. |
| 2580 | if (fDoFullFlush || fPeriodicWrite) { |
| 2581 | // Depend on nMinDiskSpace to ensure we can write block index |
| 2582 | if (!CheckDiskSpace(0)) |
| 2583 | return state.Error("out of disk space"); |
| 2584 | // First make sure all block and undo data is flushed to disk. |
| 2585 | FlushBlockFile(); |
| 2586 | // Then update all block file information (which may refer to block and undo files). |
| 2587 | { |
| 2588 | std::vector<std::pair<int, const CBlockFileInfo*> > vFiles; |
| 2589 | vFiles.reserve(setDirtyFileInfo.size()); |
| 2590 | for (set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) { |
| 2591 | vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it])); |
| 2592 | setDirtyFileInfo.erase(it++); |
| 2593 | } |
| 2594 | std::vector<const CBlockIndex*> vBlocks; |
| 2595 | vBlocks.reserve(setDirtyBlockIndex.size()); |
no test coverage detected