changeset 3648:4e4ec61eb33d draft

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.
author Pieter Wuille <pieter.wuille@gmail.com>
date Thu, 16 Aug 2012 02:21:28 +0200
parents fdd92a9e5196
children eb986f1e2e93
files src/main.cpp src/main.h src/util.cpp src/util.h
diffstat 4 files changed, 49 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1844,6 +1844,17 @@
     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 @@
 
     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");
     }
 
-    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");
+    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);
+    }
+
     return true;
 }
 
--- a/src/main.h
+++ b/src/main.h
@@ -29,6 +29,8 @@
 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;
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1137,6 +1137,20 @@
     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
--- a/src/util.h
+++ b/src/util.h
@@ -196,6 +196,7 @@
 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);