diff --git a/src/main.cpp b/src/main.cpp index 15a2331376..616845e929 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1844,6 +1844,17 @@ bool FindBlockPos(CTxDB &txdb, CDiskBlockPos &pos, unsigned int nAddSize, unsign infoLastBlockFile.nSize += nAddSize; infoLastBlockFile.AddBlock(nHeight, nTime); + unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; + unsigned int nNewChunks = (infoLastBlockFile.nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; + if (nNewChunks > nOldChunks) { + FILE *file = OpenBlockFile(pos); + if (file) { + printf("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); + } + if (!txdb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) return error("FindBlockPos() : cannot write updated block info"); if (fUpdatedLast) @@ -1858,21 +1869,33 @@ bool FindUndoPos(CTxDB &txdb, int nFile, CDiskBlockPos &pos, unsigned int nAddSi LOCK(cs_LastBlockFile); + unsigned int nNewSize; if (nFile == nLastBlockFile) { pos.nPos = infoLastBlockFile.nUndoSize; - infoLastBlockFile.nUndoSize += nAddSize; + nNewSize = (infoLastBlockFile.nUndoSize += nAddSize); if (!txdb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) return error("FindUndoPos() : cannot write updated block info"); - return true; + } else { + CBlockFileInfo info; + if (!txdb.ReadBlockFileInfo(nFile, info)) + return error("FindUndoPos() : cannot read block info"); + pos.nPos = info.nUndoSize; + nNewSize = (info.nUndoSize += nAddSize); + if (!txdb.WriteBlockFileInfo(nFile, info)) + return error("FindUndoPos() : cannot write updated block info"); + } + + 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) { + FILE *file = OpenUndoFile(pos); + if (file) { + printf("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); } - CBlockFileInfo info; - if (!txdb.ReadBlockFileInfo(nFile, info)) - return error("FindUndoPos() : cannot read block info"); - pos.nPos = info.nUndoSize; - info.nUndoSize += nAddSize; - if (!txdb.WriteBlockFileInfo(nFile, info)) - return error("FindUndoPos() : cannot write updated block info"); return true; } diff --git a/src/main.h b/src/main.h index 449cc47df8..936a4e184d 100644 --- a/src/main.h +++ b/src/main.h @@ -29,6 +29,8 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; static const unsigned int MAX_INV_SZ = 50000; static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB +static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB +static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB static const int64 MIN_TX_FEE = 50000; static const int64 MIN_RELAY_TX_FEE = 10000; static const int64 MAX_MONEY = 21000000 * COIN; diff --git a/src/util.cpp b/src/util.cpp index c72b84bfa4..9162886450 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1137,6 +1137,20 @@ int GetFilesize(FILE* file) return nFilesize; } +// this function tries to make a particular range of a file allocated (corresponding to disk space) +// it is advisory, and the range specified in the arguments will never contain live data +void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { + static const char buf[65536] = {}; + fseek(file, offset, SEEK_SET); + while (length > 0) { + unsigned int now = 65536; + if (length < now) + now = length; + fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway + length -= now; + } +} + void ShrinkDebugFile() { // Scroll debug.log if it's getting too big diff --git a/src/util.h b/src/util.h index d80b3c28b2..b798f60aa7 100644 --- a/src/util.h +++ b/src/util.h @@ -196,6 +196,7 @@ bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); void FileCommit(FILE *fileout); int GetFilesize(FILE* file); +void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); boost::filesystem::path GetDefaultDataDir(); const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);