Skip to content

Commit 6cb70ca

Browse files
ajweisslaanwj
authored andcommitted
Prune: Support noncontiguous block files
In some corner cases, it may be possible for recent blocks to end up in the same block file as much older blocks. Previously, the pruning code would stop looking for files to remove upon first encountering a file containing a block that cannot be pruned, now it will keep looking for candidate files until the target is met and all other criteria are satisfied. This can result in a noncontiguous set of block files (by number) on disk, which is fine except for during some reindex corner cases, so make reindex preparation smarter such that we keep the data we can actually use and throw away the rest. This allows pruning to work correctly while downloading any blocks needed during the reindex. Rebased-From: c257a8c Github-Pull: #6221
1 parent 37b4e42 commit 6cb70ca

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

src/init.cpp

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -473,24 +473,43 @@ struct CImportingNow
473473

474474
// If we're using -prune with -reindex, then delete block files that will be ignored by the
475475
// reindex. Since reindexing works by starting at block file 0 and looping until a blockfile
476-
// is missing, and since pruning works by deleting the oldest block file first, just check
477-
// for block file 0, and if it doesn't exist, delete all the block files in the
478-
// directory (since they won't be read by the reindex but will take up disk space).
479-
void DeleteAllBlockFiles()
476+
// is missing, do the same here to delete any later block files after a gap. Also delete all
477+
// rev files since they'll be rewritten by the reindex anyway. This ensures that vinfoBlockFile
478+
// is in sync with what's actually on disk by the time we start downloading, so that pruning
479+
// works correctly.
480+
void CleanupBlockRevFiles()
480481
{
481-
if (boost::filesystem::exists(GetBlockPosFilename(CDiskBlockPos(0, 0), "blk")))
482-
return;
482+
using namespace boost::filesystem;
483+
map<string, path> mapBlockFiles;
484+
485+
// Glob all blk?????.dat and rev?????.dat files from the blocks directory.
486+
// Remove the rev files immediately and insert the blk file paths into an
487+
// ordered map keyed by block file index.
488+
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
489+
path blocksdir = GetDataDir() / "blocks";
490+
for (directory_iterator it(blocksdir); it != directory_iterator(); it++) {
491+
if (is_regular_file(*it) &&
492+
it->path().filename().string().length() == 12 &&
493+
it->path().filename().string().substr(8,4) == ".dat")
494+
{
495+
if (it->path().filename().string().substr(0,3) == "blk")
496+
mapBlockFiles[it->path().filename().string().substr(3,5)] = it->path();
497+
else if (it->path().filename().string().substr(0,3) == "rev")
498+
remove(it->path());
499+
}
500+
}
483501

484-
LogPrintf("Removing all blk?????.dat and rev?????.dat files for -reindex with -prune\n");
485-
boost::filesystem::path blocksdir = GetDataDir() / "blocks";
486-
for (boost::filesystem::directory_iterator it(blocksdir); it != boost::filesystem::directory_iterator(); it++) {
487-
if (is_regular_file(*it)) {
488-
if ((it->path().filename().string().length() == 12) &&
489-
(it->path().filename().string().substr(8,4) == ".dat") &&
490-
((it->path().filename().string().substr(0,3) == "blk") ||
491-
(it->path().filename().string().substr(0,3) == "rev")))
492-
boost::filesystem::remove(it->path());
502+
// Remove all block files that aren't part of a contiguous set starting at
503+
// zero by walking the ordered map (keys are block file indices) by
504+
// keeping a separate counter. Once we hit a gap (or if 0 doesn't exist)
505+
// start removing block files.
506+
int nContigCounter = 0;
507+
BOOST_FOREACH(const PAIRTYPE(string, path)& item, mapBlockFiles) {
508+
if (atoi(item.first) == nContigCounter) {
509+
nContigCounter++;
510+
continue;
493511
}
512+
remove(item.second);
494513
}
495514
}
496515

@@ -1110,9 +1129,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
11101129

11111130
if (fReindex) {
11121131
pblocktree->WriteReindexing(true);
1113-
//If we're reindexing in prune mode, wipe away all our block and undo data files
1132+
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
11141133
if (fPruneMode)
1115-
DeleteAllBlockFiles();
1134+
CleanupBlockRevFiles();
11161135
}
11171136

11181137
if (!LoadBlockIndex()) {

src/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3040,9 +3040,9 @@ void FindFilesToPrune(std::set<int>& setFilesToPrune)
30403040
if (nCurrentUsage + nBuffer < nPruneTarget) // are we below our target?
30413041
break;
30423042

3043-
// don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the main chain's tip
3043+
// don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the main chain's tip but keep scanning
30443044
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
3045-
break;
3045+
continue;
30463046

30473047
PruneOneBlockFile(fileNumber);
30483048
// Queue up the files for removal

0 commit comments

Comments
 (0)