Skip to content

Commit

Permalink
Prune: Support noncontiguous block files
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ajweiss authored and laanwj committed Jun 11, 2015
1 parent 37b4e42 commit 6cb70ca
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 19 deletions.
53 changes: 36 additions & 17 deletions src/init.cpp
Expand Up @@ -473,24 +473,43 @@ struct CImportingNow

// If we're using -prune with -reindex, then delete block files that will be ignored by the
// reindex. Since reindexing works by starting at block file 0 and looping until a blockfile
// is missing, and since pruning works by deleting the oldest block file first, just check
// for block file 0, and if it doesn't exist, delete all the block files in the
// directory (since they won't be read by the reindex but will take up disk space).
void DeleteAllBlockFiles()
// is missing, do the same here to delete any later block files after a gap. Also delete all
// rev files since they'll be rewritten by the reindex anyway. This ensures that vinfoBlockFile
// is in sync with what's actually on disk by the time we start downloading, so that pruning
// works correctly.
void CleanupBlockRevFiles()
{
if (boost::filesystem::exists(GetBlockPosFilename(CDiskBlockPos(0, 0), "blk")))
return;
using namespace boost::filesystem;
map<string, path> mapBlockFiles;

// Glob all blk?????.dat and rev?????.dat files from the blocks directory.
// Remove the rev files immediately and insert the blk file paths into an
// ordered map keyed by block file index.
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n");
path blocksdir = GetDataDir() / "blocks";
for (directory_iterator it(blocksdir); it != directory_iterator(); it++) {
if (is_regular_file(*it) &&
it->path().filename().string().length() == 12 &&
it->path().filename().string().substr(8,4) == ".dat")
{
if (it->path().filename().string().substr(0,3) == "blk")
mapBlockFiles[it->path().filename().string().substr(3,5)] = it->path();
else if (it->path().filename().string().substr(0,3) == "rev")
remove(it->path());
}
}

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

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

if (fReindex) {
pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away all our block and undo data files
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
if (fPruneMode)
DeleteAllBlockFiles();
CleanupBlockRevFiles();
}

if (!LoadBlockIndex()) {
Expand Down
4 changes: 2 additions & 2 deletions src/main.cpp
Expand Up @@ -3040,9 +3040,9 @@ void FindFilesToPrune(std::set<int>& setFilesToPrune)
if (nCurrentUsage + nBuffer < nPruneTarget) // are we below our target?
break;

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

PruneOneBlockFile(fileNumber);
// Queue up the files for removal
Expand Down

0 comments on commit 6cb70ca

Please sign in to comment.