1#include <test/nodestore/TestBase.h> 
    2#include <test/unit_test/SuiteJournal.h> 
    4#include <xrpl/basics/BasicConfig.h> 
    5#include <xrpl/basics/ByteUtilities.h> 
    6#include <xrpl/basics/safe_cast.h> 
    7#include <xrpl/beast/unit_test.h> 
    8#include <xrpl/beast/unit_test/thread.h> 
    9#include <xrpl/beast/utility/temp_dir.h> 
   10#include <xrpl/beast/xor_shift_engine.h> 
   11#include <xrpl/nodestore/DummyScheduler.h> 
   12#include <xrpl/nodestore/Manager.h> 
   14#include <boost/algorithm/string.hpp> 
   26#ifndef NODESTORE_TIMING_DO_VERIFY 
   27#define NODESTORE_TIMING_DO_VERIFY 0 
   40        config, 
megabytes(4), scheduler, journal);
 
 
   44template <
class Generator>
 
   48    using result_type = 
typename Generator::result_type;
 
   49    while (bytes >= 
sizeof(result_type))
 
   52        memcpy(buffer, &v, 
sizeof(v));
 
   53        buffer = 
reinterpret_cast<std::uint8_t*
>(buffer) + 
sizeof(v);
 
   60        memcpy(buffer, &v, bytes);
 
 
  152        for (
auto iter = config.
begin(); iter != config.
end(); ++iter)
 
  153            s += (iter != config.
begin() ? 
"," : 
"") + iter->first + 
"=" +
 
 
  171        boost::split(v, s, boost::algorithm::is_any_of(
","));
 
 
  180    template <
class Body>
 
  193        template <
class... Args>
 
 
  214    template <
class Body, 
class... Args>
 
  224        for (
std::size_t id = 0; 
id < number_of_threads; ++id)
 
 
  230    template <
class Body, 
class... Args>
 
  240        for (
std::size_t id = 0; 
id < number_of_threads; ++id)
 
 
  256        auto backend = 
make_Backend(config, scheduler, journal);
 
  257        BEAST_EXPECT(backend != 
nullptr);
 
  268            explicit Body(suite& s, 
Backend& backend)
 
  269                : suite_(s), backend_(backend), seq_(1)
 
  282                    suite_.fail(e.
what());
 
  297#if NODESTORE_TIMING_DO_VERIFY 
 
  313        auto backend = 
make_Backend(config, scheduler, journal);
 
  314        BEAST_EXPECT(backend != 
nullptr);
 
  336                , dist_(0, params.
items - 1)
 
  347                    obj = seq1_.
obj(dist_(gen_));
 
  348                    backend_.
