1#include <xrpl/basics/contract.h> 
    2#include <xrpl/beast/core/LexicalCast.h> 
    3#include <xrpl/beast/utility/instrumentation.h> 
    4#include <xrpl/nodestore/Factory.h> 
    5#include <xrpl/nodestore/Manager.h> 
    6#include <xrpl/nodestore/detail/DecodedBlob.h> 
    7#include <xrpl/nodestore/detail/EncodedBlob.h> 
    8#include <xrpl/nodestore/detail/codec.h> 
   10#include <boost/filesystem.hpp> 
   12#include <nudb/nudb.hpp> 
   56            Throw<std::runtime_error>(
 
   57                "nodestore: Missing path in NuDB backend");
 
 
   65        nudb::context& context,
 
   77            Throw<std::runtime_error>(
 
   78                "nodestore: Missing path in NuDB backend");
 
 
   88        catch (nudb::system_error 
const&)
 
 
  108    open(
bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt)
 
  111        using namespace boost::filesystem;
 
  116                "ripple::NodeStore::NuDBBackend::open : database is already " 
  118            JLOG(
j_.
error()) << 
"database is already open";
 
  122        auto const folder = path(
name_);
 
  123        auto const dp = (folder / 
"nudb.dat").
string();
 
  124        auto const kp = (folder / 
"nudb.key").
string();
 
  125        auto const lp = (folder / 
"nudb.log").
string();
 
  129            create_directories(folder);
 
  130            nudb::create<nudb::xxhasher>(
 
  141            if (ec == nudb::errc::file_exists)
 
  144                Throw<nudb::system_error>(ec);
 
  146        db_.open(dp, kp, lp, ec);
 
  148            Throw<nudb::system_error>(ec);
 
  151            Throw<std::runtime_error>(
"nodestore: unknown appnum");
 
 
  158        return db_.is_open();
 
 
  162    open(
bool createIfMissing)
 override 
  164        open(createIfMissing, 
appnum, nudb::make_uid(), nudb::make_salt());
 
 
  177                JLOG(
j_.
fatal()) << 
"NuBD close() failed: " << ec.message();
 
  178                Throw<nudb::system_error>(ec);
 
  183                boost::filesystem::remove_all(
name_, ec);
 
  186                    JLOG(
j_.
fatal()) << 
"Filesystem remove_all of " << 
name_ 
  187                                     << 
" failed with: " << ec.message();
 
 
  201            [key, pno, &status](
void const* data, 
std::size_t size) {
 
  202                nudb::detail::buffer bf;
 
  204                DecodedBlob decoded(key, result.first, result.second);
 
  205                if (!decoded.
wasOk())
 
  214        if (ec == nudb::error::key_not_found)
 
  217            Throw<nudb::system_error>(ec);
 
 
  226        for (
auto const& h : hashes)
 
  236        return {results, 
ok};
 
 
  244        nudb::detail::buffer bf;
 
  246        db_.insert(e.
getKey(), result.first, result.second, ec);
 
  247        if (ec && ec != nudb::error::key_exists)
 
  248            Throw<nudb::system_error>(ec);
 
 
  258        report.
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
 
 
  269        for (
auto const& e : 
batch)
 
  271        report.
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
 
 
  284        auto const dp = 
db_.dat_path();
 
  285        auto const kp = 
db_.key_path();
 
  286        auto const lp = 
db_.log_path();
 
  291            Throw<nudb::system_error>(ec);
 
  299                nudb::detail::buffer bf;
 
  301                DecodedBlob decoded(key, result.first, result.second);
 
  302                if (!decoded.
wasOk())
 
  312            Throw<nudb::system_error>(ec);
 
  313        db_.open(dp, kp, lp, ec);
 
  315            Throw<nudb::system_error>(ec);
 
 
  333        auto const dp = 
db_.dat_path();
 
  334        auto const kp = 
db_.key_path();
 
  335        auto const lp = 
db_.log_path();
 
  339            Throw<nudb::system_error>(ec);
 
  340        nudb::verify_info vi;
 
  341        nudb::verify<nudb::xxhasher>(vi, dp, kp, 0, nudb::no_progress{}, ec);
 
  343            Throw<nudb::system_error>(ec);
 
  344        db_.open(dp, kp, lp, ec);
 
  346            Throw<nudb::system_error>(ec);
 
 
  362        using namespace boost::filesystem;
 
  363        auto const folder = path(name);
 
  364        auto const kp = (folder / 
"nudb.key").
string();
 
  367            nudb::block_size(kp);  
 
  371        if (!
get_if_exists(keyValues, 
"nudb_block_size", blockSizeStr))
 
  379                beast::lexicalCastThrow<std::size_t>(blockSizeStr);
 
  382            if (parsedBlockSize < 4096 || parsedBlockSize > 32768 ||
 
  383                (parsedBlockSize & (parsedBlockSize - 1)) != 0)
 
  386                s << 
"Invalid nudb_block_size: " << parsedBlockSize
 
  387                  << 
". Must be power of 2 between 4096 and 32768.";
 
  388                Throw<std::runtime_error>(s.
str());
 
  392                << 
"Using custom NuDB block size: " << parsedBlockSize
 
  394            return parsedBlockSize;
 
  399            s << 
"Invalid nudb_block_size value: " << blockSizeStr
 
  400              << 
". Error: " << e.
what();
 
  401            Throw<std::runtime_error>(s.
str());
 
 
 
  434            keyBytes, keyValues, 
burstSize, scheduler, journal);
 
 
  443        nudb::context& context,
 
  447            keyBytes, keyValues, 
burstSize, scheduler, context, journal);
 
 
 
