1#include <test/nodestore/TestBase.h>
2#include <test/unit_test/SuiteJournal.h>
4#include <xrpl/basics/Blob.h>
5#include <xrpl/basics/ByteUtilities.h>
6#include <xrpl/basics/base_uint.h>
7#include <xrpl/basics/contract.h>
8#include <xrpl/basics/safe_cast.h>
9#include <xrpl/beast/unit_test/suite.h>
10#include <xrpl/beast/unit_test/thread.h>
11#include <xrpl/beast/utility/Journal.h>
12#include <xrpl/beast/utility/temp_dir.h>
13#include <xrpl/beast/xor_shift_engine.h>
14#include <xrpl/config/BasicConfig.h>
15#include <xrpl/config/Constants.h>
16#include <xrpl/nodestore/Backend.h>
17#include <xrpl/nodestore/DummyScheduler.h>
18#include <xrpl/nodestore/Manager.h>
19#include <xrpl/nodestore/NodeObject.h>
20#include <xrpl/nodestore/Scheduler.h>
21#include <xrpl/nodestore/Types.h>
23#include <boost/algorithm/string/classification.hpp>
24#include <boost/algorithm/string/split.hpp>
43#ifndef NODESTORE_TIMING_DO_VERIFY
44#define NODESTORE_TIMING_DO_VERIFY 0
49std::unique_ptr<Backend>
56template <
class Generator>
60 using result_type = Generator::result_type;
61 while (bytes >=
sizeof(result_type))
64 memcpy(buffer, &v,
sizeof(v));
65 buffer =
reinterpret_cast<std::uint8_t*
>(buffer) +
sizeof(v);
72 memcpy(buffer, &v, bytes);
132 while ((size--) != 0u)
164 for (
auto iter = config.
begin(); iter != config.
end(); ++iter)
165 s += (iter != config.
begin() ?
"," :
"") + iter->first +
"=" + iter->second;
182 boost::split(v, s, boost::algorithm::is_any_of(
","));
191 template <
class Body>
203 template <
class... Args>
224 template <
class Body,
class... Args>
231 for (
std::size_t id = 0;
id < numberOfThreads; ++id)
237 template <
class Body,
class... Args>
244 for (
std::size_t id = 0;
id < numberOfThreads; ++id)
257 auto backend =
makeBackend(config, scheduler, journal);
258 BEAST_EXPECT(backend !=
nullptr);
269 explicit Body(
Suite& s,
Backend& backend) : suite_(s), backend_(backend), seq_(1)
282 suite_.fail(e.
what());
293#if NODESTORE_TIMING_DO_VERIFY
306 auto backend =
makeBackend(config, scheduler, journal);
307 BEAST_EXPECT(backend !=
nullptr);
321 : suite_(s), backend_(backend), seq1_(1), gen_(
id + 1), dist_(0, params.
items - 1)
332 obj = seq1_.
obj(dist_(gen_));
333 backend_.
fetch(obj->getHash(), &result);
334 suite_.expect(result &&
isSame(result, obj));
338 suite_.fail(e.
what());
353#if NODESTORE_TIMING_DO_VERIFY
366 auto backend =
makeBackend(config, scheduler, journal);
367 BEAST_EXPECT(backend !=
nullptr);
387 , dist_(0, params.
items - 1)
396 auto const hash = seq2_.
key(i);
398 backend_.
fetch(hash, &result);
399 suite_.expect(!result);
403 suite_.fail(e.
what());
419#if NODESTORE_TIMING_DO_VERIFY
432 auto backend =
makeBackend(config, scheduler, journal);
433 BEAST_EXPECT(backend !=
nullptr);
457 , dist_(0, params.
items - 1)
468 auto const hash = seq2_.
key(dist_(gen_));
470 backend_.
fetch(hash, &result);
471 suite_.expect(!result);
477 obj = seq1_.
obj(dist_(gen_));
478 backend_.
fetch(obj->getHash(), &result);
479 suite_.expect(result &&
isSame(result, obj));
484 suite_.fail(e.
what());
500#if NODESTORE_TIMING_DO_VERIFY
517 auto backend =
makeBackend(config, scheduler, journal);
518 BEAST_EXPECT(backend !=
nullptr);
519 backend->setDeletePath();
542 , recent_(params.
items, (params.
items * 2) - 1)
543 , older_(0, params.
items - 1)
552 if (rand_(gen_) < 200)
557 auto const j = older_(gen_);
559 backend_.
fetch(obj->getHash(), &result);
560 suite_.expect(result !=
nullptr);
561 suite_.expect(
isSame(result, obj));
565 p[0] = rand_(gen_) < 50 ? 0 : 1;
567 for (
int q = 0; q < 2; ++q)
576 auto const j = recent_(gen_);
578 backend_.
fetch(obj->getHash(), &result);
579 suite_.expect(!result ||
isSame(result, obj));
585 auto const j = i + params_.
items;
594 suite_.fail(e.
what());
610#if NODESTORE_TIMING_DO_VERIFY
627 (this->*f)(config, params, journal);
643 log << threads <<
" Thread" << (threads > 1 ?
"s" :
"") <<
", " <<
defaultItems
649 ss <<
" " << setw(w) <<
test.first;
656 for (
auto const& configString : configStrings)
692#if XRPL_ROCKSDB_AVAILABLE
693 ";type=rocksdb,open_files=2000,filter_bits=12,cache_mb=256,"
694 "file_size_mb=8,file_size_mult=2"
697 ";type=memory|path=NodeStore"
710 boost::split(configStrings, args, boost::algorithm::is_any_of(
";"));
711 for (
auto iter = configStrings.
begin(); iter != configStrings.
end();)
715 iter = configStrings.
erase(iter);
A generic endpoint for log messages.
RAII temporary directory.
std::string path() const
Get the native path for the temporary directory.
void operator()(Runner &r)
Invokes the test using the specified runner.
LogOs< char > log
Logging output stream.
TestcaseT testcase
Memberspace for declaring test cases.
std::string const & arg() const
Return the argument associated with the runner.
static constexpr std::size_t size()
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 void store(std::shared_ptr< NodeObject > const &object)=0
Store a single object.
virtual Status fetch(uint256 const &hash, std::shared_ptr< NodeObject > *pObject)=0
Fetch a single object.
Simple NodeStore Scheduler that just performs the tasks synchronously.
virtual std::unique_ptr< Backend > makeBackend(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.
beast::xor_shift_engine gen_
static constexpr auto kMaxLedger
Sequence(std::uint8_t prefix)
static constexpr auto kMinLedger
std::uniform_int_distribution< std::uint32_t > dSize_
static constexpr auto kMaxSize
std::discrete_distribution< std::uint32_t > dType_
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)
static constexpr auto kMinSize
std::atomic< std::size_t > & c_
ParallelForLambda(std::size_t n, std::atomic< std::size_t > &c)
void operator()(Args &&... args)
void doMixed(Section const &config, Params const ¶ms, beast::Journal journal)
void(Timing_test::*)(Section const &, Params const &, beast::Journal) test_func
void doInsert(Section const &config, Params const ¶ms, beast::Journal journal)
std::chrono::steady_clock clock_type
static std::string toString(duration_type const &d)
void doFetch(Section const &config, Params const ¶ms, beast::Journal journal)
void doWork(Section const &config, Params const ¶ms, beast::Journal journal)
void doMissing(Section const &config, Params const ¶ms, beast::Journal journal)
std::chrono::milliseconds duration_type
std::vector< std::pair< std::string, test_func > > test_list
void parallelFor(std::size_t const n, std::size_t numberOfThreads, Args const &... args)
static Section parse(std::string s)
std::size_t const defaultItems
static std::string toString(Section const &config)
duration_type doTest(test_func f, Section const &config, Params const ¶ms, beast::Journal journal)
void doTests(std::size_t threads, test_list const &tests, std::vector< std::string > const &configStrings)
void parallelForId(std::size_t const n, std::size_t numberOfThreads, Args const &... args)
std::size_t const defaultRepeat
void run() override
Runs the suite.
static constexpr auto kMissingNodePercent
Holds a collection of configuration values.
const_iterator end() const
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.
T duration_cast(T... args)
T emplace_back(T... args)
detail::XorShiftEngine<> xor_shift_engine
XOR-shift Generator.
Severity
Severity level / threshold of a Journal message.
bool isSame(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs)
Returns true if objects are identical.
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Timing, nodestore, xrpl, 1)
static void rngcpy(void *buffer, std::size_t bytes, Generator &g)
std::unique_ptr< Backend > makeBackend(Section const &config, Scheduler &scheduler, beast::Journal journal)
std::vector< std::shared_ptr< NodeObject > > Batch
A batch of NodeObjects to write at once.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
XRPL_NO_SANITIZE_ADDRESS void rethrow()
Rethrow the exception currently being handled.
constexpr auto megabytes(T value) noexcept
std::vector< unsigned char > Blob
Storage for linear binary data.
T setprecision(T... args)
static constexpr auto kType
static constexpr auto kPath