From 288fdc092aff9d7e0cea159196b2e96044a786c7 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 28 Jan 2013 00:07:51 +0100 Subject: [PATCH 1/2] Native versions for AllocateFileRange() --- src/util.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/util.cpp b/src/util.cpp index d8f05cb9f..6ea5e1d83 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3,6 +3,15 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#ifndef WIN32 +// for posix_fallocate +#ifdef __linux__ +#define _POSIX_C_SOURCE 200112L +#endif +#include +#include +#endif + #include "util.h" #include "sync.h" #include "version.h" @@ -1155,6 +1164,35 @@ int GetFilesize(FILE* file) // 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) { +#if defined(WIN32) + // Windows-specific version + HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file)); + LARGE_INTEGER nFileSize; + int64 nEndPos = (int64)offset + length; + nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF; + nFileSize.u.HighPart = nEndPos >> 32; + SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN); + SetEndOfFile(hFile); +#elif defined(MAC_OSX) + // OSX specific version + fstore_t fst; + fst.fst_flags = F_ALLOCATECONTIG; + fst.fst_posmode = F_PEOFPOSMODE; + fst.fst_offset = 0; + fst.fst_length = (off_t)offset + length; + fst.fst_bytesalloc = 0; + if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) { + fst.fst_flags = F_ALLOCATEALL; + fcntl(fileno(file), F_PREALLOCATE, &fst); + } + ftruncate(fileno(file), fst.fst_length); +#elif defined(__linux__) + // Version using posix_fallocate + off_t nEndPos = (off_t)offset + length; + posix_fallocate(fileno(file), 0, nEndPos); +#else + // Fallback version + // TODO: just write one byte per block static const char buf[65536] = {}; fseek(file, offset, SEEK_SET); while (length > 0) { @@ -1164,6 +1202,7 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) { fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway length -= now; } +#endif } void ShrinkDebugFile() From 1eb578796c98f457546059b66eb98fd0efc8e690 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 30 Jan 2013 04:17:33 +0100 Subject: [PATCH 2/2] Drop padding in blk* when finalizing file --- src/main.cpp | 8 ++++++-- src/util.cpp | 8 ++++++++ src/util.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index fe35fbaf2..a94fdc309 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1572,7 +1572,7 @@ bool CBlock::DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &view, bool *p } } -void static FlushBlockFile() +void static FlushBlockFile(bool fFinalize = false) { LOCK(cs_LastBlockFile); @@ -1580,12 +1580,16 @@ void static FlushBlockFile() FILE *fileOld = OpenBlockFile(posOld); if (fileOld) { + if (fFinalize) + TruncateFile(fileOld, infoLastBlockFile.nSize); FileCommit(fileOld); fclose(fileOld); } fileOld = OpenUndoFile(posOld); if (fileOld) { + if (fFinalize) + TruncateFile(fileOld, infoLastBlockFile.nUndoSize); FileCommit(fileOld); fclose(fileOld); } @@ -1991,7 +1995,7 @@ bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeigh } else { while (infoLastBlockFile.nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { printf("Leaving block file %i: %s\n", nLastBlockFile, infoLastBlockFile.ToString().c_str()); - FlushBlockFile(); + FlushBlockFile(true); nLastBlockFile++; infoLastBlockFile.SetNull(); pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine diff --git a/src/util.cpp b/src/util.cpp index 6ea5e1d83..4ac66d466 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1161,6 +1161,14 @@ int GetFilesize(FILE* file) return nFilesize; } +bool TruncateFile(FILE *file, unsigned int length) { +#if defined(WIN32) + return _chsize(_fileno(file), length) == 0; +#else + return ftruncate(fileno(file), length) == 0; +#endif +} + // 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) { diff --git a/src/util.h b/src/util.h index 97911d749..1d2986707 100644 --- a/src/util.h +++ b/src/util.h @@ -193,6 +193,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); +bool TruncateFile(FILE *file, unsigned int length); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); boost::filesystem::path GetDefaultDataDir();