A generic endpoint for log messages.
 
A backend used for the NodeStore.
 
Parsed key/value blob into NodeObject components.
 
std::shared_ptr< NodeObject > createObject()
Create a NodeObject from this data.
 
bool wasOk() const noexcept
Determine if the decoding was successful.
 
Convert a NodeObject from in-memory to database format.
 
void const * getKey() const noexcept
 
std::size_t getSize() const noexcept
 
void const * getData() const noexcept
 
Base class for backend factories.
 
Singleton for managing NodeStore factories and back ends.
 
virtual void insert(Factory &factory)=0
Add a factory.
 
void store(std::shared_ptr< NodeObject > const &no) override
Store a single object.
 
NuDBBackend(size_t keyBytes, Section const &keyValues, std::size_t burstSize, Scheduler &scheduler, beast::Journal journal)
 
Status fetch(void const *key, std::shared_ptr< NodeObject > *pno) override
Fetch a single object.
 
void open(bool createIfMissing) override
Open the backend.
 
std::size_t const burstSize_
 
std::pair< std::vector< std::shared_ptr< NodeObject > >, Status > fetchBatch(std::vector< uint256 const * > const &hashes) override
Fetch a batch synchronously.
 
static std::size_t parseBlockSize(std::string const &name, Section const &keyValues, beast::Journal journal)
 
static constexpr std::uint64_t appnum
 
void close() override
Close the backend.
 
NuDBBackend(size_t keyBytes, Section const &keyValues, std::size_t burstSize, Scheduler &scheduler, nudb::context &context, beast::Journal journal)
 
void storeBatch(Batch const &batch) override
Store a group of objects.
 
void do_insert(std::shared_ptr< NodeObject > const &no)
 
std::optional< std::size_t > getBlockSize() const override
Get the block size for backends that support it.
 
int fdRequired() const override
Returns the number of file descriptors the backend expects to need.
 
std::string getName() override
Get the human-readable name of this backend.
 
void open(bool createIfMissing, uint64_t appType, uint64_t uid, uint64_t salt) override
Open the backend.
 
void verify() override
Perform consistency checks on database.
 
void for_each(std::function< void(std::shared_ptr< NodeObject >)> f) override
Visit every object in the database This is usually called during import.
 
std::atomic< bool > deletePath_
 
std::size_t const blockSize_
 
bool isOpen() override
Returns true is the database is open.
 
int getWriteLoad() override
Estimate the number of write operations pending.
 
void setDeletePath() override
Remove contents on disk upon destruction.
 
std::unique_ptr< Backend > createInstance(size_t keyBytes, Section const &keyValues, std::size_t burstSize, Scheduler &scheduler, nudb::context &context, beast::Journal journal) override
Create an instance of this factory's backend.
 
NuDBFactory(Manager &manager)
 
std::string getName() const override
Retrieve the name of this factory.
 
std::unique_ptr< Backend > createInstance(size_t keyBytes, Section const &keyValues, std::size_t burstSize, Scheduler &scheduler, beast::Journal journal) override
Create an instance of this factory's backend.
 
Scheduling for asynchronous backend activity.
 
virtual void onBatchWrite(BatchWriteReport const &report)=0
Reports the completion of a batch write Allows the scheduler to monitor the node store's performance.
 
Holds a collection of configuration values.
 
void registerNuDBFactory(Manager &manager)
 
std::pair< void const *, std::size_t > nodeobject_decompress(void const *in, std::size_t in_size, BufferFactory &&bf)
 
std::pair< void const *, std::size_t > nodeobject_compress(void const *in, std::size_t in_size, BufferFactory &&bf)
 
Status
Return codes from Backend operations.
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
bool get_if_exists(Section const §ion, std::string const &name, T &v)
 
std::error_code make_error_code(ripple::TokenCodecErrc e)
 
@ open
We haven't closed our ledger yet, but others might have.
 
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
 
Contains information about a batch write operation.
 
std::chrono::milliseconds elapsed