mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
Merge #15118: Refactor block file logic
04cca33094Style cleanup. (Jim Posen)4c01e4e159flatfile: Unit tests for FlatFileSeq methods. (Jim Posen)65a489e93dscripted-diff: Rename CBlockDiskPos to FlatFilePos. (Jim Posen)d6d8a78f26Move CDiskBlockPos from chain to flatfile. (Jim Posen)e0380933e3validation: Refactor file flush logic into FlatFileSeq. (Jim Posen)992404b31evalidation: Refactor block file pre-allocation into FlatFileSeq. (Jim Posen)e2d2abb99fvalidation: Refactor OpenDiskFile into method on FlatFileSeq. (Jim Posen)9183d6ef65validation: Extract basic block file logic into FlatFileSeq class. (Jim Posen)62e7addb63util: Move CheckDiskSpace to util. (Jim Posen) Pull request description: This cleans up and refactors block file helpers so that they may be used by the block filter indexer. Per [design discussion](https://github.com/bitcoin/bitcoin/pull/14121#issuecomment-451252591) about storing BIP 157 block filters, it has been suggested that they are stored in the same way as block and undo data. This refactor is sufficient to simplify file operations for this use case, though in the future perhaps more pruning-related logic ought to be moved into the new classes. The basic abstraction is a `FlatFileSeq` which manages access to a sequence of numbered files into which raw data is written. Tree-SHA512: b2108756777f2dad8964a1a2ef2764486e708a4a4a8cfac47b5de8bcb0625388964438eb096b10cfd9ea39212c299b5cb32fa943e768db2333cf49ea7def157e
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <consensus/tx_verify.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <cuckoocache.h>
|
||||
#include <flatfile.h>
|
||||
#include <hash.h>
|
||||
#include <index/txindex.h>
|
||||
#include <policy/fees.h>
|
||||
@@ -165,7 +166,7 @@ public:
|
||||
* that it doesn't descend from an invalid block, and then add it to mapBlockIndex.
|
||||
*/
|
||||
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
// Block (dis)connection on a given view:
|
||||
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
|
||||
@@ -204,7 +205,7 @@ private:
|
||||
|
||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
|
||||
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
@@ -317,7 +318,9 @@ static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &
|
||||
static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
|
||||
static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight);
|
||||
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr);
|
||||
static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||
static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly = false);
|
||||
static FlatFileSeq BlockFileSeq();
|
||||
static FlatFileSeq UndoFileSeq();
|
||||
|
||||
bool CheckFinalTx(const CTransaction &tx, int flags)
|
||||
{
|
||||
@@ -1042,7 +1045,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, const Consensus
|
||||
// CBlock and CBlockIndex
|
||||
//
|
||||
|
||||
static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart)
|
||||
static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart)
|
||||
{
|
||||
// Open history file to append
|
||||
CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
|
||||
@@ -1063,7 +1066,7 @@ static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMes
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
|
||||
bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams)
|
||||
{
|
||||
block.SetNull();
|
||||
|
||||
@@ -1089,7 +1092,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus:
|
||||
|
||||
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||
{
|
||||
CDiskBlockPos blockPos;
|
||||
FlatFilePos blockPos;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
blockPos = pindex->GetBlockPos();
|
||||
@@ -1103,9 +1106,9 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start)
|
||||
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start)
|
||||
{
|
||||
CDiskBlockPos hpos = pos;
|
||||
FlatFilePos hpos = pos;
|
||||
hpos.nPos -= 8; // Seek back 8 bytes for meta header
|
||||
CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION);
|
||||
if (filein.IsNull()) {
|
||||
@@ -1140,7 +1143,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos,
|
||||
|
||||
bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start)
|
||||
{
|
||||
CDiskBlockPos block_pos;
|
||||
FlatFilePos block_pos;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
block_pos = pindex->GetBlockPos();
|
||||
@@ -1452,7 +1455,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
|
||||
|
||||
namespace {
|
||||
|
||||
bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
|
||||
bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart)
|
||||
{
|
||||
// Open history file to append
|
||||
CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION);
|
||||
@@ -1481,7 +1484,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint
|
||||
|
||||
static bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex *pindex)
|
||||
{
|
||||
CDiskBlockPos pos = pindex->GetUndoPos();
|
||||
FlatFilePos pos = pindex->GetUndoPos();
|
||||
if (pos.IsNull()) {
|
||||
return error("%s: no undo data available", __func__);
|
||||
}
|
||||
@@ -1627,37 +1630,24 @@ void static FlushBlockFile(bool fFinalize = false)
|
||||
{
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
CDiskBlockPos posOld(nLastBlockFile, 0);
|
||||
FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize);
|
||||
FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize);
|
||||
|
||||
bool status = true;
|
||||
|
||||
FILE *fileOld = OpenBlockFile(posOld);
|
||||
if (fileOld) {
|
||||
if (fFinalize)
|
||||
status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize);
|
||||
status &= FileCommit(fileOld);
|
||||
fclose(fileOld);
|
||||
}
|
||||
|
||||
fileOld = OpenUndoFile(posOld);
|
||||
if (fileOld) {
|
||||
if (fFinalize)
|
||||
status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize);
|
||||
status &= FileCommit(fileOld);
|
||||
fclose(fileOld);
|
||||
}
|
||||
|
||||
status &= BlockFileSeq().Flush(block_pos_old, fFinalize);
|
||||
status &= UndoFileSeq().Flush(undo_pos_old, fFinalize);
|
||||
if (!status) {
|
||||
AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error.");
|
||||
}
|
||||
}
|
||||
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize);
|
||||
|
||||
static bool WriteUndoDataForBlock(const CBlockUndo& blockundo, CValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams)
|
||||
{
|
||||
// Write undo information to disk
|
||||
if (pindex->GetUndoPos().IsNull()) {
|
||||
CDiskBlockPos _pos;
|
||||
FlatFilePos _pos;
|
||||
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40))
|
||||
return error("ConnectBlock(): FindUndoPos failed");
|
||||
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart()))
|
||||
@@ -2134,8 +2124,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
|
||||
// Write blocks and block index to disk.
|
||||
if (fDoFullFlush || fPeriodicWrite) {
|
||||
// Depend on nMinDiskSpace to ensure we can write block index
|
||||
if (!CheckDiskSpace(0, true))
|
||||
return state.Error("out of disk space");
|
||||
if (!CheckDiskSpace(GetBlocksDir())) {
|
||||
return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
|
||||
}
|
||||
// First make sure all block and undo data is flushed to disk.
|
||||
FlushBlockFile();
|
||||
// Then update all block file information (which may refer to block and undo files).
|
||||
@@ -2168,8 +2159,9 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &
|
||||
// twice (once in the log, and once in the tables). This is already
|
||||
// an overestimation, as most will delete an existing entry or
|
||||
// overwrite one. Still, use a conservative safety factor of 2.
|
||||
if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize()))
|
||||
return state.Error("out of disk space");
|
||||
if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * pcoinsTip->GetCacheSize())) {
|
||||
return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
|
||||
}
|
||||
// Flush the chainstate (which may refer to block index entries).
|
||||
if (!pcoinsTip->Flush())
|
||||
return AbortNode(state, "Failed to write to coin database");
|
||||
@@ -2922,7 +2914,7 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
|
||||
}
|
||||
|
||||
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
|
||||
void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams)
|
||||
void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams)
|
||||
{
|
||||
pindexNew->nTx = block.vtx.size();
|
||||
pindexNew->nChainTx = 0;
|
||||
@@ -2968,7 +2960,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
|
||||
}
|
||||
}
|
||||
|
||||
static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
|
||||
static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false)
|
||||
{
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
@@ -3003,21 +2995,13 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int
|
||||
vinfoBlockFile[nFile].nSize += nAddSize;
|
||||
|
||||
if (!fKnown) {
|
||||
unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
|
||||
unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE;
|
||||
if (nNewChunks > nOldChunks) {
|
||||
if (fPruneMode)
|
||||
fCheckForPruning = true;
|
||||
if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos, true)) {
|
||||
FILE *file = OpenBlockFile(pos);
|
||||
if (file) {
|
||||
LogPrintf("Pre-allocating up to position 0x%x in blk%05u.dat\n", nNewChunks * BLOCKFILE_CHUNK_SIZE, pos.nFile);
|
||||
AllocateFileRange(file, pos.nPos, nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
return error("out of disk space");
|
||||
bool out_of_space;
|
||||
size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
|
||||
if (out_of_space) {
|
||||
return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
|
||||
}
|
||||
if (bytes_allocated != 0 && fPruneMode) {
|
||||
fCheckForPruning = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3025,32 +3009,23 @@ static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
|
||||
static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, unsigned int nAddSize)
|
||||
{
|
||||
pos.nFile = nFile;
|
||||
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
unsigned int nNewSize;
|
||||
pos.nPos = vinfoBlockFile[nFile].nUndoSize;
|
||||
nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize;
|
||||
vinfoBlockFile[nFile].nUndoSize += nAddSize;
|
||||
setDirtyFileInfo.insert(nFile);
|
||||
|
||||
unsigned int nOldChunks = (pos.nPos + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
|
||||
unsigned int nNewChunks = (nNewSize + UNDOFILE_CHUNK_SIZE - 1) / UNDOFILE_CHUNK_SIZE;
|
||||
if (nNewChunks > nOldChunks) {
|
||||
if (fPruneMode)
|
||||
fCheckForPruning = true;
|
||||
if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos, true)) {
|
||||
FILE *file = OpenUndoFile(pos);
|
||||
if (file) {
|
||||
LogPrintf("Pre-allocating up to position 0x%x in rev%05u.dat\n", nNewChunks * UNDOFILE_CHUNK_SIZE, pos.nFile);
|
||||
AllocateFileRange(file, pos.nPos, nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
return state.Error("out of disk space");
|
||||
bool out_of_space;
|
||||
size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
|
||||
if (out_of_space) {
|
||||
return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!"));
|
||||
}
|
||||
if (bytes_allocated != 0 && fPruneMode) {
|
||||
fCheckForPruning = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -3435,26 +3410,26 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio
|
||||
}
|
||||
|
||||
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
|
||||
static CDiskBlockPos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const CDiskBlockPos* dbp) {
|
||||
static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, const CChainParams& chainparams, const FlatFilePos* dbp) {
|
||||
unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
|
||||
CDiskBlockPos blockPos;
|
||||
FlatFilePos blockPos;
|
||||
if (dbp != nullptr)
|
||||
blockPos = *dbp;
|
||||
if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, block.GetBlockTime(), dbp != nullptr)) {
|
||||
error("%s: FindBlockPos failed", __func__);
|
||||
return CDiskBlockPos();
|
||||
return FlatFilePos();
|
||||
}
|
||||
if (dbp == nullptr) {
|
||||
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) {
|
||||
AbortNode("Failed to write block");
|
||||
return CDiskBlockPos();
|
||||
return FlatFilePos();
|
||||
}
|
||||
}
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */
|
||||
bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const CDiskBlockPos* dbp, bool* fNewBlock)
|
||||
bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock)
|
||||
{
|
||||
const CBlock& block = *pblock;
|
||||
|
||||
@@ -3516,7 +3491,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
|
||||
// Write block to history file
|
||||
if (fNewBlock) *fNewBlock = true;
|
||||
try {
|
||||
CDiskBlockPos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
|
||||
FlatFilePos blockPos = SaveBlockToDisk(block, pindex->nHeight, chainparams, dbp);
|
||||
if (blockPos.IsNull()) {
|
||||
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
|
||||
return false;
|
||||
@@ -3647,9 +3622,9 @@ void PruneOneBlockFile(const int fileNumber)
|
||||
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune)
|
||||
{
|
||||
for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) {
|
||||
CDiskBlockPos pos(*it, 0);
|
||||
fs::remove(GetBlockPosFilename(pos, "blk"));
|
||||
fs::remove(GetBlockPosFilename(pos, "rev"));
|
||||
FlatFilePos pos(*it, 0);
|
||||
fs::remove(BlockFileSeq().FileName(pos));
|
||||
fs::remove(UndoFileSeq().FileName(pos));
|
||||
LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it);
|
||||
}
|
||||
}
|
||||
@@ -3757,52 +3732,28 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte
|
||||
nLastBlockWeCanPrune, count);
|
||||
}
|
||||
|
||||
bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir)
|
||||
static FlatFileSeq BlockFileSeq()
|
||||
{
|
||||
uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available;
|
||||
|
||||
// Check for nMinDiskSpace bytes (currently 50MB)
|
||||
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
|
||||
return AbortNode("Disk space is low!", _("Error: Disk space is low!"));
|
||||
|
||||
return true;
|
||||
return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
|
||||
static FlatFileSeq UndoFileSeq()
|
||||
{
|
||||
if (pos.IsNull())
|
||||
return nullptr;
|
||||
fs::path path = GetBlockPosFilename(pos, prefix);
|
||||
fs::create_directories(path.parent_path());
|
||||
FILE* file = fsbridge::fopen(path, fReadOnly ? "rb": "rb+");
|
||||
if (!file && !fReadOnly)
|
||||
file = fsbridge::fopen(path, "wb+");
|
||||
if (!file) {
|
||||
LogPrintf("Unable to open file %s\n", path.string());
|
||||
return nullptr;
|
||||
}
|
||||
if (pos.nPos) {
|
||||
if (fseek(file, pos.nPos, SEEK_SET)) {
|
||||
LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string());
|
||||
fclose(file);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return file;
|
||||
return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) {
|
||||
return OpenDiskFile(pos, "blk", fReadOnly);
|
||||
FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly) {
|
||||
return BlockFileSeq().Open(pos, fReadOnly);
|
||||
}
|
||||
|
||||
/** Open an undo file (rev?????.dat) */
|
||||
static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
|
||||
return OpenDiskFile(pos, "rev", fReadOnly);
|
||||
static FILE* OpenUndoFile(const FlatFilePos &pos, bool fReadOnly) {
|
||||
return UndoFileSeq().Open(pos, fReadOnly);
|
||||
}
|
||||
|
||||
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix)
|
||||
fs::path GetBlockPosFilename(const FlatFilePos &pos)
|
||||
{
|
||||
return GetBlocksDir() / strprintf("%s%05u.dat", prefix, pos.nFile);
|
||||
return BlockFileSeq().FileName(pos);
|
||||
}
|
||||
|
||||
CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
|
||||
@@ -3909,7 +3860,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE
|
||||
}
|
||||
for (std::set<int>::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++)
|
||||
{
|
||||
CDiskBlockPos pos(*it, 0);
|
||||
FlatFilePos pos(*it, 0);
|
||||
if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) {
|
||||
return false;
|
||||
}
|
||||
@@ -4342,7 +4293,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
|
||||
|
||||
try {
|
||||
const CBlock& block = chainparams.GenesisBlock();
|
||||
CDiskBlockPos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
|
||||
FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
|
||||
if (blockPos.IsNull())
|
||||
return error("%s: writing genesis block to disk failed", __func__);
|
||||
CBlockIndex *pindex = AddToBlockIndex(block);
|
||||
@@ -4359,10 +4310,10 @@ bool LoadGenesisBlock(const CChainParams& chainparams)
|
||||
return g_chainstate.LoadGenesisBlock(chainparams);
|
||||
}
|
||||
|
||||
bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp)
|
||||
bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp)
|
||||
{
|
||||
// Map of disk positions for blocks with unknown parent (only used for reindex)
|
||||
static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent;
|
||||
static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
|
||||
int64_t nStart = GetTimeMillis();
|
||||
|
||||
int nLoaded = 0;
|
||||
@@ -4448,9 +4399,9 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB
|
||||
while (!queue.empty()) {
|
||||
uint256 head = queue.front();
|
||||
queue.pop_front();
|
||||
std::pair<std::multimap<uint256, CDiskBlockPos>::iterator, std::multimap<uint256, CDiskBlockPos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
|
||||
std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
|
||||
while (range.first != range.second) {
|
||||
std::multimap<uint256, CDiskBlockPos>::iterator it = range.first;
|
||||
std::multimap<uint256, FlatFilePos>::iterator it = range.first;
|
||||
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
|
||||
if (ReadBlockFromDisk(*pblockrecursive, it->second, chainparams.GetConsensus()))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user