diff --git a/CMakeLists.txt b/CMakeLists.txt index eaaa854c4f7e..8ccff3d1251e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,7 @@ set(SERVER_SOURCES ./src/chain.cpp ./src/checkpoints.cpp ./src/consensus/tx_verify.cpp + ./src/flatfile.cpp ./src/httprpc.cpp ./src/httpserver.cpp ./src/indirectmap.h @@ -416,7 +417,7 @@ set(UTIL_SOURCES ./src/arith_uint256.cpp ./src/uint256.cpp ./src/util/threadnames.cpp - ./src/util.cpp + ./src/util/system.cpp ./src/utilstrencodings.cpp ./src/utilmoneystr.cpp ./src/utiltime.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 75a59b125d0d..2517edf8cbb4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,6 +190,7 @@ BITCOIN_CORE_H = \ pairresult.h \ addressbook.h \ wallet/db.h \ + flatfile.h \ fs.h \ hash.h \ httprpc.h \ @@ -283,7 +284,7 @@ BITCOIN_CORE_H = \ uint256.h \ undo.h \ util/memory.h \ - util.h \ + util/system.h \ util/macros.h \ util/threadnames.h \ utilstrencodings.h \ @@ -326,6 +327,7 @@ libbitcoin_server_a_SOURCES = \ checkpoints.cpp \ consensus/params.cpp \ consensus/tx_verify.cpp \ + flatfile.cpp \ consensus/zerocoin_verify.cpp \ evo/deterministicmns.cpp \ evo/evodb.cpp \ @@ -546,7 +548,7 @@ libbitcoin_util_a_SOURCES = \ sync.cpp \ threadinterrupt.cpp \ uint256.cpp \ - util.cpp \ + util/system.cpp \ utilmoneystr.cpp \ util/threadnames.cpp \ utilstrencodings.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 9c47b8287945..a3bf6225cdb6 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -64,6 +64,7 @@ BITCOIN_TESTS =\ test/DoS_tests.cpp \ test/evo_deterministicmns_tests.cpp \ test/evo_specialtx_tests.cpp \ + test/flatfile_tests.cpp \ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/key_tests.cpp \ diff --git a/src/addrdb.cpp b/src/addrdb.cpp index cdd67f1f19a3..318bd7e96374 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -14,7 +14,7 @@ #include "random.h" #include "streams.h" #include "tinyformat.h" -#include "util.h" +#include "util/system.h" namespace { diff --git a/src/addrman.h b/src/addrman.h index 872916686547..b78d391959aa 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -12,7 +12,7 @@ #include "random.h" #include "sync.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" #include #include diff --git a/src/bench/bench_pivx.cpp b/src/bench/bench_pivx.cpp index 9bf3993397cb..aa3ac218b479 100644 --- a/src/bench/bench_pivx.cpp +++ b/src/bench/bench_pivx.cpp @@ -6,7 +6,7 @@ #include "bench.h" #include "key.h" -#include "util.h" +#include "util/system.h" int main(int argc, char** argv) diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 5e1fa93fac5e..6a1bfacfdd01 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "bench.h" -#include "util.h" +#include "util/system.h" #include "checkqueue.h" #include "prevector.h" #include "random.h" diff --git a/src/bip38.cpp b/src/bip38.cpp index fa4516cf98c9..e83f81b1d09f 100644 --- a/src/bip38.cpp +++ b/src/bip38.cpp @@ -8,7 +8,7 @@ #include "crypto/aes.h" #include "hash.h" #include "pubkey.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "random.h" diff --git a/src/blockassembler.cpp b/src/blockassembler.cpp index e500ffccc1ce..c86a6b5e440d 100644 --- a/src/blockassembler.cpp +++ b/src/blockassembler.cpp @@ -21,7 +21,7 @@ #include "spork.h" #include "timedata.h" #include "txmempool.h" -#include "util.h" +#include "util/system.h" #include "validation.h" #include "validationinterface.h" diff --git a/src/chain.cpp b/src/chain.cpp index 5a14cacdf2b4..5691d31d59da 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -142,9 +142,9 @@ std::string CBlockIndex::ToString() const GetBlockHash().ToString()); } -CDiskBlockPos CBlockIndex::GetBlockPos() const +FlatFilePos CBlockIndex::GetBlockPos() const { - CDiskBlockPos ret; + FlatFilePos ret; if (nStatus & BLOCK_HAVE_DATA) { ret.nFile = nFile; ret.nPos = nDataPos; @@ -152,9 +152,9 @@ CDiskBlockPos CBlockIndex::GetBlockPos() const return ret; } -CDiskBlockPos CBlockIndex::GetUndoPos() const +FlatFilePos CBlockIndex::GetUndoPos() const { - CDiskBlockPos ret; + FlatFilePos ret; if (nStatus & BLOCK_HAVE_UNDO) { ret.nFile = nFile; ret.nPos = nUndoPos; diff --git a/src/chain.h b/src/chain.h index 6c80e254bdb0..fd16e8e5f68c 100644 --- a/src/chain.h +++ b/src/chain.h @@ -11,13 +11,14 @@ #define BITCOIN_CHAIN_H #include "chainparams.h" +#include "flatfile.h" #include "optional.h" #include "pow.h" #include "primitives/block.h" #include "timedata.h" #include "tinyformat.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "libzerocoin/Denominations.h" #include @@ -87,47 +88,6 @@ class CBlockFileInfo } }; -struct CDiskBlockPos { - int nFile; - unsigned int nPos; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED)); - READWRITE(VARINT(nPos)); - } - - CDiskBlockPos() - { - SetNull(); - } - - CDiskBlockPos(int nFileIn, unsigned int nPosIn) - { - nFile = nFileIn; - nPos = nPosIn; - } - - friend bool operator==(const CDiskBlockPos& a, const CDiskBlockPos& b) - { - return (a.nFile == b.nFile && a.nPos == b.nPos); - } - - friend bool operator!=(const CDiskBlockPos& a, const CDiskBlockPos& b) - { - return !(a == b); - } - - void SetNull() - { - nFile = -1; - nPos = 0; - } - bool IsNull() const { return (nFile == -1); } -}; - enum BlockStatus { //! Unused. BLOCK_VALID_UNKNOWN = 0, @@ -253,8 +213,8 @@ class CBlockIndex std::string ToString() const; - CDiskBlockPos GetBlockPos() const; - CDiskBlockPos GetUndoPos() const; + FlatFilePos GetBlockPos() const; + FlatFilePos GetUndoPos() const; CBlockHeader GetBlockHeader() const; uint256 GetBlockHash() const { return *phashBlock; } int64_t GetBlockTime() const { return (int64_t)nTime; } diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 3b5b98b3dab8..849a850c8587 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -7,7 +7,7 @@ #include "chainparamsbase.h" #include "tinyformat.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index b0fdae284755..ef28d107065c 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -5,7 +5,7 @@ #include "consensus/params.h" #include "consensus/upgrades.h" -#include "util.h" +#include "util/system.h" namespace Consensus { diff --git a/src/core_read.cpp b/src/core_read.cpp index b9a6eef164d0..9509b4015075 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -10,7 +10,7 @@ #include "script/script.h" #include "serialize.h" #include "streams.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "version.h" diff --git a/src/core_write.cpp b/src/core_write.cpp index 266e95e0deeb..041fcc5563cf 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -13,7 +13,7 @@ #include "serialize.h" #include "streams.h" #include -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "utilstrencodings.h" diff --git a/src/crypter.cpp b/src/crypter.cpp index f0929f74fb53..83420a3c0486 100644 --- a/src/crypter.cpp +++ b/src/crypter.cpp @@ -9,7 +9,7 @@ #include "crypto/sha512.h" #include "script/script.h" #include "script/standard.h" -#include "util.h" +#include "util/system.h" #include "init.h" #include "uint256.h" diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 5ac82fb2dc5f..f44b613cf497 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -4,7 +4,7 @@ #include "dbwrapper.h" -#include "util.h" +#include "util/system.h" #include #include diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 3889651a9d71..dd0a48c24b28 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -9,7 +9,7 @@ #include "fs.h" #include "serialize.h" #include "streams.h" -#include "util.h" +#include "util/system.h" #include "version.h" #include diff --git a/src/flatfile.cpp b/src/flatfile.cpp new file mode 100644 index 000000000000..ec136272e7c3 --- /dev/null +++ b/src/flatfile.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include "flatfile.h" +#include "logging.h" +#include "tinyformat.h" +#include "util/system.h" + +FlatFileSeq::FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size) : + m_dir(std::move(dir)), + m_prefix(prefix), + m_chunk_size(chunk_size) +{ + if (chunk_size == 0) { + throw std::invalid_argument("chunk_size must be positive"); + } +} + +std::string FlatFilePos::ToString() const +{ + return strprintf("FlatFilePos(nFile=%i, nPos=%i)", nFile, nPos); +} + +fs::path FlatFileSeq::FileName(const FlatFilePos& pos) const +{ + return m_dir / strprintf("%s%05u.dat", m_prefix, pos.nFile); +} + +FILE* FlatFileSeq::Open(const FlatFilePos& pos, bool read_only) +{ + if (pos.IsNull()) { + return nullptr; + } + fs::path path = FileName(pos); + fs::create_directories(path.parent_path()); + FILE* file = fsbridge::fopen(path, read_only ? "rb": "rb+"); + if (!file && !read_only) + file = fsbridge::fopen(path, "wb+"); + if (!file) { + LogPrintf("Unable to open file %s\n", path.string()); + return nullptr; + } + if (pos.nPos && fseek(file, pos.nPos, SEEK_SET)) { + LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); + fclose(file); + return nullptr; + } + return file; +} + +size_t FlatFileSeq::Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space) +{ + out_of_space = false; + + unsigned int n_old_chunks = (pos.nPos + m_chunk_size - 1) / m_chunk_size; + unsigned int n_new_chunks = (pos.nPos + add_size + m_chunk_size - 1) / m_chunk_size; + if (n_new_chunks > n_old_chunks) { + size_t old_size = pos.nPos; + size_t new_size = n_new_chunks * m_chunk_size; + size_t inc_size = new_size - old_size; + + if (CheckDiskSpace(m_dir, inc_size)) { + FILE *file = Open(pos); + if (file) { + LogPrintf("Pre-allocating up to position 0x%x in %s%05u.dat\n", new_size, m_prefix, pos.nFile); + AllocateFileRange(file, pos.nPos, inc_size); + fclose(file); + return inc_size; + } + } else { + out_of_space = true; + } + } + return 0; +} + +bool FlatFileSeq::Flush(const FlatFilePos& pos, bool finalize) +{ + FILE* file = Open(FlatFilePos(pos.nFile, 0)); // Avoid fseek to nPos + if (!file) { + return error("%s: failed to open file %d", __func__, pos.nFile); + } + if (finalize && !TruncateFile(file, pos.nPos)) { + fclose(file); + return error("%s: failed to truncate file %d", __func__, pos.nFile); + } + if (!FileCommit(file)) { + fclose(file); + return error("%s: failed to commit file %d", __func__, pos.nFile); + } + + fclose(file); + return true; +} diff --git a/src/flatfile.h b/src/flatfile.h new file mode 100644 index 000000000000..17eaaeb7b09d --- /dev/null +++ b/src/flatfile.h @@ -0,0 +1,96 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_FLATFILE_H +#define BITCOIN_FLATFILE_H + +#include + +#include "fs.h" +#include "serialize.h" + +struct FlatFilePos +{ + int nFile; + unsigned int nPos; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(VARINT(nFile, VarIntMode::NONNEGATIVE_SIGNED)); + READWRITE(VARINT(nPos)); + } + + FlatFilePos() : nFile(-1), nPos(0) {} + + FlatFilePos(int nFileIn, unsigned int nPosIn) : + nFile(nFileIn), + nPos(nPosIn) + {} + + friend bool operator==(const FlatFilePos &a, const FlatFilePos &b) { + return (a.nFile == b.nFile && a.nPos == b.nPos); + } + + friend bool operator!=(const FlatFilePos &a, const FlatFilePos &b) { + return !(a == b); + } + + void SetNull() { nFile = -1; nPos = 0; } + bool IsNull() const { return (nFile == -1); } + + std::string ToString() const; +}; + +/** + * FlatFileSeq represents a sequence of numbered files storing raw data. This class facilitates + * access to and efficient management of these files. + */ +class FlatFileSeq +{ +private: + const fs::path m_dir; + const char* const m_prefix; + const size_t m_chunk_size; + +public: + /** + * Constructor + * + * @param dir The base directory that all files live in. + * @param prefix A short prefix given to all file names. + * @param chunk_size Disk space is pre-allocated in multiples of this amount. + */ + FlatFileSeq(fs::path dir, const char* prefix, size_t chunk_size); + + /** Get the name of the file at the given position. */ + fs::path FileName(const FlatFilePos& pos) const; + + /** Open a handle to the file at the given position. */ + FILE* Open(const FlatFilePos& pos, bool read_only = false); + + /** + * Allocate additional space in a file after the given starting position. The amount allocated + * will be the minimum multiple of the sequence chunk size greater than add_size. + * + * @param[in] pos The starting position that bytes will be allocated after. + * @param[in] add_size The minimum number of bytes to be allocated. + * @param[out] out_of_space Whether the allocation failed due to insufficient disk space. + * @return The number of bytes successfully allocated. + */ + size_t Allocate(const FlatFilePos& pos, size_t add_size, bool& out_of_space); + + /** + * Commit a file to disk, and optionally truncate off extra pre-allocated bytes if final. + * + * @param[in] pos The first unwritten position in the file to be flushed. + * @param[in] finalize True if no more data will be written to this file. + * @return true on success, false on failure. + */ + bool Flush(const FlatFilePos& pos, bool finalize = false); +}; + +#endif // BITCOIN_FLATFILE_H diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 56bf3047c8b4..24db0d455414 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -13,7 +13,7 @@ #include "rpc/server.h" #include "random.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "guiinterface.h" diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 02317dbea12c..ed88665cfe93 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -7,7 +7,7 @@ #include "chainparamsbase.h" #include "compat.h" -#include "util.h" +#include "util/system.h" #include "netbase.h" #include "rpc/protocol.h" // For HTTP status codes #include "sync.h" diff --git a/src/init.cpp b/src/init.cpp index 200d6ea340dc..002ff1f954b3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -50,7 +50,7 @@ #include "torcontrol.h" #include "guiinterface.h" #include "guiinterfaceutil.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "util/threadnames.h" #include "validation.h" @@ -688,8 +688,8 @@ void ThreadImport(const std::vector& vImportFiles) CImportingNow imp; int nFile = 0; while (true) { - CDiskBlockPos pos(nFile, 0); - if (!fs::exists(GetBlockPosFilename(pos, "blk"))) + FlatFilePos pos(nFile, 0); + if (!fs::exists(GetBlockPosFilename(pos))) break; // No block files left to reindex FILE* file = OpenBlockFile(pos, true); if (!file) @@ -1735,11 +1735,11 @@ bool AppInitMain() #endif // ********************************************************* Step 9: import blocks - if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ false)) { + if (!CheckDiskSpace(GetDataDir())) { UIError(strprintf(_("Error: Disk space is low for %s"), GetDataDir())); return false; } - if (!CheckDiskSpace(/* additional_bytes */ 0, /* blocks_dir */ true)) { + if (!CheckDiskSpace(GetBlocksDir())) { UIError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir())); return false; } diff --git a/src/kernel.cpp b/src/kernel.cpp index 0b41f9755ab9..a764bef3af31 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -12,7 +12,7 @@ #include "policy/policy.h" #include "script/interpreter.h" #include "stakeinput.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "validation.h" #include "zpivchain.h" diff --git a/src/keystore.cpp b/src/keystore.cpp index 47e8fa5723b2..09c3390b17c6 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -10,7 +10,7 @@ #include "key.h" #include "script/script.h" #include "script/standard.h" -#include "util.h" +#include "util/system.h" bool CKeyStore::AddKey(const CKey& key) diff --git a/src/libzerocoin/Coin.h b/src/libzerocoin/Coin.h index 290acc12af5f..8860d41c48d6 100644 --- a/src/libzerocoin/Coin.h +++ b/src/libzerocoin/Coin.h @@ -17,7 +17,7 @@ #include "Params.h" #include "amount.h" #include "bignum.h" -#include "util.h" +#include "util/system.h" #include "key.h" namespace libzerocoin diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp index b06d8fb741b7..9ae558cfa265 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode-payments.cpp @@ -15,7 +15,7 @@ #include "net_processing.h" #include "spork.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp index a7352ebaf803..7fcec9276c9b 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode-sync.cpp @@ -12,7 +12,7 @@ #include "masternodeman.h" #include "netmessagemaker.h" #include "spork.h" -#include "util.h" +#include "util/system.h" #include "addrman.h" // clang-format on diff --git a/src/masternode.cpp b/src/masternode.cpp index 2e566b56c9f8..a4780d0635c1 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -11,7 +11,7 @@ #include "masternodeman.h" #include "netbase.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "wallet/wallet.h" #define MASTERNODE_MIN_CONFIRMATIONS_REGTEST 1 diff --git a/src/masternode.h b/src/masternode.h index 20f0bd1ab9bd..048826fb393a 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -13,7 +13,7 @@ #include "serialize.h" #include "sync.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" /* Depth of the block pinged by masternodes */ static const unsigned int MNPING_DEPTH = 12; diff --git a/src/masternodeconfig.cpp b/src/masternodeconfig.cpp index 265e4b91a521..8e156b21a512 100644 --- a/src/masternodeconfig.cpp +++ b/src/masternodeconfig.cpp @@ -6,7 +6,7 @@ #include "fs.h" #include "netbase.h" -#include "util.h" +#include "util/system.h" #include "guiinterface.h" #include diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index c4e52e57e584..fd38d3e3873a 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -16,7 +16,7 @@ #include "netmessagemaker.h" #include "net_processing.h" #include "spork.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/masternodeman.h b/src/masternodeman.h index e675ad0f6684..1859304df0ee 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -13,7 +13,7 @@ #include "masternode.h" #include "net.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #define MASTERNODES_DUMP_SECONDS (15 * 60) #define MASTERNODES_DSEG_SECONDS (3 * 60 * 60) diff --git a/src/messagesigner.cpp b/src/messagesigner.cpp index 386f47c86885..46df3e55b824 100644 --- a/src/messagesigner.cpp +++ b/src/messagesigner.cpp @@ -7,7 +7,7 @@ #include "hash.h" #include "messagesigner.h" #include "tinyformat.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" const std::string strMessageMagic = "DarkNet Signed Message:\n"; diff --git a/src/miner.cpp b/src/miner.cpp index 68291fc60ef2..8aa545d9b1ea 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -20,7 +20,7 @@ #include "primitives/block.h" #include "primitives/transaction.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" diff --git a/src/netbase.cpp b/src/netbase.cpp index 442260e58a81..12123fd47f13 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -14,7 +14,7 @@ #include "sync.h" #include "uint256.h" #include "random.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include diff --git a/src/noui.cpp b/src/noui.cpp index 147d61cdb81e..20b280ae8ecf 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -8,7 +8,7 @@ #include "noui.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include #include diff --git a/src/pivx-cli.cpp b/src/pivx-cli.cpp index f98fcb1f619b..9775106c6d2e 100644 --- a/src/pivx-cli.cpp +++ b/src/pivx-cli.cpp @@ -10,7 +10,7 @@ #include "fs.h" #include "rpc/client.h" #include "rpc/protocol.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include diff --git a/src/pivx-tx.cpp b/src/pivx-tx.cpp index 94259d7bfdc8..1621aff68ecf 100644 --- a/src/pivx-tx.cpp +++ b/src/pivx-tx.cpp @@ -14,7 +14,7 @@ #include "script/script.h" #include "script/sign.h" #include -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "utilstrencodings.h" diff --git a/src/pivxd.cpp b/src/pivxd.cpp index bcde06ae07e0..ad02677ccc8f 100644 --- a/src/pivxd.cpp +++ b/src/pivxd.cpp @@ -12,7 +12,7 @@ #include "masternodeconfig.h" #include "noui.h" #include "rpc/server.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 93f789175260..3e2c169c99c9 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -10,7 +10,7 @@ #include "primitives/transaction.h" #include "streams.h" #include "txmempool.h" -#include "util.h" +#include "util/system.h" void TxConfirmStats::Initialize(std::vector& defaultBuckets, unsigned int maxConfirms, double _decay) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 41f61031449b..deae2082bead 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -9,7 +9,7 @@ #include "consensus/tx_verify.h" // for IsFinal() #include "tinyformat.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "validation.h" diff --git a/src/pow.cpp b/src/pow.cpp index 384cb742957c..6b41d9796956 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -11,7 +11,7 @@ #include "chainparams.h" #include "primitives/block.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 84c32be40eae..e0b7fd2d618c 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -11,7 +11,7 @@ #include "script/sign.h" #include "tinyformat.h" #include "utilstrencodings.h" -#include "util.h" +#include "util/system.h" uint256 CBlockHeader::GetHash() const { diff --git a/src/protocol.cpp b/src/protocol.cpp index ea570180ff1b..f40fc79aed7e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -7,7 +7,7 @@ #include "protocol.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #ifndef WIN32 diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 136faffd829e..51096dcabaa4 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -19,7 +19,7 @@ #include "net.h" #include "netbase.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "warnings.h" #include diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index c13d07b808c0..ba4a73b4336a 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -17,7 +17,7 @@ #include "protocol.h" #include "script/script.h" #include "script/standard.h" -#include "util.h" +#include "util/system.h" #ifdef WIN32 #ifdef _WIN32_WINNT diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 1ed9cf798598..28f8a1e99fde 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -10,7 +10,7 @@ #include "fs.h" #include "guiutil.h" -#include "util.h" +#include "util/system.h" #include "qt/pivx/qtutils.h" #include diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 09c1a585bd80..7f4d39da2702 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -18,7 +18,7 @@ #include "net.h" #include "netbase.h" #include "txdb.h" // for -dbcache defaults -#include "util.h" +#include "util/system.h" #ifdef ENABLE_WALLET #include "masternodeconfig.h" diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index f8265c4fd027..a9554e7c5b30 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -14,7 +14,7 @@ #include "base58.h" #include "chainparams.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "wallet/wallet.h" #include diff --git a/src/qt/pivx.cpp b/src/qt/pivx.cpp index d0b9a4d76c68..b96eddba4208 100644 --- a/src/qt/pivx.cpp +++ b/src/qt/pivx.cpp @@ -33,7 +33,7 @@ #include "init.h" #include "rpc/server.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "warnings.h" #ifdef ENABLE_WALLET diff --git a/src/qt/pivx/masternodeswidget.cpp b/src/qt/pivx/masternodeswidget.cpp index 722ade7abd02..f9b32472259c 100644 --- a/src/qt/pivx/masternodeswidget.cpp +++ b/src/qt/pivx/masternodeswidget.cpp @@ -21,7 +21,7 @@ #include "sync.h" #include "wallet/wallet.h" #include "askpassphrasedialog.h" -#include "util.h" +#include "util/system.h" #include "qt/pivx/optionbutton.h" #include #include diff --git a/src/qt/pivx/pivxgui.cpp b/src/qt/pivx/pivxgui.cpp index 77594265f991..dadf137304d8 100644 --- a/src/qt/pivx/pivxgui.cpp +++ b/src/qt/pivx/pivxgui.cpp @@ -19,7 +19,7 @@ #include "qt/pivx/defaultdialog.h" #include "init.h" -#include "util.h" +#include "util/system.h" #include #include diff --git a/src/qt/pivx/settings/settingsconsolewidget.cpp b/src/qt/pivx/settings/settingsconsolewidget.cpp index 0e1fd165a542..2f991f004171 100644 --- a/src/qt/pivx/settings/settingsconsolewidget.cpp +++ b/src/qt/pivx/settings/settingsconsolewidget.cpp @@ -13,7 +13,7 @@ #include "chainparams.h" #include "sapling/key_io_sapling.h" -#include "util.h" +#include "util/system.h" #include "utilitydialog.h" #ifdef ENABLE_WALLET diff --git a/src/qt/pivx/settings/settingsinformationwidget.cpp b/src/qt/pivx/settings/settingsinformationwidget.cpp index 2294a3ddbf0d..39fbf03ad7b1 100644 --- a/src/qt/pivx/settings/settingsinformationwidget.cpp +++ b/src/qt/pivx/settings/settingsinformationwidget.cpp @@ -8,7 +8,7 @@ #include "clientmodel.h" #include "chainparams.h" #include "db.h" -#include "util.h" +#include "util/system.h" #include "guiutil.h" #include "qt/pivx/qtutils.h" diff --git a/src/qt/pivx/splash.cpp b/src/qt/pivx/splash.cpp index 149f72ff4fee..fa07fe393117 100644 --- a/src/qt/pivx/splash.cpp +++ b/src/qt/pivx/splash.cpp @@ -10,7 +10,7 @@ #include "init.h" #include "guiinterface.h" #include "networkstyle.h" -#include "util.h" +#include "util/system.h" #include "version.h" #include "guiutil.h" diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index ac64e526d96b..10da3b125dc4 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -15,7 +15,7 @@ #include "chainparams.h" #include "netbase.h" -#include "util.h" +#include "util/system.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #endif // ENABLE_WALLET diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 5a23c4e9a394..085aac9aff33 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -8,7 +8,7 @@ #include "config/pivx-config.h" #endif -#include "util.h" +#include "util/system.h" #include "uritests.h" #include diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index da2aaa375ede..1cea8e4f236e 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -16,7 +16,7 @@ #include "interfaces/handler.h" #include "sync.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "wallet/wallet.h" #include diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index 089a58e5c8ea..6eea16dd421b 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -15,7 +15,7 @@ #include "intro.h" #include "guiutil.h" #include "qt/pivx/qtutils.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 395cbc6e79ec..a3d8d975e68a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -18,7 +18,7 @@ #include "rpc/server.h" #include "sync.h" #include "txdb.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "utilstrencodings.h" #include "hash.h" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 794b7fb4fd63..7ae80a8d0235 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -16,7 +16,7 @@ #include "rpc/server.h" #include "spork.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #include "wallet/walletdb.h" diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 110fae714870..66fc589ac83f 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -14,7 +14,7 @@ #include "sync.h" #include "timedata.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "version.h" #include "validation.h" diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 6e4fe2ca930c..a493397768e6 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -9,7 +9,7 @@ #include "random.h" #include "tinyformat.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "utiltime.h" #include "version.h" diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 482b317d8b32..7031123e07f3 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -13,7 +13,7 @@ #include "random.h" #include "sync.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #ifdef ENABLE_WALLET diff --git a/src/sapling/crypter_sapling.cpp b/src/sapling/crypter_sapling.cpp index 2921ca1d99c7..5860a4e89be4 100644 --- a/src/sapling/crypter_sapling.cpp +++ b/src/sapling/crypter_sapling.cpp @@ -7,7 +7,7 @@ #include "script/script.h" #include "script/standard.h" -#include "util.h" +#include "util/system.h" #include "uint256.h" #include "wallet/wallet.h" diff --git a/src/sapling/sapling_validation.cpp b/src/sapling/sapling_validation.cpp index e2ac6f248c99..838ad45d400f 100644 --- a/src/sapling/sapling_validation.cpp +++ b/src/sapling/sapling_validation.cpp @@ -8,7 +8,7 @@ #include "consensus/consensus.h" // for MAX_BLOCK_SIZE_CURRENT #include "script/interpreter.h" // for SigHash #include "consensus/validation.h" // for CValidationState -#include "util.h" // for error() +#include "util/system.h" // for error() #include "consensus/upgrades.h" // for CurrentEpochBranchId() #include diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index e9312b4cf5e4..7394e7879a0c 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -11,7 +11,7 @@ #include "script/script.h" #include "script/sign.h" #include "script/standard.h" -#include "util.h" +#include "util/system.h" diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 37e0998da63c..c5198131354e 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -11,7 +11,7 @@ #include "pubkey.h" #include "random.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 7a34a872207b..12878f4fb885 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -12,7 +12,7 @@ #include "primitives/transaction.h" #include "script/standard.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" typedef std::vector valtype; diff --git a/src/spork.h b/src/spork.h index 89d18955e3f6..814261e6daa2 100644 --- a/src/spork.h +++ b/src/spork.h @@ -13,7 +13,7 @@ #include "net.h" #include "sporkid.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "protocol.h" diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 7d6403774ccd..db5df51ce43f 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -96,6 +96,7 @@ set(BITCOIN_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/DoS_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/evo_deterministicmns_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/evo_specialtx_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/flatfile_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/getarg_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hash_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/key_tests.cpp diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 349af79763f2..36146b6b47d8 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -17,7 +17,7 @@ #include "pow.h" #include "script/sign.h" #include "serialize.h" -#include "util.h" +#include "util/system.h" #include "validation.h" #include diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 2a35d3b00bfc..3d478c10bead 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -8,7 +8,7 @@ // #include "chainparams.h" -#include "util.h" +#include "util/system.h" #include "test/test_bitcoin.h" diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index 9976268ce9c2..c22e21ad92b0 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" +#include "util/system.h" #include "support/allocators/zeroafterfree.h" #include "test/test_pivx.h" diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 5e907e58ba3b..11b50bbe9f5d 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -12,7 +12,7 @@ #include "key.h" #include "script/script.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "test/test_pivx.h" diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 9b99d10fca7c..63dba3864b0f 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -13,7 +13,7 @@ #include "serialize.h" #include "streams.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "test/test_pivx.h" diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp index 7dac65943ea6..c0bcbb7ba67b 100644 --- a/src/test/compress_tests.cpp +++ b/src/test/compress_tests.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "compressor.h" -#include "util.h" +#include "util/system.h" #include "test/test_pivx.h" #include diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 7da815912b49..d060a03eb8a1 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -24,7 +24,7 @@ BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(dbwrapper) { { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper")); CDBWrapper dbw(ph, (1 << 20), true, false); char key = 'k'; uint256 in = GetRandHash(); @@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_basic_data) BOOST_AUTO_TEST_CASE(dbwrapper_batch) { { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper_batch")); CDBWrapper dbw(ph, (1 << 20), true, false); char key = 'i'; @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) BOOST_AUTO_TEST_CASE(dbwrapper_iterator) { { - fs::path ph = fs::temp_directory_path() / fs::unique_path(); + fs::path ph = SetDataDir(std::string("dbwrapper_iterator")); CDBWrapper dbw(ph, (1 << 20), true, false); // The two keys are intentionally chosen for ordering diff --git a/src/test/flatfile_tests.cpp b/src/test/flatfile_tests.cpp new file mode 100644 index 000000000000..e02ae7c0cf4b --- /dev/null +++ b/src/test/flatfile_tests.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "flatfile.h" +#include "test/test_pivx.h" + +#include + +BOOST_FIXTURE_TEST_SUITE(flatfile_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(flatfile_filename) +{ + auto data_dir = SetDataDir("flatfile_test"); + + FlatFilePos pos(456, 789); + + FlatFileSeq seq1(data_dir, "a", 16 * 1024); + BOOST_CHECK_EQUAL(seq1.FileName(pos), data_dir / "a00456.dat"); + + FlatFileSeq seq2(data_dir / "a", "b", 16 * 1024); + BOOST_CHECK_EQUAL(seq2.FileName(pos), data_dir / "a" / "b00456.dat"); +} + +BOOST_AUTO_TEST_CASE(flatfile_open) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 16 * 1024); + + std::string line1("A purely peer-to-peer version of electronic cash would allow online " + "payments to be sent directly from one party to another without going " + "through a financial institution."); + std::string line2("Digital signatures provide part of the solution, but the main benefits are " + "lost if a trusted third party is still required to prevent double-spending."); + + size_t pos1 = 0; + size_t pos2 = pos1 + GetSerializeSize(line1, CLIENT_VERSION); + + // Write first line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos1)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line1, 256); + } + + // Attempt to append to file opened in read-only mode. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2), true), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file << LIMITED_STRING(line2, 256), std::ios_base::failure); + } + + // Append second line to file. + { + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + file << LIMITED_STRING(line2, 256); + } + + // Read text from file in read-only mode. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos1), true), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line1); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Read text from file with position offset. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(0, pos2)), SER_DISK, CLIENT_VERSION); + + file >> LIMITED_STRING(text, 256); + BOOST_CHECK_EQUAL(text, line2); + } + + // Ensure another file in the sequence has no data. + { + std::string text; + CAutoFile file(seq.Open(FlatFilePos(1, pos2)), SER_DISK, CLIENT_VERSION); + BOOST_CHECK_THROW(file >> LIMITED_STRING(text, 256), std::ios_base::failure); + } +} + +BOOST_AUTO_TEST_CASE(flatfile_allocate) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 0), 1, out_of_space), 100); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 0))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 1, out_of_space), 0); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 100); + BOOST_CHECK(!out_of_space); + + BOOST_CHECK_EQUAL(seq.Allocate(FlatFilePos(0, 99), 2, out_of_space), 101); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 99))), 200); + BOOST_CHECK(!out_of_space); +} + +BOOST_AUTO_TEST_CASE(flatfile_flush) +{ + auto data_dir = SetDataDir("flatfile_test"); + FlatFileSeq seq(data_dir, "a", 100); + + bool out_of_space; + seq.Allocate(FlatFilePos(0, 0), 1, out_of_space); + + // Flush without finalize should not truncate file. + seq.Flush(FlatFilePos(0, 1)); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 100); + + // Flush with finalize should truncate file. + seq.Flush(FlatFilePos(0, 1), true); + BOOST_CHECK_EQUAL(fs::file_size(seq.FileName(FlatFilePos(0, 1))), 1); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 1bc35d541a84..8d0eeb1b6044 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" +#include "util/system.h" #include "test/test_pivx.h" #include diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 7cf278d01af2..e33de3fe0f5b 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -8,7 +8,7 @@ #include "base58.h" #include "script/script.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "test_pivx.h" diff --git a/src/test/librust/wallet_zkeys_tests.cpp b/src/test/librust/wallet_zkeys_tests.cpp index 2093c9877551..cb06c2efbfa8 100644 --- a/src/test/librust/wallet_zkeys_tests.cpp +++ b/src/test/librust/wallet_zkeys_tests.cpp @@ -9,7 +9,7 @@ #include "sapling/address.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" -#include "util.h" +#include "util/system.h" #include /** diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 0ca5a76ae982..da62536d506f 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -6,7 +6,7 @@ #include "policy/feerate.h" #include "txmempool.h" -#include "util.h" +#include "util/system.h" #include diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index a0924ad7d143..317d3d3b1c29 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -11,7 +11,7 @@ #include "miner.h" #include "pubkey.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "validation.h" #include "wallet/wallet.h" diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 9e9e57655985..91f672d52d81 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -6,7 +6,7 @@ #include "policy/fees.h" #include "txmempool.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "test/test_pivx.h" diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 042c2316cfed..9a5cb364098f 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -8,7 +8,7 @@ #include "base58.h" #include "netbase.h" -#include "util.h" +#include "util/system.h" #include "test/test_pivx.h" diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 79ebc1aaad1a..458cc4439fa5 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,7 +11,7 @@ #include "serialize.h" #include "script/script.h" #include "script/interpreter.h" -#include "util.h" +#include "util/system.h" #include "validation.h" #include "version.h" diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 17ff327de683..e8385f1e2b0d 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -5,7 +5,7 @@ #include "test/test_pivx.h" -#include "util.h" +#include "util/system.h" #include "validation.h" #include diff --git a/src/test/test_pivx.cpp b/src/test/test_pivx.cpp index 732fce7474d6..a120ac67ea08 100644 --- a/src/test/test_pivx.cpp +++ b/src/test/test_pivx.cpp @@ -39,29 +39,38 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) } BasicTestingSetup::BasicTestingSetup(const std::string& chainName) + : m_path_root(fs::temp_directory_path() / "test_pivx" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30)))) { - ECC_Start(); - SetupEnvironment(); - InitSignatureCache(); - fCheckBlockIndex = true; - SelectParams(chainName); - evoDb.reset(new CEvoDB(1 << 20, true, true)); - deterministicMNManager.reset(new CDeterministicMNManager(*evoDb)); + ECC_Start(); + SetupEnvironment(); + InitSignatureCache(); + fCheckBlockIndex = true; + SelectParams(chainName); + evoDb.reset(new CEvoDB(1 << 20, true, true)); + deterministicMNManager.reset(new CDeterministicMNManager(*evoDb)); } + BasicTestingSetup::~BasicTestingSetup() { - ECC_Stop(); - g_connman.reset(); - deterministicMNManager.reset(); - evoDb.reset(); + fs::remove_all(m_path_root); + ECC_Stop(); + g_connman.reset(); + deterministicMNManager.reset(); + evoDb.reset(); +} + +fs::path BasicTestingSetup::SetDataDir(const std::string& name) +{ + fs::path ret = m_path_root / name; + fs::create_directories(ret); + gArgs.ForceSetArg("-datadir", ret.string()); + return ret; } TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) { + SetDataDir("tempdir"); ClearDatadirCache(); - pathTemp = fs::temp_directory_path() / strprintf("test_pivx_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); - fs::create_directories(pathTemp); - gArgs.ForceSetArg("-datadir", pathTemp.string()); // Start the lightweight task scheduler thread CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler); @@ -110,7 +119,6 @@ TestingSetup::~TestingSetup() delete pblocktree; delete zerocoinDB; delete pSporkDB; - fs::remove_all(pathTemp); } // Test chain only available on regtest diff --git a/src/test/test_pivx.h b/src/test/test_pivx.h index 67ed4d039377..75c85e60629a 100644 --- a/src/test/test_pivx.h +++ b/src/test/test_pivx.h @@ -38,6 +38,11 @@ struct BasicTestingSetup { BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN); ~BasicTestingSetup(); + + fs::path SetDataDir(const std::string& name); + +private: + const fs::path m_path_root; }; /** Testing setup that configures a complete environment. @@ -47,7 +52,6 @@ struct BasicTestingSetup { class CConnman; struct TestingSetup: public BasicTestingSetup { CCoinsViewDB *pcoinsdbview; - fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; CScheduler scheduler; diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index c5774015c720..a66a1ffa7285 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "util.h" +#include "util/system.h" #include "clientversion.h" #include "primitives/transaction.h" diff --git a/src/timedata.cpp b/src/timedata.cpp index 4963fbdeaac6..e29cfcad0c96 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -9,7 +9,7 @@ #include "guiinterface.h" #include "netaddress.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "warnings.h" diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index c0439091852c..38bbe9b38df8 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -10,7 +10,7 @@ #include "utilstrencodings.h" #include "netbase.h" #include "net.h" -#include "util.h" +#include "util/system.h" #include "crypto/hmac_sha256.h" #include diff --git a/src/txdb.cpp b/src/txdb.cpp index 4862fcbf9412..42c45ffcc3dd 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -9,7 +9,7 @@ #include "random.h" #include "pow.h" #include "uint256.h" -#include "util.h" +#include "util/system.h" #include "zpiv/zerocoin.h" #include diff --git a/src/txdb.h b/src/txdb.h index ed04c4b97b83..48ce71047976 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -32,7 +32,7 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024; //! min. -dbcache in (MiB) static const int64_t nMinDbCache = 4; -struct CDiskTxPos : public CDiskBlockPos +struct CDiskTxPos : public FlatFilePos { unsigned int nTxOffset; // after header @@ -41,11 +41,11 @@ struct CDiskTxPos : public CDiskBlockPos template inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITEAS(CDiskBlockPos, *this); + READWRITEAS(FlatFilePos, *this); READWRITE(VARINT(nTxOffset)); } - CDiskTxPos(const CDiskBlockPos& blockIn, unsigned int nTxOffsetIn) : CDiskBlockPos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) + CDiskTxPos(const FlatFilePos& blockIn, unsigned int nTxOffsetIn) : FlatFilePos(blockIn.nFile, blockIn.nPos), nTxOffset(nTxOffsetIn) { } @@ -56,7 +56,7 @@ struct CDiskTxPos : public CDiskBlockPos void SetNull() { - CDiskBlockPos::SetNull(); + FlatFilePos::SetNull(); nTxOffset = 0; } }; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 42c8ff5bb93f..e279bb679c61 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -14,7 +14,7 @@ #include "reverse_iterate.h" #include "streams.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "utiltime.h" #include "version.h" diff --git a/src/util.cpp b/src/util/system.cpp similarity index 99% rename from src/util.cpp rename to src/util/system.cpp index a4bcb85ea9f8..bc7085985c45 100644 --- a/src/util.cpp +++ b/src/util/system.cpp @@ -9,7 +9,7 @@ #include "config/pivx-config.h" #endif -#include "util.h" +#include "util/system.h" #include "chainparamsbase.h" #include "random.h" @@ -95,6 +95,14 @@ ArgsManager gArgs; bool fDaemon = false; CTranslationInterface translationInterface; +bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes) +{ + constexpr uint64_t min_disk_space = 52428800; // 50 MiB + + uint64_t free_bytes_available = fs::space(dir).available; + return free_bytes_available >= min_disk_space + additional_bytes; +} + /** * Interpret a string argument as a boolean. * diff --git a/src/util.h b/src/util/system.h similarity index 98% rename from src/util.h rename to src/util/system.h index ee5bfe9ba1db..8837ee8784bf 100644 --- a/src/util.h +++ b/src/util/system.h @@ -9,8 +9,8 @@ * Server/client environment: argument handling, config file parsing, * thread wrappers */ -#ifndef BITCOIN_UTIL_H -#define BITCOIN_UTIL_H +#ifndef BITCOIN_UTIL_SYSTEM_H +#define BITCOIN_UTIL_SYSTEM_H #if defined(HAVE_CONFIG_H) #include "config/pivx-config.h" @@ -86,6 +86,7 @@ bool FileCommit(FILE* file); bool TruncateFile(FILE* file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length); +bool CheckDiskSpace(const fs::path& dir, uint64_t additional_bytes = 0); bool RenameOver(fs::path src, fs::path dest); bool TryCreateDirectories(const fs::path& p); fs::path GetDefaultDataDir(); @@ -292,4 +293,4 @@ fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific = true); */ int ScheduleBatchPriority(void); -#endif // BITCOIN_UTIL_H +#endif // BITCOIN_UTIL_SYSTEM_H diff --git a/src/validation.cpp b/src/validation.cpp index db625a30b883..f7409d10b46c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -24,6 +24,7 @@ #include "consensus/zerocoin_verify.h" #include "evo/deterministicmns.h" #include "evo/specialtx.h" +#include "flatfile.h" #include "fs.h" #include "guiinterface.h" #include "init.h" @@ -34,13 +35,9 @@ #include "masternode-payments.h" #include "masternode-sync.h" #include "masternodeman.h" -#include "messagesigner.h" -#include "netmessagemaker.h" -#include "net_processing.h" #include "policy/policy.h" #include "pow.h" #include "reverse_iterate.h" -#include "sapling/sapling_validation.h" #include "script/sigcache.h" #include "spork.h" #include "sporkdb.h" @@ -48,7 +45,7 @@ #include "txdb.h" #include "txmempool.h" #include "undo.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "validationinterface.h" #include "warnings.h" @@ -224,6 +221,8 @@ enum FlushStateMode { // See definition for documentation bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode); +static FlatFileSeq BlockFileSeq(); +static FlatFileSeq UndoFileSeq(); bool CheckFinalTx(const CTransactionRef& tx, int flags) { @@ -780,7 +779,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& txOut, uint256& hashBl // CBlock and CBlockIndex // -bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos) +bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos) { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -801,7 +800,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos) return true; } -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) { block.SetNull(); @@ -828,7 +827,7 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos) bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex) { - CDiskBlockPos blockPos = WITH_LOCK(cs_main, return pindex->GetBlockPos(); ); + FlatFilePos blockPos = WITH_LOCK(cs_main, return pindex->GetBlockPos(); ); if (!ReadBlockFromDisk(block, blockPos)) { return false; } @@ -1219,7 +1218,7 @@ static bool AbortNode(CValidationState& state, const std::string& strMessage, co namespace { -bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock) +bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock) { // Open history file to append CAutoFile fileout(OpenUndoFile(pos), SER_DISK, CLIENT_VERSION); @@ -1246,7 +1245,7 @@ bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint return true; } -bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uint256& hashBlock) +bool UndoReadFromDisk(CBlockUndo& blockundo, const FlatFilePos& pos, const uint256& hashBlock) { // Open history file to read CAutoFile filein(OpenUndoFile(pos, true), SER_DISK, CLIENT_VERSION); @@ -1333,7 +1332,7 @@ DisconnectResult DisconnectBlock(CBlock& block, const CBlockIndex* pindex, CCoin bool fClean = true; CBlockUndo blockUndo; - CDiskBlockPos pos = pindex->GetUndoPos(); + FlatFilePos pos = pindex->GetUndoPos(); if (pos.IsNull()) { error("%s: no undo data available", __func__); return DISCONNECT_FAILED; @@ -1430,31 +1429,18 @@ void static FlushBlockFile(bool fFinalize = false) { LOCK(cs_LastBlockFile); - CDiskBlockPos posOld(nLastBlockFile, 0); - bool status = true; - - FILE* fileOld = OpenBlockFile(posOld); - if (fileOld) { - if (fFinalize) - status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nSize); - status &= FileCommit(fileOld); - fclose(fileOld); - } - - fileOld = OpenUndoFile(posOld); - if (fileOld) { - if (fFinalize) - status &= TruncateFile(fileOld, vinfoBlockFile[nLastBlockFile].nUndoSize); - status &= FileCommit(fileOld); - fclose(fileOld); - } + FlatFilePos block_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nSize); + FlatFilePos undo_pos_old(nLastBlockFile, vinfoBlockFile[nLastBlockFile].nUndoSize); + bool status = true; + status &= BlockFileSeq().Flush(block_pos_old, fFinalize); + status &= UndoFileSeq().Flush(undo_pos_old, fFinalize); if (!status) { AbortNode("Flushing block file to disk failed. This is likely the result of an I/O error."); } } -bool FindUndoPos(CValidationState& state, int nFile, CDiskBlockPos& pos, unsigned int nAddSize); +bool FindUndoPos(CValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize); static CCheckQueue scriptcheckqueue(128); @@ -1760,7 +1746,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd // Write undo information to disk if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) { - CDiskBlockPos diskPosBlock; + FlatFilePos diskPosBlock; if (!FindUndoPos(state, pindex->nFile, diskPosBlock, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 40)) return error("ConnectBlock() : FindUndoPos failed"); if (!UndoWriteToDisk(blockundo, diskPosBlock, pindex->pprev->GetBlockHash())) @@ -1853,8 +1839,9 @@ bool static FlushStateToDisk(CValidationState& state, FlushStateMode mode) // Write blocks and block index to disk. if (fDoFullFlush || fPeriodicWrite) { // Depend on nMinDiskSpace to ensure we can write block index - if (!CheckDiskSpace(0, true)) - return state.Error("out of disk space"); + if (!CheckDiskSpace(GetBlocksDir())) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } // First make sure all block and undo data is flushed to disk. FlushBlockFile(); // Then update all block file information (which may refer to block and undo files). @@ -1885,8 +1872,9 @@ bool static FlushStateToDisk(CValidationState& state, FlushStateMode mode) // twice (once in the log, and once in the tables). This is already // an overestimation, as most will delete an existing entry or // overwrite one. Still, use a conservative safety factor of 2. - if (!CheckDiskSpace(48 * 2 * 2 * pcoinsTip->GetCacheSize())) - return state.Error("out of disk space"); + if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * pcoinsTip->GetCacheSize())) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); + } // Flush the chainstate (which may refer to block index entries). if (!pcoinsTip->Flush()) return AbortNode(state, "Failed to write to coin database"); @@ -2555,7 +2543,7 @@ CBlockIndex* AddToBlockIndex(const CBlock& block) } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -bool ReceivedBlockTransactions(const CBlock& block, CValidationState& state, CBlockIndex* pindexNew, const CDiskBlockPos& pos) +bool ReceivedBlockTransactions(const CBlock& block, CValidationState& state, CBlockIndex* pindexNew, const FlatFilePos& pos) { if (block.IsProofOfStake()) pindexNew->SetProofOfStake(); @@ -2621,7 +2609,7 @@ bool ReceivedBlockTransactions(const CBlock& block, CValidationState& state, CBl return true; } -bool FindBlockPos(CValidationState& state, CDiskBlockPos& pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +bool FindBlockPos(CValidationState& state, FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -2656,49 +2644,34 @@ bool FindBlockPos(CValidationState& state, CDiskBlockPos& pos, unsigned int nAdd vinfoBlockFile[nFile].nSize += nAddSize; if (!fKnown) { - unsigned int nOldChunks = (pos.nPos + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; - unsigned int nNewChunks = (vinfoBlockFile[nFile].nSize + BLOCKFILE_CHUNK_SIZE - 1) / BLOCKFILE_CHUNK_SIZE; - if (nNewChunks > nOldChunks) { - if (CheckDiskSpace(nNewChunks * BLOCKFILE_CHUNK_SIZE - pos.nPos, true)) { - FILE* file = OpenBlockFile(pos); - if (file) { - LogPrintf("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); - } - } else - return state.Error("out of disk space"); + bool out_of_space; + BlockFileSeq().Allocate(pos, nAddSize, out_of_space); + if (out_of_space) { + return AbortNode("Disk space is low!", _("Error: Disk space is low!")); } + // future: add prunning flag check } setDirtyFileInfo.insert(nFile); return true; } -bool FindUndoPos(CValidationState& state, int nFile, CDiskBlockPos& pos, unsigned int nAddSize) +bool FindUndoPos(CValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize) { pos.nFile = nFile; LOCK(cs_LastBlockFile); - unsigned int nNewSize; pos.nPos = vinfoBlockFile[nFile].nUndoSize; - nNewSize = vinfoBlockFile[nFile].nUndoSize += nAddSize; + vinfoBlockFile[nFile].nUndoSize += nAddSize; setDirtyFileInfo.insert(nFile); - 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) { - if (CheckDiskSpace(nNewChunks * UNDOFILE_CHUNK_SIZE - pos.nPos, true)) { - FILE* file = OpenUndoFile(pos); - if (file) { - LogPrintf("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); - } - } else - return state.Error("out of disk space"); + bool out_of_space; + UndoFileSeq().Allocate(pos, nAddSize, out_of_space); + if (out_of_space) { + return AbortNode(state, "Disk space is low!", _("Error: Disk space is low!")); } + // future: add prunning flag check return true; } @@ -3149,7 +3122,7 @@ bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex return true; } -bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp) +bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppindex, FlatFilePos* dbp) { AssertLockHeld(cs_main); @@ -3378,7 +3351,7 @@ bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppi // Write block to history file try { unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; + FlatFilePos blockPos; if (dbp != NULL) blockPos = *dbp; if (!FindBlockPos(state, blockPos, nBlockSize + 8, nHeight, block.GetBlockTime(), dbp != NULL)) @@ -3395,7 +3368,7 @@ bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** ppi return true; } -bool ProcessNewBlock(CValidationState& state, CNode* pfrom, const std::shared_ptr pblock, CDiskBlockPos* dbp, bool* fAccepted) +bool ProcessNewBlock(CValidationState& state, CNode* pfrom, const std::shared_ptr pblock, FlatFilePos* dbp, bool* fAccepted) { AssertLockNotHeld(cs_main); @@ -3469,53 +3442,29 @@ bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex return true; } -bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir) +static FlatFileSeq BlockFileSeq() { - uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available; - - // Check for nMinDiskSpace bytes (currently 50MB) - if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) - return AbortNode("Disk space is low!", _("Error: Disk space is low!")); - - return true; + return FlatFileSeq(GetBlocksDir(), "blk", BLOCKFILE_CHUNK_SIZE); } -FILE* OpenDiskFile(const CDiskBlockPos& pos, const char* prefix, bool fReadOnly) +static FlatFileSeq UndoFileSeq() { - if (pos.IsNull()) - return NULL; - fs::path path = GetBlockPosFilename(pos, prefix); - fs::create_directories(path.parent_path()); - FILE* file = fsbridge::fopen(path, "rb+"); - if (!file && !fReadOnly) - file = fsbridge::fopen(path, "wb+"); - if (!file) { - LogPrintf("Unable to open file %s\n", path.string()); - return NULL; - } - if (pos.nPos) { - if (fseek(file, pos.nPos, SEEK_SET)) { - LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); - fclose(file); - return NULL; - } - } - return file; + return FlatFileSeq(GetBlocksDir(), "rev", UNDOFILE_CHUNK_SIZE); } -FILE* OpenBlockFile(const CDiskBlockPos& pos, bool fReadOnly) +FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) { - return OpenDiskFile(pos, "blk", fReadOnly); + return BlockFileSeq().Open(pos, fReadOnly); } -FILE* OpenUndoFile(const CDiskBlockPos& pos, bool fReadOnly) +FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly) { - return OpenDiskFile(pos, "rev", fReadOnly); + return UndoFileSeq().Open(pos, fReadOnly); } -fs::path GetBlockPosFilename(const CDiskBlockPos& pos, const char* prefix) +fs::path GetBlockPosFilename(const FlatFilePos &pos) { - return GetBlocksDir() / strprintf("%s%05u.dat", prefix, pos.nFile); + return BlockFileSeq().FileName(pos); } CBlockIndex* InsertBlockIndex(uint256 hash) @@ -3619,7 +3568,7 @@ bool static LoadBlockIndexDB(std::string& strError) } } for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) { - CDiskBlockPos pos(*it, 0); + FlatFilePos pos(*it, 0); if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) { return false; } @@ -3728,7 +3677,7 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth // check level 2: verify undo validity if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; - CDiskBlockPos pos = pindex->GetUndoPos(); + FlatFilePos pos = pindex->GetUndoPos(); if (!pos.IsNull()) { if (!UndoReadFromDisk(undo, pos, pindex->pprev->GetBlockHash())) return error("%s: *** found bad undo data at %d, hash=%s\n", __func__, pindex->nHeight, pindex->GetBlockHash().ToString()); @@ -3932,7 +3881,7 @@ bool LoadGenesisBlock() CBlock& block = const_cast(Params().GenesisBlock()); // Start new block file unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; + FlatFilePos blockPos; CValidationState state; if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, block.GetBlockTime())) return error("%s: FindBlockPos failed", __func__); @@ -3949,10 +3898,10 @@ bool LoadGenesisBlock() } -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp) +bool LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp) { // Map of disk positions for blocks with unknown parent (only used for reindex) - static std::multimap mapBlocksUnknownParent; + static std::multimap mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); int nLoaded = 0; @@ -4022,9 +3971,9 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp) while (!queue.empty()) { uint256 head = queue.front(); queue.pop_front(); - std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); + std::pair::iterator, std::multimap::iterator> range = mapBlocksUnknownParent.equal_range(head); while (range.first != range.second) { - std::multimap::iterator it = range.first; + std::multimap::iterator it = range.first; if (ReadBlockFromDisk(block, it->second)) { LogPrintf("%s: Processing out of order child %s of %s\n", __func__, block.GetHash().ToString(), head.ToString()); diff --git a/src/validation.h b/src/validation.h index 46243099ac4a..2f475d8176b5 100644 --- a/src/validation.h +++ b/src/validation.h @@ -159,9 +159,6 @@ extern CMoneySupply MoneySupply; /** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex* pindexBestHeader; -/** Minimum disk space required - used in CheckDiskSpace() */ -static const uint64_t nMinDiskSpace = 52428800; - /** * Process an incoming block. This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the @@ -174,17 +171,16 @@ static const uint64_t nMinDiskSpace = 52428800; * @param[out] fAccepted Whether the block is accepted or not * @return True if state.IsValid() */ -bool ProcessNewBlock(CValidationState& state, CNode* pfrom, const std::shared_ptr pblock, CDiskBlockPos* dbp, bool* fAccepted = nullptr); -/** Check whether enough disk space is available for an incoming block */ -bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false); +bool ProcessNewBlock(CValidationState& state, CNode* pfrom, const std::shared_ptr pblock, FlatFilePos* dbp, bool* fAccepted = nullptr); + /** Open a block file (blk?????.dat) */ -FILE* OpenBlockFile(const CDiskBlockPos& pos, bool fReadOnly = false); +FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false); /** Open an undo file (rev?????.dat) */ -FILE* OpenUndoFile(const CDiskBlockPos& pos, bool fReadOnly = false); +FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false); /** Translation to a filesystem path */ -fs::path GetBlockPosFilename(const CDiskBlockPos& pos, const char* prefix); +fs::path GetBlockPosFilename(const FlatFilePos &pos); /** Import blocks from an external file */ -bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp = NULL); +bool LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = NULL); /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ bool LoadGenesisBlock(); /** Load the block tree and coins database from disk, @@ -325,8 +321,8 @@ class CScriptCheck /** Functions for disk access for blocks */ -bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos); -bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); +bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos); +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); @@ -344,7 +340,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true, bool fCheckBlockSig = true); /** Store block on disk. If dbp is provided, the file is known to already reside on disk */ -bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL); +bool AcceptBlock(const CBlock& block, CValidationState& state, CBlockIndex** pindex, FlatFilePos* dbp = NULL); bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex** ppindex = nullptr, CBlockIndex* pindexPrev = nullptr); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 94b85583c139..7ea9dfbab1e8 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -10,7 +10,7 @@ #include "guiinterfaceutil.h" #include "hash.h" #include "protocol.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include diff --git a/src/wallet/hdchain.cpp b/src/wallet/hdchain.cpp index 29e37b4fb69e..642fb8217e9a 100644 --- a/src/wallet/hdchain.cpp +++ b/src/wallet/hdchain.cpp @@ -7,7 +7,7 @@ #include "base58.h" #include "chainparams.h" #include "tinyformat.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" bool CHDChain::SetNull() diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index d2af3d405655..f476efde8d24 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -12,7 +12,7 @@ #include "script/script.h" #include "script/standard.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "utilstrencodings.h" #include "utiltime.h" #include "wallet/wallet.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index e75e86d20939..43ccaf5ff13f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -18,7 +18,7 @@ #include "policy/feerate.h" #include "rpc/server.h" #include "timedata.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "wallet.h" #include "walletdb.h" diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 659407c10b65..32397d0d106c 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -412,6 +412,8 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) SetMockTime(KEY_TIME); coinbaseTxns.emplace_back(*CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]); + std::string backup_file = (SetDataDir("importwallet_rescan") / "wallet.backup").string(); + // Import key into wallet and call dumpwallet to create backup file. { CWallet wallet; @@ -423,7 +425,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back((pathTemp / "wallet.backup").string()); + request.params.push_back(backup_file); ::pwalletMain = &wallet; ::dumpwallet(request); } @@ -435,7 +437,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); - request.params.push_back((pathTemp / "wallet.backup").string()); + request.params.push_back(backup_file); ::pwalletMain = &wallet; ::importwallet(request); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ef529162553b..c00b6f23fa8e 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -18,7 +18,7 @@ #include "script/sign.h" #include "scheduler.h" #include "spork.h" -#include "util.h" +#include "util/system.h" #include "utilmoneystr.h" #include "zpivchain.h" diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 27c225ad9ea0..ae19ef76ac38 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -24,7 +24,7 @@ #include "primitives/transaction.h" #include "sapling/address.h" #include "guiinterface.h" -#include "util.h" +#include "util/system.h" #include "util/memory.h" #include "utilstrencodings.h" #include "validationinterface.h" diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index dda03280b919..0e7b50007caf 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -15,7 +15,7 @@ #include "sapling/key_io_sapling.h" #include "serialize.h" #include "sync.h" -#include "util.h" +#include "util/system.h" #include "utiltime.h" #include "wallet/wallet.h" diff --git a/src/warnings.cpp b/src/warnings.cpp index 9be652d5c53c..a7b607a48e44 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -7,7 +7,7 @@ #include "sync.h" #include "clientversion.h" -#include "util.h" +#include "util/system.h" RecursiveMutex cs_warnings; std::string strMiscWarning; diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 53dac44aebc8..d39d0be0fd7d 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "zmqabstractnotifier.h" -#include "util.h" +#include "util/system.h" CZMQAbstractNotifier::~CZMQAbstractNotifier() diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 110e2df44ba4..18dfe917bbe9 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -7,7 +7,7 @@ #include "version.h" #include "streams.h" -#include "util.h" +#include "util/system.h" void zmqError(const char *str) { diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index ee08858fe18e..67998ee27f96 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -5,7 +5,7 @@ #include "zmqpublishnotifier.h" #include "chainparams.h" -#include "util.h" +#include "util/system.h" #include "crypto/common.h" #include "validation.h" // cs_main diff --git a/src/zpiv/mintpool.cpp b/src/zpiv/mintpool.cpp index 775f056919dc..16c8f39b6051 100644 --- a/src/zpiv/mintpool.cpp +++ b/src/zpiv/mintpool.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "mintpool.h" -#include "util.h" +#include "util/system.h" CMintPool::CMintPool()