rippled
DatabaseShard_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2020 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/ledger/LedgerMaster.h>
21 #include <ripple/app/ledger/LedgerToJson.h>
22 #include <ripple/beast/hash/hash_append.h>
23 #include <ripple/beast/utility/temp_dir.h>
24 #include <ripple/core/ConfigSections.h>
25 #include <ripple/nodestore/DatabaseShard.h>
26 #include <ripple/nodestore/DummyScheduler.h>
27 #include <ripple/nodestore/Manager.h>
28 #include <ripple/nodestore/impl/DecodedBlob.h>
29 #include <ripple/nodestore/impl/EncodedBlob.h>
30 #include <ripple/nodestore/impl/Shard.h>
31 #include <ripple/protocol/digest.h>
32 #include <boost/algorithm/hex.hpp>
33 #include <chrono>
34 #include <fstream>
35 #include <iostream>
36 #include <openssl/ripemd.h>
37 #include <test/jtx.h>
38 #include <test/nodestore/TestBase.h>
39 
40 namespace ripple {
41 namespace NodeStore {
42 
53 template <class IntType = int>
55 {
56  using resultType = IntType;
57 
58  const resultType A, B;
59 
60  struct paramType
61  {
62  const resultType A, B;
63 
64  paramType(resultType aa, resultType bb) : A(aa), B(bb)
65  {
66  }
67  };
68 
70  const resultType a = 0,
72  : A(a), B(b)
73  {
74  }
75 
76  explicit uniformIntDistribution(const paramType& params)
77  : A(params.A), B(params.B)
78  {
79  }
80 
81  template <class Generator>
84  {
85  return rnd(g, A, B);
86  }
87 
88  template <class Generator>
90  operator()(Generator& g, const paramType& params) const
91  {
92  return rnd(g, params.A, params.B);
93  }
94 
96  a() const
97  {
98  return A;
99  }
100 
101  resultType
102  b() const
103  {
104  return B;
105  }
106 
107  resultType
108  min() const
109  {
110  return A;
111  }
112 
113  resultType
114  max() const
115  {
116  return B;
117  }
118 
119 private:
120  template <class Generator>
121  resultType
122  rnd(Generator& g, const resultType a, const resultType b) const
123  {
124  static_assert(
126  value,
127  "Ups...");
128  static_assert(
129  Generator::min() == 0, "If non-zero we have handle the offset");
130  const resultType range = b - a + 1;
131  assert(Generator::max() >= range); // Just for safety
132  const resultType rejectLim = g.max() % range;
133  resultType n;
134  do
135  n = g();
136  while (n <= rejectLim);
137  return (n % range) + a;
138  }
139 };
140 
141 template <class Engine, class Integral>
142 Integral
143 randInt(Engine& engine, Integral min, Integral max)
144 {
145  assert(max > min);
146 
147  // This should have no state and constructing it should
148  // be very cheap. If that turns out not to be the case
149  // it could be hand-optimized.
150  return uniformIntDistribution<Integral>(min, max)(engine);
151 }
152 
153 template <class Engine, class Integral>
154 Integral
155 randInt(Engine& engine, Integral max)
156 {
157  return randInt(engine, Integral(0), max);
158 }
159 
160 // Tests DatabaseShard class
161 //
163 {
164  static constexpr std::uint32_t maxSizeGb = 10;
165  static constexpr std::uint32_t ledgersPerShard = 256;
166  static constexpr std::uint32_t earliestSeq = ledgersPerShard + 1;
167  static constexpr std::uint32_t dataSizeMax = 4;
168  static constexpr std::uint32_t iniAmount = 1000000;
169  static constexpr std::uint32_t nTestShards = 4;
174 
175  struct TestData
176  {
177  /* ring used to generate pseudo-random sequence */
179  /* number of shards to generate */
180  int nShards_;
181  /* vector of accounts used to send test transactions */
183  /* nAccounts_[i] is the number of these accounts existed before i-th
184  * ledger */
186  /* payAccounts_[i][j] = {from, to} is the pair which consists of two
187  * number of acoounts: source and destinations, which participate in
188  * j-th payment on i-th ledger */
190  /* xrpAmount_[i] is the amount for all payments on i-th ledger */
192  /* ledgers_[i] is the i-th ledger which contains the above described
193  * accounts and payments */
195 
197  std::uint64_t const seedValue,
198  int dataSize = dataSizeMax,
199  int nShards = 1)
200  : rng_(seedValue), nShards_(nShards)
201  {
202  std::uint32_t n = 0;
203  std::uint32_t nLedgers = ledgersPerShard * nShards;
204 
205  nAccounts_.reserve(nLedgers);
206  payAccounts_.reserve(nLedgers);
207  xrpAmount_.reserve(nLedgers);
208 
209  for (std::uint32_t i = 0; i < nLedgers; ++i)
210  {
211  int p;
212  if (n >= 2)
213  p = randInt(rng_, 2 * dataSize);
214  else
215  p = 0;
216 
218  pay.reserve(p);
219 
220  for (int j = 0; j < p; ++j)
221  {
222  int from, to;
223  do
224  {
225  from = randInt(rng_, n - 1);
226  to = randInt(rng_, n - 1);
227  } while (from == to);
228 
229  pay.push_back(std::make_pair(from, to));
230  }
231 
232  n += !randInt(rng_, nLedgers / dataSize);
233 
234  if (n > accounts_.size())
235  {
236  char str[9];
237  for (int j = 0; j < 8; ++j)
238  str[j] = 'a' + randInt(rng_, 'z' - 'a');
239  str[8] = 0;
240  accounts_.emplace_back(str);
241  }
242 
244  payAccounts_.push_back(std::move(pay));
245  xrpAmount_.push_back(randInt(rng_, 90) + 10);
246  }
247  }
248 
249  bool
250  isNewAccounts(int seq)
251  {
252  return nAccounts_[seq] > (seq ? nAccounts_[seq - 1] : 0);
253  }
254 
255  void
257  {
258  using namespace test::jtx;
259 
260  if (isNewAccounts(seq))
261  env_.fund(XRP(iniAmount), accounts_[nAccounts_[seq] - 1]);
262 
263  for (std::uint32_t i = 0; i < payAccounts_[seq].size(); ++i)
264  {
265  env_(
266  pay(accounts_[payAccounts_[seq][i].first],
267  accounts_[payAccounts_[seq][i].second],
268  XRP(xrpAmount_[seq])));
269  }
270  }
271 
272  bool
274  {
275  for (std::uint32_t i = 3; i <= ledgersPerShard; ++i)
276  {
277  if (!env_.close())
278  return false;
281  if (ledger->info().seq != i)
282  return false;
283  }
284 
285  for (std::uint32_t i = 0; i < ledgersPerShard * nShards_; ++i)
286  {
287  makeLedgerData(env_, i);
288  if (!env_.close())
289  return false;
292  if (ledger->info().seq != i + ledgersPerShard + 1)
293  return false;
294  ledgers_.push_back(ledger);
295  }
296 
297  return true;
298  }
299  };
300 
301  void
303  TestData& data,
305  std::uint32_t seq)
306  {
307  using namespace test::jtx;
308 
309  auto rootCount{0};
310  auto accCount{0};
311  auto sothCount{0};
312  for (auto const& sles : ledger->sles)
313  {
314  if (sles->getType() == ltACCOUNT_ROOT)
315  {
316  int sq = sles->getFieldU32(sfSequence);
317  int reqsq = -1;
318  const auto id = sles->getAccountID(sfAccount);
319 
320  for (int i = 0; i < data.accounts_.size(); ++i)
321  {
322  if (id == data.accounts_[i].id())
323  {
324  reqsq = ledgersPerShard + 1;
325  for (int j = 0; j <= seq; ++j)
326  if (data.nAccounts_[j] > i + 1 ||
327  (data.nAccounts_[j] == i + 1 &&
328  !data.isNewAccounts(j)))
329  {
330  for (int k = 0; k < data.payAccounts_[j].size();
331  ++k)
332  if (data.payAccounts_[j][k].first == i)
333  reqsq++;
334  }
335  else
336  reqsq++;
337  ++accCount;
338  break;
339  }
340  }
341  if (reqsq == -1)
342  {
343  reqsq = data.nAccounts_[seq] + 1;
344  ++rootCount;
345  }
346  BEAST_EXPECT(sq == reqsq);
347  }
348  else
349  ++sothCount;
350  }
351  BEAST_EXPECT(rootCount == 1);
352  BEAST_EXPECT(accCount == data.nAccounts_[seq]);
353  BEAST_EXPECT(sothCount == 3);
354 
355  auto iniCount{0};
356  auto setCount{0};
357  auto payCount{0};
358  auto tothCount{0};
359  for (auto const& tx : ledger->txs)
360  {
361  if (tx.first->getTxnType() == ttPAYMENT)
362  {
363  std::int64_t xrpAmount =
364  tx.first->getFieldAmount(sfAmount).xrp().decimalXRP();
365  if (xrpAmount == iniAmount)
366  ++iniCount;
367  else
368  {
369  ++payCount;
370  BEAST_EXPECT(xrpAmount == data.xrpAmount_[seq]);
371  }
372  }
373  else if (tx.first->getTxnType() == ttACCOUNT_SET)
374  ++setCount;
375  else
376  ++tothCount;
377  }
378  int newacc = data.isNewAccounts(seq) ? 1 : 0;
379  BEAST_EXPECT(iniCount == newacc);
380  BEAST_EXPECT(setCount == newacc);
381  BEAST_EXPECT(payCount == data.payAccounts_[seq].size());
382  BEAST_EXPECT(tothCount == !seq);
383  }
384 
385  bool
387  Database& db,
388  Ledger const& ledger,
389  std::shared_ptr<Ledger const> const& next = {})
390  {
391  // Store header
392  {
393  Serializer s(128);
394  s.add32(HashPrefix::ledgerMaster);
395  addRaw(ledger.info(), s);
396  db.store(
397  hotLEDGER,
398  std::move(s.modData()),
399  ledger.info().hash,
400  ledger.info().seq);
401  }
402 
403  // Store the state map
404  auto visitAcc = [&](SHAMapAbstractNode& node) {
405  Serializer s;
406  node.addRaw(s, snfPREFIX);
407  db.store(
408  node.getType() == SHAMapAbstractNode::TNType::tnINNER
409  ? hotUNKNOWN
410  : hotACCOUNT_NODE,
411  std::move(s.modData()),
412  node.getNodeHash().as_uint256(),
413  ledger.info().seq);
414  return true;
415  };
416 
417  if (ledger.stateMap().getHash().isNonZero())
418  {
419  if (!ledger.stateMap().isValid())
420  return false;
421  if (next && next->info().parentHash == ledger.info().hash)
422  {
423  auto have = next->stateMap().snapShot(false);
424  ledger.stateMap().snapShot(false)->visitDifferences(
425  &(*have), visitAcc);
426  }
427  else
428  ledger.stateMap().snapShot(false)->visitNodes(visitAcc);
429  }
430 
431  // Store the transaction map
432  auto visitTx = [&](SHAMapAbstractNode& node) {
433  Serializer s;
434  node.addRaw(s, snfPREFIX);
435  db.store(
436  node.getType() == SHAMapAbstractNode::TNType::tnINNER
437  ? hotUNKNOWN
439  std::move(s.modData()),
440  node.getNodeHash().as_uint256(),
441  ledger.info().seq);
442  return true;
443  };
444 
445  if (ledger.info().txHash.isNonZero())
446  {
447  if (!ledger.txMap().isValid())
448  return false;
449  ledger.txMap().snapShot(false)->visitNodes(visitTx);
450  }
451 
452  return true;
453  }
454 
455  void
456  checkLedger(TestData& data, DatabaseShard& db, Ledger const& ledger)
457  {
458  auto fetched = db.fetchLedger(ledger.info().hash, ledger.info().seq);
459  if (!BEAST_EXPECT(fetched))
460  return;
461 
462  testLedgerData(data, fetched, ledger.info().seq - ledgersPerShard - 1);
463 
464  // verify the metadata/header info by serializing to json
465  BEAST_EXPECT(
466  getJson(
468  getJson(
470 
471  BEAST_EXPECT(
472  getJson(
474  getJson(
476 
477  // walk shamap and validate each node
478  auto fcompAcc = [&](SHAMapAbstractNode& node) -> bool {
479  Serializer s;
480  node.addRaw(s, snfPREFIX);
481  auto nSrc{NodeObject::createObject(
482  node.getType() == SHAMapAbstractNode::TNType::tnINNER
483  ? hotUNKNOWN
484  : hotACCOUNT_NODE,
485  std::move(s.modData()),
486  node.getNodeHash().as_uint256())};
487  if (!BEAST_EXPECT(nSrc))
488  return false;
489 
490  auto nDst =
491  db.fetch(node.getNodeHash().as_uint256(), ledger.info().seq);
492  if (!BEAST_EXPECT(nDst))
493  return false;
494 
495  BEAST_EXPECT(isSame(nSrc, nDst));
496 
497  return true;
498  };
499  if (ledger.stateMap().getHash().isNonZero())
500  ledger.stateMap().snapShot(false)->visitNodes(fcompAcc);
501 
502  auto fcompTx = [&](SHAMapAbstractNode& node) -> bool {
503  Serializer s;
504  node.addRaw(s, snfPREFIX);
505  auto nSrc{NodeObject::createObject(
506  node.getType() == SHAMapAbstractNode::TNType::tnINNER
507  ? hotUNKNOWN
509  std::move(s.modData()),
510  node.getNodeHash().as_uint256())};
511  if (!BEAST_EXPECT(nSrc))
512  return false;
513 
514  auto nDst =
515  db.fetch(node.getNodeHash().as_uint256(), ledger.info().seq);
516  if (!BEAST_EXPECT(nDst))
517  return false;
518 
519  BEAST_EXPECT(isSame(nSrc, nDst));
520 
521  return true;
522  };
523  if (ledger.info().txHash.isNonZero())
524  ledger.txMap().snapShot(false)->visitNodes(fcompTx);
525  }
526 
529  {
531  if (!bitmask)
532  return set;
533  bool empty = true;
534 
535  for (std::uint32_t i = 0; i < 64 && bitmask; i++)
536  {
537  if (bitmask & (1ll << i))
538  {
539  if (!empty)
540  set += ",";
541  set += std::to_string(i);
542  empty = false;
543  }
544  }
545 
547  from_string(rs, set);
548  return to_string(rs);
549  }
550 
553  std::string const& testName,
554  std::string const& backendType,
555  std::string const& shardDir,
556  std::string const& nodeDir = std::string())
557  {
558  using namespace test::jtx;
559 
560  if (testName != "")
561  {
562  std::string caseName =
563  "DatabaseShard " + testName + " with backend " + backendType;
564  testcase(caseName);
565  }
566 
567  return envconfig([&](std::unique_ptr<Config> cfg) {
568  cfg->overwrite(ConfigSection::shardDatabase(), "type", backendType);
569  cfg->overwrite(ConfigSection::shardDatabase(), "path", shardDir);
570  cfg->overwrite(
572  "max_size_gb",
574  cfg->overwrite(
576  "ledgers_per_shard",
578  cfg->overwrite(
580  "earliest_seq",
582  cfg->overwrite(ConfigSection::nodeDatabase(), "type", backendType);
583  cfg->overwrite(
585  "max_size_gb",
587  cfg->overwrite(
589  "earliest_seq",
591  if (nodeDir.empty())
592  cfg->overwrite(
594  else
595  cfg->overwrite(ConfigSection::nodeDatabase(), "path", nodeDir);
596  return cfg;
597  });
598  }
599 
602  DatabaseShard& db,
603  int shardNumber,
605  {
607  auto start = std::chrono::system_clock::now();
608  auto end = start + timeout;
609  while (!from_string(rs, db.getCompleteShards()) ||
610  !boost::icl::contains(rs, shardNumber))
611  {
612  if (!BEAST_EXPECT(std::chrono::system_clock::now() < end))
613  return {};
615  }
616 
617  return shardNumber;
618  }
619 
621  createShard(TestData& data, DatabaseShard& db, int maxShardNumber = 1)
622  {
623  int shardNumber = -1;
624 
625  for (std::uint32_t i = 0; i < ledgersPerShard; ++i)
626  {
627  auto ind = db.prepareLedger((maxShardNumber + 1) * ledgersPerShard);
628  if (!BEAST_EXPECT(ind != boost::none))
629  return {};
630  shardNumber = db.seqToShardIndex(*ind);
631  int arrInd = *ind - ledgersPerShard - 1;
632  BEAST_EXPECT(
633  arrInd >= 0 && arrInd < maxShardNumber * ledgersPerShard);
634  BEAST_EXPECT(saveLedger(db, *data.ledgers_[arrInd]));
635  if (arrInd % ledgersPerShard == (ledgersPerShard - 1))
636  {
637  uint256 const finalKey_{0};
638  Serializer s;
640  s.add32(db.firstLedgerSeq(shardNumber));
641  s.add32(db.lastLedgerSeq(shardNumber));
642  s.addRaw(data.ledgers_[arrInd]->info().hash.data(), 256 / 8);
643  db.store(hotUNKNOWN, std::move(s.modData()), finalKey_, *ind);
644  }
645  db.setStored(data.ledgers_[arrInd]);
646  }
647 
648  return waitShard(db, shardNumber);
649  }
650 
651  void
652  testStandalone(std::string const& backendType)
653  {
654  using namespace test::jtx;
655 
656  beast::temp_dir shardDir;
657  Env env{*this, testConfig("standalone", backendType, shardDir.path())};
658  DummyScheduler scheduler;
659  RootStoppable parent("TestRootStoppable");
660 
662  make_ShardStore(env.app(), parent, scheduler, 2, journal_);
663 
664  BEAST_EXPECT(db);
665  BEAST_EXPECT(db->ledgersPerShard() == db->ledgersPerShardDefault);
666  BEAST_EXPECT(db->init());
667  BEAST_EXPECT(db->ledgersPerShard() == ledgersPerShard);
668  BEAST_EXPECT(db->seqToShardIndex(ledgersPerShard + 1) == 1);
669  BEAST_EXPECT(db->seqToShardIndex(2 * ledgersPerShard) == 1);
670  BEAST_EXPECT(db->seqToShardIndex(2 * ledgersPerShard + 1) == 2);
671  BEAST_EXPECT(
672  db->earliestShardIndex() == (earliestSeq - 1) / ledgersPerShard);
673  BEAST_EXPECT(db->firstLedgerSeq(1) == ledgersPerShard + 1);
674  BEAST_EXPECT(db->lastLedgerSeq(1) == 2 * ledgersPerShard);
675  BEAST_EXPECT(db->getRootDir().string() == shardDir.path());
676  }
677 
678  void
680  std::string const& backendType,
681  std::uint64_t const seedValue)
682  {
683  using namespace test::jtx;
684 
685  beast::temp_dir shardDir;
686  Env env{*this, testConfig("createShard", backendType, shardDir.path())};
687  DatabaseShard* db = env.app().getShardStore();
688  BEAST_EXPECT(db);
689 
690  TestData data(seedValue);
691  if (!BEAST_EXPECT(data.makeLedgers(env)))
692  return;
693 
694  if (!createShard(data, *db, 1))
695  return;
696 
697  for (std::uint32_t i = 0; i < ledgersPerShard; ++i)
698  checkLedger(data, *db, *data.ledgers_[i]);
699  }
700 
701  void
703  std::string const& backendType,
704  std::uint64_t const seedValue)
705  {
706  using namespace test::jtx;
707 
708  beast::temp_dir shardDir;
709  {
710  Env env{
711  *this,
712  testConfig("reopenDatabase", backendType, shardDir.path())};
713  DatabaseShard* db = env.app().getShardStore();
714  BEAST_EXPECT(db);
715 
716  TestData data(seedValue, 4, 2);
717  if (!BEAST_EXPECT(data.makeLedgers(env)))
718  return;
719 
720  for (std::uint32_t i = 0; i < 2; ++i)
721  if (!createShard(data, *db, 2))
722  return;
723  }
724  {
725  Env env{*this, testConfig("", backendType, shardDir.path())};
726  DatabaseShard* db = env.app().getShardStore();
727  BEAST_EXPECT(db);
728 
729  TestData data(seedValue, 4, 2);
730  if (!BEAST_EXPECT(data.makeLedgers(env)))
731  return;
732 
733  for (std::uint32_t i = 1; i <= 2; ++i)
734  waitShard(*db, i);
735 
736  for (std::uint32_t i = 0; i < 2 * ledgersPerShard; ++i)
737  checkLedger(data, *db, *data.ledgers_[i]);
738  }
739  }
740 
741  void
743  std::string const& backendType,
744  std::uint64_t const seedValue)
745  {
746  using namespace test::jtx;
747 
748  beast::temp_dir shardDir;
749  Env env{
750  *this,
751  testConfig("getCompleteShards", backendType, shardDir.path())};
752  DatabaseShard* db = env.app().getShardStore();
753  BEAST_EXPECT(db);
754 
755  TestData data(seedValue, 2, nTestShards);
756  if (!BEAST_EXPECT(data.makeLedgers(env)))
757  return;
758 
759  BEAST_EXPECT(db->getCompleteShards() == "");
760 
761  std::uint64_t bitMask = 0;
762 
763  for (std::uint32_t i = 0; i < nTestShards; ++i)
764  {
765  auto n = createShard(data, *db, nTestShards);
766  if (!BEAST_EXPECT(n && *n >= 1 && *n <= nTestShards))
767  return;
768  bitMask |= 1ll << *n;
769  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(bitMask));
770  }
771  }
772 
773  void
775  std::string const& backendType,
776  std::uint64_t const seedValue)
777  {
778  using namespace test::jtx;
779 
780  beast::temp_dir shardDir;
781  Env env{
782  *this, testConfig("prepareShard", backendType, shardDir.path())};
783  DatabaseShard* db = env.app().getShardStore();
784  BEAST_EXPECT(db);
785 
786  TestData data(seedValue, 1, nTestShards);
787  if (!BEAST_EXPECT(data.makeLedgers(env)))
788  return;
789 
790  std::uint64_t bitMask = 0;
791  BEAST_EXPECT(db->getPreShards() == "");
792 
793  for (std::uint32_t i = 0; i < nTestShards * 2; ++i)
794  {
795  std::uint32_t n = randInt(data.rng_, nTestShards - 1) + 1;
796  if (bitMask & (1ll << n))
797  {
798  db->removePreShard(n);
799  bitMask &= ~(1ll << n);
800  }
801  else
802  {
803  db->prepareShard(n);
804  bitMask |= 1ll << n;
805  }
806  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(bitMask));
807  }
808 
809  // test illegal cases
810  // adding shards with too large number
811  db->prepareShard(0);
812  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(bitMask));
813  db->prepareShard(nTestShards + 1);
814  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(bitMask));
815  db->prepareShard(nTestShards + 2);
816  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(bitMask));
817 
818  // create shards which are not prepared for import
819  BEAST_EXPECT(db->getCompleteShards() == "");
820 
821  std::uint64_t bitMask2 = 0;
822 
823  for (std::uint32_t i = 0; i < nTestShards; ++i)
824  {
825  auto n = createShard(data, *db, nTestShards);
826  if (!BEAST_EXPECT(n && *n >= 1 && *n <= nTestShards))
827  return;
828  bitMask2 |= 1ll << *n;
829  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(bitMask));
830  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(bitMask2));
831  BEAST_EXPECT((bitMask & bitMask2) == 0);
832  if ((bitMask | bitMask2) == ((1ll << nTestShards) - 1) << 1)
833  break;
834  }
835 
836  // try to create another shard
837  BEAST_EXPECT(
839  boost::none);
840  }
841 
842  void
844  std::string const& backendType,
845  std::uint64_t const seedValue)
846  {
847  using namespace test::jtx;
848 
849  beast::temp_dir importDir;
850  TestData data(seedValue, 2);
851 
852  {
853  Env env{
854  *this,
855  testConfig("importShard", backendType, importDir.path())};
856  DatabaseShard* db = env.app().getShardStore();
857  BEAST_EXPECT(db);
858 
859  if (!BEAST_EXPECT(data.makeLedgers(env)))
860  return;
861 
862  if (!createShard(data, *db, 1))
863  return;
864 
865  for (std::uint32_t i = 0; i < ledgersPerShard; ++i)
866  checkLedger(data, *db, *data.ledgers_[i]);
867 
868  data.ledgers_.clear();
869  }
870 
871  boost::filesystem::path importPath(importDir.path());
872  importPath /= "1";
873 
874  {
875  beast::temp_dir shardDir;
876  Env env{*this, testConfig("", backendType, shardDir.path())};
877  DatabaseShard* db = env.app().getShardStore();
878  BEAST_EXPECT(db);
879 
880  if (!BEAST_EXPECT(data.makeLedgers(env)))
881  return;
882 
883  db->prepareShard(1);
884  BEAST_EXPECT(db->getPreShards() == bitmask2Rangeset(2));
885  if (!BEAST_EXPECT(db->importShard(1, importPath)))
886  return;
887  BEAST_EXPECT(db->getPreShards() == "");
888 
889  auto n = waitShard(*db, 1);
890  if (!BEAST_EXPECT(n && *n == 1))
891  return;
892 
893  for (std::uint32_t i = 0; i < ledgersPerShard; ++i)
894  checkLedger(data, *db, *data.ledgers_[i]);
895  }
896  }
897 
898  void
900  std::string const& backendType,
901  std::uint64_t const seedValue)
902  {
903  using namespace test::jtx;
904 
905  beast::temp_dir shardDir;
906  {
907  TestData data(seedValue, 4, 2);
908  {
909  Env env{
910  *this,
911  testConfig(
912  "corruptedDatabase", backendType, shardDir.path())};
913  DatabaseShard* db = env.app().getShardStore();
914  BEAST_EXPECT(db);
915 
916  if (!BEAST_EXPECT(data.makeLedgers(env)))
917  return;
918 
919  for (std::uint32_t i = 0; i < 2; ++i)
920  if (!BEAST_EXPECT(createShard(data, *db, 2)))
921  return;
922  }
923 
924  boost::filesystem::path path = shardDir.path();
925  path /= std::string("2");
926  path /= backendType + ".dat";
927 
928  FILE* f = fopen(path.string().c_str(), "r+b");
929  if (!BEAST_EXPECT(f))
930  return;
931  char buf[256];
932  beast::rngfill(buf, sizeof(buf), data.rng_);
933  BEAST_EXPECT(fwrite(buf, 1, 256, f) == 256);
934  fclose(f);
935  }
936  {
937  Env env{*this, testConfig("", backendType, shardDir.path())};
938  DatabaseShard* db = env.app().getShardStore();
939  BEAST_EXPECT(db);
940 
941  TestData data(seedValue, 4, 2);
942  if (!BEAST_EXPECT(data.makeLedgers(env)))
943  return;
944 
945  for (std::uint32_t i = 1; i <= 1; ++i)
946  waitShard(*db, i);
947 
948  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(0x2));
949 
950  for (std::uint32_t i = 0; i < 1 * ledgersPerShard; ++i)
951  checkLedger(data, *db, *data.ledgers_[i]);
952  }
953  }
954 
955  void
957  std::string const& backendType,
958  std::uint64_t const seedValue)
959  {
960  using namespace test::jtx;
961 
962  for (int i = 0; i < 5; ++i)
963  {
964  beast::temp_dir shardDir;
965  {
966  Env env{
967  *this,
968  testConfig(
969  (i == 0 ? "illegalFinalKey" : ""),
970  backendType,
971  shardDir.path())};
972  DatabaseShard* db = env.app().getShardStore();
973  BEAST_EXPECT(db);
974 
975  TestData data(seedValue + i, 2);
976  if (!BEAST_EXPECT(data.makeLedgers(env)))
977  return;
978 
979  int shardNumber = -1;
980  for (std::uint32_t j = 0; j < ledgersPerShard; ++j)
981  {
982  auto ind = db->prepareLedger(2 * ledgersPerShard);
983  if (!BEAST_EXPECT(ind != boost::none))
984  return;
985  shardNumber = db->seqToShardIndex(*ind);
986  int arrInd = *ind - ledgersPerShard - 1;
987  BEAST_EXPECT(arrInd >= 0 && arrInd < ledgersPerShard);
988  BEAST_EXPECT(saveLedger(*db, *data.ledgers_[arrInd]));
989  if (arrInd % ledgersPerShard == (ledgersPerShard - 1))
990  {
991  uint256 const finalKey_{0};
992  Serializer s;
993  s.add32(Shard::version + (i == 0));
994  s.add32(db->firstLedgerSeq(shardNumber) + (i == 1));
995  s.add32(db->lastLedgerSeq(shardNumber) - (i == 3));
996  s.addRaw(
997  data.ledgers_[arrInd - (i == 4)]
998  ->info()
999  .hash.data(),
1000  256 / 8);
1001  db->store(
1002  hotUNKNOWN,
1003  std::move(s.modData()),
1004  finalKey_,
1005  *ind);
1006  }
1007  db->setStored(data.ledgers_[arrInd]);
1008  }
1009 
1010  if (i == 2)
1011  waitShard(*db, shardNumber);
1012  else
1013  {
1014  boost::filesystem::path path(shardDir.path());
1015  path /= "1";
1016  boost::system::error_code ec;
1017  auto start = std::chrono::system_clock::now();
1018  auto end = start + shardStoreTimeout;
1019  while (std::chrono::system_clock::now() < end &&
1020  boost::filesystem::exists(path, ec))
1021  {
1023  }
1024  }
1025 
1026  BEAST_EXPECT(
1027  db->getCompleteShards() ==
1028  bitmask2Rangeset(i == 2 ? 2 : 0));
1029  }
1030 
1031  {
1032  Env env{*this, testConfig("", backendType, shardDir.path())};
1033  DatabaseShard* db = env.app().getShardStore();
1034  BEAST_EXPECT(db);
1035 
1036  TestData data(seedValue + i, 2);
1037  if (!BEAST_EXPECT(data.makeLedgers(env)))
1038  return;
1039 
1040  if (i == 2)
1041  waitShard(*db, 1);
1042 
1043  BEAST_EXPECT(
1044  db->getCompleteShards() ==
1045  bitmask2Rangeset(i == 2 ? 2 : 0));
1046 
1047  if (i == 2)
1048  {
1049  for (std::uint32_t j = 0; j < ledgersPerShard; ++j)
1050  checkLedger(data, *db, *data.ledgers_[j]);
1051  }
1052  }
1053  }
1054  }
1055 
1056  void
1057  testImport(std::string const& backendType, std::uint64_t const seedValue)
1058  {
1059  using namespace test::jtx;
1060 
1061  beast::temp_dir shardDir;
1062  {
1063  beast::temp_dir nodeDir;
1064  Env env{
1065  *this,
1066  testConfig(
1067  "import", backendType, shardDir.path(), nodeDir.path())};
1068  DatabaseShard* db = env.app().getShardStore();
1069  Database& ndb = env.app().getNodeStore();
1070  BEAST_EXPECT(db);
1071 
1072  TestData data(seedValue, 4, 2);
1073  if (!BEAST_EXPECT(data.makeLedgers(env)))
1074  return;
1075 
1076  for (std::uint32_t i = 0; i < 2 * ledgersPerShard; ++i)
1077  BEAST_EXPECT(saveLedger(ndb, *data.ledgers_[i]));
1078 
1079  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(0));
1080  db->import(ndb);
1081  for (std::uint32_t i = 1; i <= 2; ++i)
1082  waitShard(*db, i);
1083  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(0x6));
1084  }
1085  {
1086  Env env{*this, testConfig("", backendType, shardDir.path())};
1087  DatabaseShard* db = env.app().getShardStore();
1088  BEAST_EXPECT(db);
1089 
1090  TestData data(seedValue, 4, 2);
1091  if (!BEAST_EXPECT(data.makeLedgers(env)))
1092  return;
1093 
1094  for (std::uint32_t i = 1; i <= 2; ++i)
1095  waitShard(*db, i);
1096 
1097  BEAST_EXPECT(db->getCompleteShards() == bitmask2Rangeset(0x6));
1098 
1099  for (std::uint32_t i = 0; i < 2 * ledgersPerShard; ++i)
1100  checkLedger(data, *db, *data.ledgers_[i]);
1101  }
1102  }
1103 
1104  std::string
1106  {
1107  using beast::hash_append;
1108  std::ifstream input(filename, std::ios::in | std::ios::binary);
1109  char buf[4096];
1110  ripemd160_hasher h;
1111 
1112  while (input.read(buf, 4096), input.gcount() > 0)
1113  hash_append(h, buf, input.gcount());
1114 
1115  auto const binResult = static_cast<ripemd160_hasher::result_type>(h);
1116  const auto charDigest = binResult.data();
1117  std::string result;
1118  boost::algorithm::hex(
1119  charDigest,
1120  charDigest + sizeof(binResult),
1121  std::back_inserter(result));
1122 
1123  return result;
1124  }
1125 
1126  void
1128  std::string const& backendType,
1129  std::uint64_t const seedValue)
1130  {
1131  using namespace test::jtx;
1132 
1133  std::string ripemd160Key("4CFA8985836B549EC99D2E9705707F488DC91E4E"),
1134  ripemd160Dat("8CC61F503C36339803F8C2FC652C1102DDB889F1");
1135 
1136  for (int i = 0; i < 2; i++)
1137  {
1138  beast::temp_dir shardDir;
1139  {
1140  Env env{
1141  *this,
1142  testConfig(
1143  (i ? "" : "deterministicShard"),
1144  backendType,
1145  shardDir.path())};
1146  DatabaseShard* db = env.app().getShardStore();
1147  BEAST_EXPECT(db);
1148 
1149  TestData data(seedValue, 4);
1150  if (!BEAST_EXPECT(data.makeLedgers(env)))
1151  return;
1152 
1153  if (createShard(data, *db) < 0)
1154  return;
1155  }
1156  {
1157  Env env{*this, testConfig("", backendType, shardDir.path())};
1158  DatabaseShard* db = env.app().getShardStore();
1159  BEAST_EXPECT(db);
1160 
1161  TestData data(seedValue, 4);
1162  if (!BEAST_EXPECT(data.makeLedgers(env)))
1163  return;
1164 
1165  waitShard(*db, 1);
1166 
1167  for (std::uint32_t j = 0; j < ledgersPerShard; ++j)
1168  checkLedger(data, *db, *data.ledgers_[j]);
1169  }
1170 
1171  boost::filesystem::path path(shardDir.path());
1172  path /= "1";
1173  boost::filesystem::path keypath = path / (backendType + ".key");
1174  std::string key = ripemd160File(keypath.string());
1175  boost::filesystem::path datpath = path / (backendType + ".dat");
1176  std::string dat = ripemd160File(datpath.string());
1177 
1178  std::cerr << "Iteration " << i << ": RIPEMD160[" << backendType
1179  << ".key] = " << key << std::endl;
1180  std::cerr << "Iteration " << i << ": RIPEMD160[" << backendType
1181  << ".dat] = " << dat << std::endl;
1182 
1183  BEAST_EXPECT(key == ripemd160Key);
1184  BEAST_EXPECT(dat == ripemd160Dat);
1185  }
1186  }
1187 
1188  void
1189  testAll(std::string const& backendType)
1190  {
1191  std::uint64_t const seedValue = 51;
1192  testStandalone(backendType);
1193  testCreateShard(backendType, seedValue);
1194  testReopenDatabase(backendType, seedValue + 5);
1195  testGetCompleteShards(backendType, seedValue + 10);
1196  testPrepareShard(backendType, seedValue + 20);
1197  testImportShard(backendType, seedValue + 30);
1198  testCorruptedDatabase(backendType, seedValue + 40);
1199  testIllegalFinalKey(backendType, seedValue + 50);
1200  testImport(backendType, seedValue + 60);
1201  testDeterministicShard(backendType, seedValue + 70);
1202  }
1203 
1204 public:
1205  DatabaseShard_test() : journal_("DatabaseShard_test", *this)
1206  {
1207  }
1208 
1209  void
1210  run() override
1211  {
1212  testAll("nudb");
1213 
1214 #if RIPPLE_ROCKSDB_AVAILABLE
1215 // testAll ("rocksdb");
1216 #endif
1217 
1218 #if RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
1219  testAll("sqlite");
1220 #endif
1221  }
1222 };
1223 
1224 BEAST_DEFINE_TESTSUITE(DatabaseShard, NodeStore, ripple);
1225 
1226 } // namespace NodeStore
1227 } // namespace ripple
ripple::NodeStore::make_ShardStore
std::unique_ptr< DatabaseShard > make_ShardStore(Application &app, Stoppable &parent, Scheduler &scheduler, int readThreads, beast::Journal j)
Definition: DatabaseShardImp.cpp:1425
ripple::NodeStore::uniformIntDistribution::paramType::A
const resultType A
Definition: DatabaseShard_test.cpp:62
ripple::NodeStore::DummyScheduler
Simple NodeStore Scheduler that just peforms the tasks synchronously.
Definition: DummyScheduler.h:29
ripple::hotUNKNOWN
@ hotUNKNOWN
Definition: NodeObject.h:33
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::SHAMap::isValid
bool isValid() const
Definition: SHAMap.h:522
ripple::NodeStore::randInt
Integral randInt(Engine &engine, Integral min, Integral max)
Definition: DatabaseShard_test.cpp:143
ripple::NodeStore::DatabaseShard_test::testLedgerData
void testLedgerData(TestData &data, std::shared_ptr< Ledger > ledger, std::uint32_t seq)
Definition: DatabaseShard_test.cpp:302
ripple::NodeStore::DatabaseShard_test::TestData::nAccounts_
std::vector< int > nAccounts_
Definition: DatabaseShard_test.cpp:185
fstream
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:53
ripple::NodeStore::DatabaseShard_test::testGetCompleteShards
void testGetCompleteShards(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:742
ripple::NodeStore::DatabaseShard_test::ledgersPerShard
static constexpr std::uint32_t ledgersPerShard
Definition: DatabaseShard_test.cpp:165
ripple::NodeStore::TestBase
Definition: TestBase.h:68
std::string
STL class.
std::shared_ptr
STL class.
ripple::SHAMap::getHash
SHAMapHash getHash() const
Definition: SHAMap.cpp:793
ripple::NodeStore::uniformIntDistribution::paramType::B
const resultType B
Definition: DatabaseShard_test.cpp:62
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:480
ripple::NodeStore::DatabaseShard::seqToShardIndex
virtual std::uint32_t seqToShardIndex(std::uint32_t seq) const =0
Calculates the shard index for a given ledger sequence.
ripple::NodeStore::uniformIntDistribution::resultType
IntType resultType
Definition: DatabaseShard_test.cpp:56
ripple::Generator
Produces a sequence of secp256k1 key pairs.
Definition: SecretKey.cpp:59
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:176
ripple::NodeStore::DatabaseShard_test::TestData::ledgers_
std::vector< std::shared_ptr< const Ledger > > ledgers_
Definition: DatabaseShard_test.cpp:194
std::vector::reserve
T reserve(T... args)
ripple::LedgerInfo::hash
uint256 hash
Definition: ReadView.h:96
ripple::NodeStore::DatabaseShard_test::journal_
test::SuiteJournal journal_
Definition: DatabaseShard_test.cpp:172
ripple::NodeStore::DatabaseShard_test::TestData::accounts_
std::vector< test::jtx::Account > accounts_
Definition: DatabaseShard_test.cpp:182
ripple::hotACCOUNT_NODE
@ hotACCOUNT_NODE
Definition: NodeObject.h:35
std::vector
STL class.
ripple::ConfigSection::shardDatabase
static std::string shardDatabase()
Definition: ConfigSections.h:38
std::vector::size
T size(T... args)
ripple::sfSequence
const SF_U32 sfSequence(access, STI_UINT32, 4, "Sequence")
Definition: SField.h:356
ripple::NodeStore::uniformIntDistribution::B
const resultType B
Definition: DatabaseShard_test.cpp:58
ripple::NodeStore::uniformIntDistribution::b
resultType b() const
Definition: DatabaseShard_test.cpp:102
std::back_inserter
T back_inserter(T... args)
ripple::snfPREFIX
@ snfPREFIX
Definition: SHAMapTreeNode.h:36
ripple::NodeObject::createObject
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
Definition: NodeObject.cpp:37
ripple::NodeStore::uniformIntDistribution::operator()
resultType operator()(Generator &g, const paramType &params) const
Definition: DatabaseShard_test.cpp:90
ripple::sfAccount
const SF_Account sfAccount(access, STI_ACCOUNT, 1, "Account")
Definition: SField.h:480
std::chrono::seconds
ripple::NodeStore::DatabaseShard_test::TestData::TestData
TestData(std::uint64_t const seedValue, int dataSize=dataSizeMax, int nShards=1)
Definition: DatabaseShard_test.cpp:196
std::ifstream::gcount
T gcount(T... args)
ripple::NodeStore::DatabaseShard_test::testConfig
std::unique_ptr< Config > testConfig(std::string const &testName, std::string const &backendType, std::string const &shardDir, std::string const &nodeDir=std::string())
Definition: DatabaseShard_test.cpp:552
ripple::NodeStore::DatabaseShard_test::TestData::payAccounts_
std::vector< std::vector< std::pair< int, int > > > payAccounts_
Definition: DatabaseShard_test.cpp:189
ripple::NodeStore::DatabaseShard::lastLedgerSeq
virtual std::uint32_t lastLedgerSeq(std::uint32_t shardIndex) const =0
Calculates the last ledger sequence for a given shard index.
ripple::NodeStore::DatabaseShard_test::testAll
void testAll(std::string const &backendType)
Definition: DatabaseShard_test.cpp:1189
ripple::NodeStore::DatabaseShard_test::checkLedger
void checkLedger(TestData &data, DatabaseShard &db, Ledger const &ledger)
Definition: DatabaseShard_test.cpp:456
ripple::NodeStore::uniformIntDistribution::rnd
resultType rnd(Generator &g, const resultType a, const resultType b) const
Definition: DatabaseShard_test.cpp:122
std::cerr
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s)
Definition: View.cpp:43
ripple::from_string
bool from_string(RangeSet< T > &rs, std::string const &s)
Convert the given styled string to a RangeSet.
Definition: RangeSet.h:126
ripple::NodeStore::DatabaseShard_test::earliestSeq
static constexpr std::uint32_t earliestSeq
Definition: DatabaseShard_test.cpp:166
ripple::test::jtx::Env::app
Application & app()
Definition: Env.h:240
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:88
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:42
std::ifstream::read
T read(T... args)
ripple::SHAMapHash::isNonZero
bool isNonZero() const
Definition: SHAMapTreeNode.h:69
ripple::NodeStore::DatabaseShard_test::TestData
Definition: DatabaseShard_test.cpp:175
ripple::hotTRANSACTION_NODE
@ hotTRANSACTION_NODE
Definition: NodeObject.h:36
ripple::sfAmount
const SF_Amount sfAmount(access, STI_AMOUNT, 1, "Amount")
Definition: SField.h:440
ripple::NodeStore::DatabaseShard_test::nTestShards
static constexpr std::uint32_t nTestShards
Definition: DatabaseShard_test.cpp:169
ripple::NodeStore::DatabaseShard_test::run
void run() override
Definition: DatabaseShard_test.cpp:1210
ripple::SHAMap::snapShot
std::shared_ptr< SHAMap > snapShot(bool isMutable) const
Definition: SHAMap.cpp:51
ripple::NodeStore::DatabaseShard_test::iniAmount
static constexpr std::uint32_t iniAmount
Definition: DatabaseShard_test.cpp:168
iostream
ripple::NodeStore::DatabaseShard::getCompleteShards
virtual std::string getCompleteShards()=0
Query which complete shards are stored.
ripple::NodeStore::DatabaseShard_test::TestData::nShards_
int nShards_
Definition: DatabaseShard_test.cpp:180
ripple::LedgerFill::expand
@ expand
Definition: LedgerToJson.h:46
ripple::LedgerInfo::txHash
uint256 txHash
Definition: ReadView.h:97
ripple::NodeStore::uniformIntDistribution::min
resultType min() const
Definition: DatabaseShard_test.cpp:108
ripple::ttPAYMENT
@ ttPAYMENT
Definition: TxFormats.h:36
ripple::NodeStore::Shard::version
static constexpr std::uint32_t version
Definition: Shard.h:157
std::is_convertible
ripple::NodeStore::DatabaseShard_test::ripemd160File
std::string ripemd160File(std::string filename)
Definition: DatabaseShard_test.cpp:1105
std::vector::push_back
T push_back(T... args)
ripple::base_uint< 256 >
ripple::NodeStore::DatabaseShard_test::DatabaseShard_test
DatabaseShard_test()
Definition: DatabaseShard_test.cpp:1205
ripple::Ledger::info
LedgerInfo const & info() const override
Returns information about the ledger.
Definition: Ledger.h:155
ripple::NodeStore::DatabaseShard_test::shardStoreTimeout
static constexpr std::chrono::seconds shardStoreTimeout
Definition: DatabaseShard_test.cpp:170
ripple::NodeStore::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(Backend, ripple_core, ripple)
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
ripple::RootStoppable
Definition: Stoppable.h:352
ripple::Ledger
Holds a ledger.
Definition: Ledger.h:77
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::NodeStore::Database::fetch
virtual std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq)=0
Fetch an object.
chrono
ripple::NodeStore::DatabaseShard_test::testCorruptedDatabase
void testCorruptedDatabase(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:899
ripple::NodeStore::DatabaseShard_test::defNodeDir
beast::temp_dir defNodeDir
Definition: DatabaseShard_test.cpp:173
ripple::Ledger::stateMap
SHAMap const & stateMap() const
Definition: Ledger.h:289
ripple::NodeStore::DatabaseShard_test::waitShard
std::optional< int > waitShard(DatabaseShard &db, int shardNumber, std::chrono::seconds timeout=shardStoreTimeout)
Definition: DatabaseShard_test.cpp:601
ripple::LedgerFill::full
@ full
Definition: LedgerToJson.h:47
ripple::NodeStore::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
ripple::Serializer::addRaw
int addRaw(Blob const &vector)
Definition: Serializer.cpp:100
std::to_string
T to_string(T... args)
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:276
std::array
STL class.
ripple::NodeStore::DatabaseShard_test::testStandalone
void testStandalone(std::string const &backendType)
Definition: DatabaseShard_test.cpp:652
ripple::NodeStore::uniformIntDistribution
std::uniform_int_distribution is platform dependent.
Definition: DatabaseShard_test.cpp:54
ripple::NodeStore::DatabaseShard_test::testIllegalFinalKey
void testIllegalFinalKey(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:956
ripple::NodeStore::DatabaseShard_test::TestData::rng_
beast::xor_shift_engine rng_
Definition: DatabaseShard_test.cpp:178
ripple::NodeStore::DatabaseShard_test
Definition: DatabaseShard_test.cpp:162
std::uint32_t
ripple::NodeStore::uniformIntDistribution::uniformIntDistribution
uniformIntDistribution(const paramType &params)
Definition: DatabaseShard_test.cpp:76
ripple::NodeStore::DatabaseShard::firstLedgerSeq
virtual std::uint32_t firstLedgerSeq(std::uint32_t shardIndex) const =0
Calculates the first ledger sequence for a given shard index.
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:53
ripple::NodeStore::uniformIntDistribution::paramType
Definition: DatabaseShard_test.cpp:60
ripple::test::SuiteJournal
Definition: SuiteJournal.h:88
beast::temp_dir::path
std::string path() const
Get the native path for the temporary directory.
Definition: temp_dir.h:66
ripple::Serializer
Definition: Serializer.h:39
ripple::LedgerFill::binary
@ binary
Definition: LedgerToJson.h:48
ripple::getJson
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
Definition: LedgerToJson.cpp:283
ripple::Ledger::txMap
SHAMap const & txMap() const
Definition: Ledger.h:301
ripple::NodeStore::DatabaseShard::fetchLedger
virtual std::shared_ptr< Ledger > fetchLedger(uint256 const &hash, std::uint32_t seq)=0
Fetch a ledger from the shard store.
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:87
ripple::NodeStore::DatabaseShard_test::testReopenDatabase
void testReopenDatabase(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:702
ripple::NodeStore::uniformIntDistribution::max
resultType max() const
Definition: DatabaseShard_test.cpp:114
ripple::NodeStore::DatabaseShard::importShard
virtual bool importShard(std::uint32_t shardIndex, boost::filesystem::path const &srcDir)=0
Import a shard into the shard database.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::DatabaseShard_test::testImportShard
void testImportShard(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:843
ripple::NodeStore::DatabaseShard_test::TestData::makeLedgers
bool makeLedgers(test::jtx::Env &env_)
Definition: DatabaseShard_test.cpp:273
std::endl
T endl(T... args)
ripple::ttACCOUNT_SET
@ ttACCOUNT_SET
Definition: TxFormats.h:39
ripple::test::jtx::Env::close
bool close(NetClock::time_point closeTime, boost::optional< std::chrono::milliseconds > consensusDelay=boost::none)
Close and advance the ledger.
Definition: Env.cpp:121
ripple::NodeStore::DatabaseShard_test::saveLedger
bool saveLedger(Database &db, Ledger const &ledger, std::shared_ptr< Ledger const > const &next={})
Definition: DatabaseShard_test.cpp:386
beast::rngfill
void rngfill(void *buffer, std::size_t bytes, Generator &g)
Definition: rngfill.h:32
ripple::NodeStore::DatabaseShard::prepareShard
virtual bool prepareShard(std::uint32_t shardIndex)=0
Prepare a shard index to be imported into the database.
beast::hash_append
std::enable_if_t< is_contiguously_hashable< T, Hasher >::value > hash_append(Hasher &h, T const &t) noexcept
Logically concatenate input data to a Hasher.
Definition: hash_append.h:232
ripple::NodeStore::uniformIntDistribution::uniformIntDistribution
uniformIntDistribution(const resultType a=0, const resultType b=std::numeric_limits< resultType >::max())
Definition: DatabaseShard_test.cpp:69
ripple::test::jtx::Env::fund
void fund(bool setDefaultRipple, STAmount const &amount, Account const &account)
Definition: Env.cpp:219
ripple::NodeStore::isSame
bool isSame(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs)
Returns true if objects are identical.
Definition: TestBase.h:57
ripple::hash_append
void hash_append(Hasher &h, Slice const &v)
Definition: Slice.h:195
ripple::NodeStore::DatabaseShard_test::TestData::isNewAccounts
bool isNewAccounts(int seq)
Definition: DatabaseShard_test.cpp:250
ripple::NodeStore::DatabaseShard::getPreShards
virtual std::string getPreShards()=0
Get shard indexes being imported.
ripple::NodeStore::DatabaseShard::setStored
virtual void setStored(std::shared_ptr< Ledger const > const &ledger)=0
Notifies the database that the given ledger has been fully acquired and stored.
ripple::NodeStore::DatabaseShard_test::testCreateShard
void testCreateShard(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:679
ripple::NodeStore::DatabaseShard_test::dataSizeMax
static constexpr std::uint32_t dataSizeMax
Definition: DatabaseShard_test.cpp:167
ripple::NodeStore::DatabaseShard_test::testImport
void testImport(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:1057
ripple::SHAMapAbstractNode
Definition: SHAMapTreeNode.h:122
ripple::NodeStore::DatabaseShard::prepareLedger
virtual boost::optional< std::uint32_t > prepareLedger(std::uint32_t validLedgerSeq)=0
Prepare to store a new ledger in the shard being acquired.
std::optional< int >
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
std::make_pair
T make_pair(T... args)
beast::detail::xor_shift_engine
Definition: xor_shift_engine.h:32
ripple::openssl_ripemd160_hasher
RIPEMD-160 digest.
Definition: digest.h:47
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::NodeStore::uniformIntDistribution::A
const resultType A
Definition: DatabaseShard_test.cpp:58
ripple::NodeStore::uniformIntDistribution::a
resultType a() const
Definition: DatabaseShard_test.cpp:96
ripple::RangeSet
boost::icl::interval_set< T, std::less, ClosedInterval< T > > RangeSet
A set of closed intervals over the domain T.
Definition: RangeSet.h:69
ripple::NodeStore::DatabaseShard_test::TestData::makeLedgerData
void makeLedgerData(test::jtx::Env &env_, std::uint32_t seq)
Definition: DatabaseShard_test.cpp:256
ripple::NodeStore::uniformIntDistribution::paramType::paramType
paramType(resultType aa, resultType bb)
Definition: DatabaseShard_test.cpp:64
ripple::NodeStore::DatabaseShard_test::createShard
std::optional< int > createShard(TestData &data, DatabaseShard &db, int maxShardNumber=1)
Definition: DatabaseShard_test.cpp:621
ripple::NodeStore::DatabaseShard::removePreShard
virtual void removePreShard(std::uint32_t shardIndex)=0
Remove a previously prepared shard index for import.
ripple::NodeStore::DatabaseShard_test::testPrepareShard
void testPrepareShard(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:774
ripple::ltACCOUNT_ROOT
@ ltACCOUNT_ROOT
Definition: LedgerFormats.h:53
std::unique_ptr
STL class.
ripple::NodeStore::Database::import
virtual void import(Database &source)=0
Import objects from another database.
ripple::LedgerFill
Definition: LedgerToJson.h:32
std::numeric_limits
ripple::NodeStore::DatabaseShard_test::bitmask2Rangeset
std::string bitmask2Rangeset(std::uint64_t bitmask)
Definition: DatabaseShard_test.cpp:528
std::array::data
T data(T... args)
ripple::NodeStore::uniformIntDistribution::operator()
resultType operator()(Generator &g) const
Definition: DatabaseShard_test.cpp:83
ripple::test::jtx::Env
A transaction testing environment.
Definition: Env.h:115
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:33
std::this_thread::yield
T yield(T... args)
beast::temp_dir
RAII temporary directory.
Definition: temp_dir.h:33
ripple::NodeStore::DatabaseShard_test::testDeterministicShard
void testDeterministicShard(std::string const &backendType, std::uint64_t const seedValue)
Definition: DatabaseShard_test.cpp:1127
ripple::NodeStore::DatabaseShard_test::TestData::xrpAmount_
std::vector< int > xrpAmount_
Definition: DatabaseShard_test.cpp:191
ripple::NodeStore::DatabaseShard_test::maxSizeGb
static constexpr std::uint32_t maxSizeGb
Definition: DatabaseShard_test.cpp:164
std::ifstream
STL class.
std::chrono::system_clock::now
T now(T... args)