...efficient.
This is also an incremental step in making an index pruner for #4481
...efficient.
This is also an incremental step in making an index pruner for #4481
What if the first encountered block with file N doesn't have undo data, but the second one does? You'd skip checking it.
EDIT: fixed
2983 | @@ -2984,19 +2984,30 @@ bool static LoadBlockIndexDB() 2984 | 2985 | // Check presence of blk files 2986 | LogPrintf("Checking all blk files are present...\n"); 2987 | - set<int> setBlkDataFiles; 2988 | + map<int, bool> mapBlkDataFileReadable,mapBlkUndoFileReadable;
Why the map and bool? Just a set for both suffices.
Because if we go the #4481 route, we'll have to expand the logic to better manage the cases when the files are missing without failing.
Closing this, as it has been rebased, refactored and pushed as part of #4481.
I simplified this code. Reopening.
3006 | @@ -3025,6 +3007,50 @@ bool static LoadBlockIndexDB() 3007 | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), 3008 | Checkpoints::GuessVerificationProgress(chainActive.Tip())); 3009 | 3010 | + // Check presence of essential data 3011 | + LogPrintf("Checking essential data is accesible...\n");
Now that this has been moved to the end of the function, consider factoring it out to a separate function (eg. CheckForBlockFiles()) and calling that separately. After all, this is not part of loading the block index DB.
2984 | +} 2985 | 2986 | +bool CheckBlockFiles() 2987 | +{ 2988 | + // Check presence of essential data 2989 | + LogPrintf("Checking essential data is accesible...\n");
Idea: Checking required block data is available...?
3021 | + else 3022 | + { 3023 | + // Block 0 doesn't have undo data. 3024 | + if (pindex->nHeight) 3025 | + { 3026 | + LogPrintf("Missing undo for block: %i\n", pindex->nHeight);
I would prepend an Error: and also log which file exactly is missing (also a suggestion for normal block files).
"Error:" prepended, but notice that this condition doesn't mean a file is missing, but that we don't have the bit HAVE_UNDO set in the index for this block. If the file were missing, it would be logged by the function called in line 3015. So, there's no need to log a file name here, IMHO.
3021 | + else 3022 | + { 3023 | + // Block 0 doesn't have undo data. 3024 | + if (pindex->nHeight) 3025 | + { 3026 | + LogPrintf("Error: Missing undo for block: %i\n", pindex->nHeight);
Nit: undo data also fits better in here, but no need to add, if this is going to be merged soon.
Feedback addressed, and some bugs were fixed, and some things improved along the way. Would this be mergeable?
Code style fixed to adhere to current standards.
Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/p4515_bac3df7ed9c9627d54c9887702182adf9adf21df/ for binaries and test log. This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/ Contact BlueMatt on freenode if something looks broken.
I guess this is too late for 0.10, but reopening this anyway as I don't expect this code to change (a lot) any further, and it feels like it would make sense merging this independently of #4701.
2897 | + // Check presence of blk files 2898 | + LogPrintf("Checking all blk files are present...\n"); 2899 | + set<int> setRequiredDataFilesAreOpenable; 2900 | + for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { 2901 | + if (pindex->nStatus & BLOCK_HAVE_DATA && pindex->nStatus & BLOCK_HAVE_UNDO) { 2902 | + if (!setRequiredDataFilesAreOpenable.count(pindex->nFile)) {
It's not clear to me why you switched from the two-pass solution to a single loop, but from a readability viewpoint I'd prefer something like:
std::map<int,uint32_t> mapBlkDataFiles;
BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
{
CBlockIndex* pindex = item.second;
mapBlkDataFiles[pindex->nFile] |= pindex->nStatus;
}
for (std::map<int,uint32_t>::iterator it = mapBlkDataFiles.begin(); it != mapBlkDataFiles.end(); it++)
{
if ((it->second & BLOCK_HAVE_DATA) && !BlockFileIsOpenable(it->first)) {
LogPrintf("Error: Required block file %i can't be opened.\n", it->first);
return false;
}
if ((it->second & BLOCK_HAVE_UNDO) && !UndoFileIsOpenable(it->first)) {
LogPrintf("Error: Required undo file %i can't be opened.\n", it->first);
return false;
}
}
2872 | @@ -2891,6 +2873,48 @@ bool static LoadBlockIndexDB() 2873 | return true; 2874 | } 2875 | 2876 | +bool BlockFileIsOpenable(int nFile)
These functions can be static
172 | @@ -173,6 +173,8 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); 173 | bool InitBlockIndex(); 174 | /** Load the block tree and coins database from disk */ 175 | bool LoadBlockIndex(); 176 | +/** Check all required block files are present */
/** Check all required block and undo files are present */
Looks like this is not necessary for the current autoprune (#5863), so I'm closing this. Let me know if I'm wrong.