diff --git a/src/ripple/nodestore/impl/DatabaseShardImp.cpp b/src/ripple/nodestore/impl/DatabaseShardImp.cpp index 8bb57b97873..b44e1acd7ca 100644 --- a/src/ripple/nodestore/impl/DatabaseShardImp.cpp +++ b/src/ripple/nodestore/impl/DatabaseShardImp.cpp @@ -65,89 +65,34 @@ DatabaseShardImp::~DatabaseShardImp() bool DatabaseShardImp::init() { - using namespace boost::filesystem; - using namespace boost::beast::detail; - auto fail = [j = j_](std::string const& msg) - { - JLOG(j.error()) << - "[" << ConfigSection::shardDatabase() << "] " << msg; - return false; - }; - { std::lock_guard lock(mutex_); - if (init_) - return fail("already initialized"); - - Config const& config {app_.config()}; - Section const& section {config.section(ConfigSection::shardDatabase())}; - - { - // Node and shard stores must use same earliest ledger sequence - std::uint32_t seq; - if (get_if_exists( - config.section(ConfigSection::nodeDatabase()), - "earliest_seq", - seq)) - { - std::uint32_t seq2; - if (get_if_exists( - section, - "earliest_seq", seq2) && - seq != seq2) - { - return fail("and [" + ConfigSection::nodeDatabase() + - "] both define 'earliest_seq'"); - } - } - } - - if (!get_if_exists(section, "path", dir_)) - return fail("'path' missing"); - - if (exists(dir_)) { - if (!is_directory(dir_)) - return fail("'path' must be a directory"); - } - else - create_directories(dir_); - - { - std::uint64_t sz; - if (!get_if_exists(section, "max_size_gb", sz)) - return fail("'max_size_gb' missing"); - - if ((sz << 30) < sz) - return fail("'max_size_gb' overflow"); - - // Minimum storage space required (in gigabytes) - if (sz < 10) - return fail("'max_size_gb' must be at least 10"); - - // Convert to bytes - maxFileSz_ = sz << 30; + JLOG(j_.error()) << "already initialized"; + return false; } - if (section.exists("ledgers_per_shard")) + if (!initConfig(lock)) { - // To be set only in standalone for testing - if (!config.standalone()) - return fail("'ledgers_per_shard' only honored in stand alone"); - - ledgersPerShard_ = get(section, "ledgers_per_shard"); - if (ledgersPerShard_ == 0 || ledgersPerShard_ % 256 != 0) - return fail("'ledgers_per_shard' must be a multiple of 256"); + JLOG(j_.error()) << "invalid configuration file settings"; + return false; } - // NuDB is the default and only supported permanent storage backend - backendName_ = get(section, "type", "nudb"); - if (!boost::iequals(backendName_, "NuDB")) - return fail("'type' value unsupported"); - try { + using namespace boost::filesystem; + if (exists(dir_)) + { + if (!is_directory(dir_)) + { + JLOG(j_.error()) << "'path' must be a directory"; + return false; + } + } + else + create_directories(dir_); + ctx_ = std::make_unique(); ctx_->start(); @@ -172,9 +117,11 @@ DatabaseShardImp::init() auto const shardIndex {std::stoul(dirName)}; if (shardIndex < earliestShardIndex()) { - return fail("shard " + std::to_string(shardIndex) + - " comes before earliest shard index " + - std::to_string(earliestShardIndex())); + JLOG(j_.error()) << + "shard " << shardIndex << + " comes before earliest shard index " << + earliestShardIndex(); + return false; } auto const shardDir {dir_ / std::to_string(shardIndex)}; @@ -223,7 +170,11 @@ DatabaseShardImp::init() else { if (acquireIndex_ != 0) - return fail("more than one shard being acquired"); + { + JLOG(j_.error()) << + "more than one shard being acquired"; + return false; + } shards_.emplace( shardIndex, @@ -234,8 +185,8 @@ DatabaseShardImp::init() } catch (std::exception const& e) { - return fail(std::string("exception ") + - e.what() + " in function " + __func__); + JLOG(j_.error()) << + "exception " << e.what() << " in function " << __func__; } updateStatus(lock); @@ -1068,6 +1019,85 @@ DatabaseShardImp::sweep() } } +bool +DatabaseShardImp::initConfig(std::lock_guard&) +{ + auto fail = [j = j_](std::string const& msg) + { + JLOG(j.error()) << + "[" << ConfigSection::shardDatabase() << "] " << msg; + return false; + }; + + Config const& config {app_.config()}; + Section const& section {config.section(ConfigSection::shardDatabase())}; + + { + // The earliest ledger sequence defaults to XRP_LEDGER_EARLIEST_SEQ. + // A custom earliest ledger sequence can be set through the + // configuration file using the 'earliest_seq' field under the + // 'node_db' and 'shard_db' stanzas. If specified, this field must + // have a value greater than zero and be equally assigned in + // both stanzas. + + std::uint32_t shardDBEarliestSeq {0}; + get_if_exists( + section, + "earliest_seq", + shardDBEarliestSeq); + + std::uint32_t nodeDBEarliestSeq {0}; + get_if_exists( + config.section(ConfigSection::nodeDatabase()), + "earliest_seq", + nodeDBEarliestSeq); + + if (shardDBEarliestSeq != nodeDBEarliestSeq) + { + return fail("and [" + ConfigSection::nodeDatabase() + + "] define different 'earliest_seq' values"); + } + } + + using namespace boost::filesystem; + if (!get_if_exists(section, "path", dir_)) + return fail("'path' missing"); + + { + std::uint64_t sz; + if (!get_if_exists(section, "max_size_gb", sz)) + return fail("'max_size_gb' missing"); + + if ((sz << 30) < sz) + return fail("'max_size_gb' overflow"); + + // Minimum storage space required (in gigabytes) + if (sz < 10) + return fail("'max_size_gb' must be at least 10"); + + // Convert to bytes + maxFileSz_ = sz << 30; + } + + if (section.exists("ledgers_per_shard")) + { + // To be set only in standalone for testing + if (!config.standalone()) + return fail("'ledgers_per_shard' only honored in stand alone"); + + ledgersPerShard_ = get(section, "ledgers_per_shard"); + if (ledgersPerShard_ == 0 || ledgersPerShard_ % 256 != 0) + return fail("'ledgers_per_shard' must be a multiple of 256"); + } + + // NuDB is the default and only supported permanent storage backend + backendName_ = get(section, "type", "nudb"); + if (!boost::iequals(backendName_, "NuDB")) + return fail("'type' value unsupported"); + + return true; +} + std::shared_ptr DatabaseShardImp::fetchFrom(uint256 const& hash, std::uint32_t seq) { @@ -1249,10 +1279,6 @@ DatabaseShardImp::setFileStats() std::lock_guard lock(mutex_); assert(init_); - fileSz_ = 0; - fdRequired_ = 0; - avgShardFileSz_ = 0; - if (shards_.empty()) return; diff --git a/src/ripple/nodestore/impl/DatabaseShardImp.h b/src/ripple/nodestore/impl/DatabaseShardImp.h index 34b0d52c23e..21a117bdab1 100644 --- a/src/ripple/nodestore/impl/DatabaseShardImp.h +++ b/src/ripple/nodestore/impl/DatabaseShardImp.h @@ -240,6 +240,11 @@ class DatabaseShardImp : public DatabaseShard // File name used to mark shards being imported from node store static constexpr auto importMarker_ = "import"; + // Initialize settings from the configuration file + // Lock must be held + bool + initConfig(std::lock_guard&); + std::shared_ptr fetchFrom(uint256 const& hash, std::uint32_t seq) override; diff --git a/src/ripple/unity/nodestore.cpp b/src/ripple/unity/nodestore.cpp deleted file mode 100644 index 5ea62a3675f..00000000000 --- a/src/ripple/unity/nodestore.cpp +++ /dev/null @@ -1,37 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include