Merge pull request #2229 from sipa/prealloc

Native versions for AllocateFileRange()
This commit is contained in:
Gavin Andresen 2013-02-22 09:00:13 -08:00
commit b8f4e42e1b
3 changed files with 54 additions and 2 deletions

View File

@ -1533,7 +1533,7 @@ bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoin
} }
} }
void static FlushBlockFile() void static FlushBlockFile(bool fFinalize = false)
{ {
LOCK(cs_LastBlockFile); LOCK(cs_LastBlockFile);
@ -1541,12 +1541,16 @@ void static FlushBlockFile()
FILE *fileOld = OpenBlockFile(posOld); FILE *fileOld = OpenBlockFile(posOld);
if (fileOld) { if (fileOld) {
if (fFinalize)
TruncateFile(fileOld, infoLastBlockFile.nSize);
FileCommit(fileOld); FileCommit(fileOld);
fclose(fileOld); fclose(fileOld);
} }
fileOld = OpenUndoFile(posOld); fileOld = OpenUndoFile(posOld);
if (fileOld) { if (fileOld) {
if (fFinalize)
TruncateFile(fileOld, infoLastBlockFile.nUndoSize);
FileCommit(fileOld); FileCommit(fileOld);
fclose(fileOld); fclose(fileOld);
} }
@ -1965,7 +1969,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd
} else { } else {
while (infoLastBlockFile.nSize + nAddSize >= MAX_BLOCKFILE_SIZE) { while (infoLastBlockFile.nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
printf("Leaving block file %i: %s\n", nLastBlockFile, infoLastBlockFile.ToString().c_str()); printf("Leaving block file %i: %s\n", nLastBlockFile, infoLastBlockFile.ToString().c_str());
FlushBlockFile(); FlushBlockFile(true);
nLastBlockFile++; nLastBlockFile++;
infoLastBlockFile.SetNull(); infoLastBlockFile.SetNull();
pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine

View File

@ -3,6 +3,15 @@
// Distributed under the MIT/X11 software license, see the accompanying // Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // 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 <fcntl.h>
#include <sys/stat.h>
#endif
#include "util.h" #include "util.h"
#include "sync.h" #include "sync.h"
#include "version.h" #include "version.h"
@ -1152,9 +1161,46 @@ int GetFilesize(FILE* file)
return nFilesize; 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) // 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 // 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) { 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] = {}; static const char buf[65536] = {};
fseek(file, offset, SEEK_SET); fseek(file, offset, SEEK_SET);
while (length > 0) { while (length > 0) {
@ -1164,6 +1210,7 @@ void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
length -= now; length -= now;
} }
#endif
} }
void ShrinkDebugFile() void ShrinkDebugFile()

View File

@ -193,6 +193,7 @@ bool WildcardMatch(const char* psz, const char* mask);
bool WildcardMatch(const std::string& str, const std::string& mask); bool WildcardMatch(const std::string& str, const std::string& mask);
void FileCommit(FILE *fileout); void FileCommit(FILE *fileout);
int GetFilesize(FILE* file); int GetFilesize(FILE* file);
bool TruncateFile(FILE *file, unsigned int length);
void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length);
bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest);
boost::filesystem::path GetDefaultDataDir(); boost::filesystem::path GetDefaultDataDir();