fetch(obj->getHash().data(), &result);
 
  349                    suite_.expect(result && 
isSame(result, obj));
 
  353                    suite_.fail(e.
what());
 
  359            parallel_for_id<Body>(
 
  368#if NODESTORE_TIMING_DO_VERIFY 
 
  384        auto backend = 
make_Backend(config, scheduler, journal);
 
  385        BEAST_EXPECT(backend != 
nullptr);
 
  409                , dist_(0, params.
items - 1)
 
  418                    auto const key = seq2_.
key(i);
 
  420                    backend_.
fetch(key.data(), &result);
 
  421                    suite_.expect(!result);
 
  425                    suite_.fail(e.
what());
 
  432            parallel_for_id<Body>(
 
  441#if NODESTORE_TIMING_DO_VERIFY 
 
  457        auto backend = 
make_Backend(config, scheduler, journal);
 
  458        BEAST_EXPECT(backend != 
nullptr);
 
  486                , dist_(0, params.
items - 1)
 
  495                    if (rand_(gen_) < missingNodePercent)
 
  497                        auto const key = seq2_.
key(dist_(gen_));
 
  499                        backend_.
fetch(key.data(), &result);
 
  500                        suite_.expect(!result);
 
  506                        obj = seq1_.
obj(dist_(gen_));
 
  507                        backend_.
fetch(obj->getHash().data(), &result);
 
  508                        suite_.expect(result && 
isSame(result, obj));
 
  513                    suite_.fail(e.
what());
 
  520            parallel_for_id<Body>(
 
  529#if NODESTORE_TIMING_DO_VERIFY 
 
  546        auto backend = 
make_Backend(config, scheduler, journal);
 
  547        BEAST_EXPECT(backend != 
nullptr);
 
  548        backend->setDeletePath();
 
  576                , older_(0, params.
items - 1)
 
  585                    if (rand_(gen_) < 200)
 
  590                        auto const j = older_(gen_);
 
  593                        backend_.
fetch(obj->getHash().data(), &result);
 
  594                        suite_.expect(result != 
nullptr);
 
  595                        suite_.expect(
isSame(result, obj));
 
  599                    p[0] = rand_(gen_) < 50 ? 0 : 1;
 
  601                    for (
int q = 0; q < 2; ++q)
 
  609                                auto const j = recent_(gen_);
 
  611                                backend_.
fetch(obj->getHash().data(), &result);
 
  612                                suite_.expect(!result || 
isSame(result, obj));
 
  618                                auto const j = i + params_.
items;
 
  627                    suite_.fail(e.
what());
 
  634            parallel_for_id<Body>(
 
  643#if NODESTORE_TIMING_DO_VERIFY 
 
  665        (this->*f)(config, params, journal);
 
  666        return std::chrono::duration_cast<duration_type>(
 
 
  678        for (
auto const& test : tests)
 
  679            if (w < test.first.size())
 
  680                w = test.first.size();
 
  681        log << threads << 
" Thread" << (threads > 1 ? 
"s" : 
"") << 
", " 
  686            for (
auto const& test : tests)
 
  687                ss << 
" " << setw(w) << test.first;
 
  694        for (
auto const& config_string : config_strings)
 
  703                config.
set(
"path", tempDir.
path());
 
  707                for (
auto const& test : tests)
 
  710                              do_test(test.second, config, params, journal));
 
 
  730#if XRPL_ROCKSDB_AVAILABLE 
  731            ";type=rocksdb,open_files=2000,filter_bits=12,cache_mb=256," 
  732            "file_size_mb=8,file_size_mult=2" 
  735            ";type=memory|path=NodeStore" 
  748        boost::split(config_strings, args, boost::algorithm::is_any_of(
";"));
 
  749        for (
auto iter = config_strings.
begin(); iter != config_strings.
end();)
 
  751                iter = config_strings.
erase(iter);
 
 
 
  762BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Timing, nodestore, 
ripple, 1);
 
A generic endpoint for log messages.
 
void seed(result_type seed)
 
RAII temporary directory.
 
std::string path() const
Get the native path for the temporary directory.
 
log_os< char > log
Logging output stream.
 
testcase_t testcase
Memberspace for declaring test cases.
 
std::string const & arg() const
Return the argument associated with the runner.
 
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
 
A backend used for the NodeStore.
 
virtual Status fetch(void const *key, std::shared_ptr< NodeObject > *pObject)=0
Fetch a single object.
 
virtual void store(std::shared_ptr< NodeObject > const &object)=0
Store a single object.
 
Simple NodeStore Scheduler that just peforms the tasks synchronously.
 
virtual std::unique_ptr< Backend > make_Backend(Section const ¶meters, std::size_t burstSize, Scheduler &scheduler, beast::Journal journal)=0
Create a backend.
 
static Manager & instance()
Returns the instance of the manager singleton.
 
Scheduling for asynchronous backend activity.
 
std::discrete_distribution< std::uint32_t > d_type_
 
Sequence(std::uint8_t prefix)
 
std::shared_ptr< NodeObject > obj(std::size_t n)
 
void batch(std::size_t n, Batch &b, std::size_t size)
 
uint256 key(std::size_t n)
 
beast::xor_shift_engine gen_
 
std::uniform_int_distribution< std::uint32_t > d_size_
 
parallel_for_lambda(std::size_t n, std::atomic< std::size_t > &c)
 
void operator()(Args &&... args)
 
std::atomic< std::size_t > & c_
 
void run() override
Runs the suite.
 
void do_fetch(Section const &config, Params const ¶ms, beast::Journal journal)
 
static std::string to_string(duration_type const &d)
 
void(Timing_test::*)(Section const  &, Params const  &, beast::Journal) test_func
 
void do_work(Section const &config, Params const ¶ms, beast::Journal journal)
 
static std::string to_string(Section const &config)
 
static Section parse(std::string s)
 
void do_tests(std::size_t threads, test_list const &tests, std::vector< std::string > const &config_strings)
 
duration_type do_test(test_func f, Section const &config, Params const ¶ms, beast::Journal journal)
 
void parallel_for(std::size_t const n, std::size_t number_of_threads, Args const &... args)
 
void do_mixed(Section const &config, Params const ¶ms, beast::Journal journal)
 
std::size_t const default_repeat
 
std::size_t const default_items
 
void do_missing(Section const &config, Params const ¶ms, beast::Journal journal)
 
void do_insert(Section const &config, Params const ¶ms, beast::Journal journal)
 
void parallel_for_id(std::size_t const n, std::size_t number_of_threads, Args const &... args)
 
Holds a collection of configuration values.
 
void set(std::string const &key, std::string const &value)
Set a key/value pair.
 
const_iterator begin() const
 
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
 
const_iterator end() const
 
static constexpr std::size_t size()
 
T emplace_back(T... args)
 
A namespace for easy access to logging severity values.
 
std::unique_ptr< Backend > make_Backend(Section const &config, Scheduler &scheduler, beast::Journal journal)
 
static void rngcpy(void *buffer, std::size_t bytes, Generator &g)
 
bool isSame(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs)
Returns true if objects are identical.
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
constexpr auto megabytes(T value) noexcept
 
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
 
void Rethrow()
Rethrow the exception currently being handled.
 
T setprecision(T... args)