aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-08-16 02:21:28 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2012-10-20 23:08:57 +0200
commitbba89aa82a80f0373dcb7288d96d5b0fcb453d73 (patch)
treef3b4fd8649021b52e19cfdf4620ffead5f30910e
parent5382bcf8cd23c36a435c29080770a79b5e28af42 (diff)
Pre-allocate block and undo files in chunks
Introduce a AllocateFileRange() function in util, which wipes or at least allocates a given range of a file. It can be overriden by more efficient OS-dependent versions if necessary. Block and undo files are now allocated in chunks of 16 and 1 MiB, respectively.
-rw-r--r--src/main.cpp41
-rw-r--r--src/main.h2
-rw-r--r--src/util.cpp14
-rw-r--r--src/util.h1
4 files changed, 49 insertions, 9 deletions
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);