Merge #15118: Refactor block file logic

04cca33094 Style cleanup. (Jim Posen)
4c01e4e159 flatfile: Unit tests for FlatFileSeq methods. (Jim Posen)
65a489e93d scripted-diff: Rename CBlockDiskPos to FlatFilePos. (Jim Posen)
d6d8a78f26 Move CDiskBlockPos from chain to flatfile. (Jim Posen)
e0380933e3 validation: Refactor file flush logic into FlatFileSeq. (Jim Posen)
992404b31e validation: Refactor block file pre-allocation into FlatFileSeq. (Jim Posen)
e2d2abb99f validation: Refactor OpenDiskFile into method on FlatFileSeq. (Jim Posen)
9183d6ef65 validation: Extract basic block file logic into FlatFileSeq class. (Jim Posen)
62e7addb63 util: Move CheckDiskSpace to util. (Jim Posen)

Pull request description:

  This cleans up and refactors block file helpers so that they may be used by the block filter indexer. Per [design discussion](https://github.com/bitcoin/bitcoin/pull/14121#issuecomment-451252591) about storing BIP 157 block filters, it has been suggested that they are stored in the same way as block and undo data. This refactor is sufficient to simplify file operations for this use case, though in the future perhaps more pruning-related logic ought to be moved into the new classes.

  The basic abstraction is a `FlatFileSeq` which manages access to a sequence of numbered files into which raw data is written.

Tree-SHA512: b2108756777f2dad8964a1a2ef2764486e708a4a4a8cfac47b5de8bcb0625388964438eb096b10cfd9ea39212c299b5cb32fa943e768db2333cf49ea7def157e
This commit is contained in:
Wladimir J. van der Laan
2019-03-02 23:03:21 +01:00
12 changed files with 417 additions and 181 deletions

123
src/test/flatfile_tests.cpp Normal file
View File

@@ -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_bitcoin.h>
#include <boost/test/unit_test.hpp>
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()