rippled
nodestore/impl/Shard.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2017 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/InboundLedger.h>
21 #include <ripple/app/main/DBInit.h>
22 #include <ripple/app/rdb/backend/detail/Shard.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/core/ConfigSections.h>
25 #include <ripple/nodestore/Manager.h>
26 #include <ripple/nodestore/impl/DeterministicShard.h>
27 #include <ripple/nodestore/impl/Shard.h>
28 #include <ripple/protocol/digest.h>
29 
30 namespace ripple {
31 namespace NodeStore {
32 
33 uint256 const Shard::finalKey{0};
34 
36  Application& app,
37  DatabaseShard const& db,
38  std::uint32_t index,
40  : Shard(app, db, index, "", j)
41 {
42 }
43 
45  Application& app,
46  DatabaseShard const& db,
47  std::uint32_t index,
48  boost::filesystem::path const& dir,
50  : app_(app)
51  , j_(j)
52  , index_(index)
53  , firstSeq_(db.firstLedgerSeq(index))
54  , lastSeq_(std::max(firstSeq_, db.lastLedgerSeq(index)))
55  , maxLedgers_(db.maxLedgers(index))
56  , dir_((dir.empty() ? db.getRootDir() : dir) / std::to_string(index_))
57 {
58 }
59 
61 {
62  if (!removeOnDestroy_)
63  return;
64 
65  if (backend_)
66  {
67  // Abort removal if the backend is in use
68  if (backendCount_ > 0)
69  {
70  JLOG(j_.error()) << "shard " << index_
71  << " backend in use, unable to remove directory";
72  return;
73  }
74 
75  // Release database files first otherwise remove_all may fail
76  backend_.reset();
77  lgrSQLiteDB_.reset();
78  txSQLiteDB_.reset();
79  acquireInfo_.reset();
80  }
81 
82  try
83  {
84  boost::filesystem::remove_all(dir_);
85  }
86  catch (std::exception const& e)
87  {
88  JLOG(j_.fatal()) << "shard " << index_
89  << ". Exception caught in function " << __func__
90  << ". Error: " << e.what();
91  }
92 }
93 
94 bool
95 Shard::init(Scheduler& scheduler, nudb::context& context)
96 {
98  std::string const type{get(section, "type", "nudb")};
99  auto const factory{Manager::instance().find(type)};
100  if (!factory)
101  {
102  JLOG(j_.error()) << "shard " << index_ << " failed to find factory for "
103  << type;
104  return false;
105  }
106  section.set("path", dir_.string());
107 
108  std::lock_guard lock{mutex_};
109  if (backend_)
110  {
111  JLOG(j_.error()) << "shard " << index_ << " already initialized";
112  return false;
113  }
114  backend_ = factory->createInstance(
116  section,
117  megabytes(
118  app_.config().getValueFor(SizedItem::burstSize, std::nullopt)),
119  scheduler,
120  context,
121  j_);
122 
123  return open(lock);
124 }
125 
126 bool
128 {
129  std::lock_guard lock(mutex_);
130  if (!backend_)
131  {
132  JLOG(j_.error()) << "shard " << index_ << " not initialized";
133  return false;
134  }
135 
136  return backend_->isOpen();
137 }
138 
139 bool
141 {
142  // Keep database open if being acquired or finalized
144  return false;
145 
146  std::lock_guard lock(mutex_);
147 
148  // Keep database open if in use
149  if (backendCount_ > 0)
150  return false;
151 
152  if (!backend_)
153  {
154  JLOG(j_.error()) << "shard " << index_ << " not initialized";
155  return false;
156  }
157  if (!backend_->isOpen())
158  return false;
159 
160  try
161  {
162  backend_->close();
163  }
164  catch (std::exception const& e)
165  {
166  JLOG(j_.fatal()) << "shard " << index_
167  << ". Exception caught in function " << __func__
168  << ". Error: " << e.what();
169  return false;
170  }
171 
172  lgrSQLiteDB_.reset();
173  txSQLiteDB_.reset();
174  acquireInfo_.reset();
175 
176  // Reset caches to reduce memory use
179 
180  return true;
181 }
182 
185 {
187  {
188  JLOG(j_.warn()) << "shard " << index_
189  << " prepare called when not acquiring";
190  return std::nullopt;
191  }
192 
193  std::lock_guard lock(mutex_);
194  if (!acquireInfo_)
195  {
196  JLOG(j_.error()) << "shard " << index_
197  << " missing acquire SQLite database";
198  return std::nullopt;
199  }
200 
201  if (acquireInfo_->storedSeqs.empty())
202  return lastSeq_;
203  return prevMissing(acquireInfo_->storedSeqs, 1 + lastSeq_, firstSeq_);
204 }
205 
206 bool
208 {
210  {
211  // The import node store case is an exception
212  if (nodeObject->getHash() != finalKey)
213  {
214  // Ignore residual calls from InboundLedgers
215  JLOG(j_.trace()) << "shard " << index_ << " not acquiring";
216  return false;
217  }
218  }
219 
220  auto const scopedCount{makeBackendCount()};
221  if (!scopedCount)
222  return false;
223 
224  try
225  {
226  std::lock_guard lock(mutex_);
227  backend_->store(nodeObject);
228  }
229  catch (std::exception const& e)
230  {
231  JLOG(j_.fatal()) << "shard " << index_
232  << ". Exception caught in function " << __func__
233  << ". Error: " << e.what();
234  return false;
235  }
236 
237  return true;
238 }
239 
241 Shard::fetchNodeObject(uint256 const& hash, FetchReport& fetchReport)
242 {
243  auto const scopedCount{makeBackendCount()};
244  if (!scopedCount)
245  return nullptr;
246 
247  std::shared_ptr<NodeObject> nodeObject;
248 
249  // Try the backend
250  Status status;
251  try
252  {
253  std::lock_guard lock(mutex_);
254  status = backend_->fetch(hash.data(), &nodeObject);
255  }
256  catch (std::exception const& e)
257  {
258  JLOG(j_.fatal()) << "shard " << index_
259  << ". Exception caught in function " << __func__
260  << ". Error: " << e.what();
261  return nullptr;
262  }
263 
264  switch (status)
265  {
266  case ok:
267  case notFound:
268  break;
269  case dataCorrupt: {
270  JLOG(j_.fatal())
271  << "shard " << index_ << ". Corrupt node object at hash "
272  << to_string(hash);
273  break;
274  }
275  default: {
276  JLOG(j_.warn())
277  << "shard " << index_ << ". Unknown status=" << status
278  << " fetching node object at hash " << to_string(hash);
279  break;
280  }
281  }
282 
283  if (nodeObject)
284  fetchReport.wasFound = true;
285 
286  return nodeObject;
287 }
288 
291  std::shared_ptr<Ledger const> const& srcLedger,
292  std::shared_ptr<Ledger const> const& next)
293 {
294  StoreLedgerResult result;
296  {
297  // Ignore residual calls from InboundLedgers
298  JLOG(j_.trace()) << "shard " << index_ << ". Not acquiring";
299  return result;
300  }
301  if (containsLedger(srcLedger->info().seq))
302  {
303  JLOG(j_.trace()) << "shard " << index_ << ". Ledger already stored";
304  return result;
305  }
306 
307  auto fail = [&](std::string const& msg) {
308  JLOG(j_.error()) << "shard " << index_ << ". Source ledger sequence "
309  << srcLedger->info().seq << ". " << msg;
310  result.error = true;
311  return result;
312  };
313 
314  if (srcLedger->info().hash.isZero())
315  return fail("Invalid hash");
316  if (srcLedger->info().accountHash.isZero())
317  return fail("Invalid account hash");
318 
319  auto& srcDB{const_cast<Database&>(srcLedger->stateMap().family().db())};
320  if (&srcDB == &(app_.getShardFamily()->db()))
321  return fail("Source and destination databases are the same");
322 
323  auto const scopedCount{makeBackendCount()};
324  if (!scopedCount)
325  return fail("Failed to lock backend");
326 
327  Batch batch;
329  auto storeBatch = [&]() {
330  std::uint64_t sz{0};
331  for (auto const& nodeObject : batch)
332  sz += nodeObject->getData().size();
333 
334  try
335  {
336  std::lock_guard lock(mutex_);
337  backend_->storeBatch(batch);
338  }
339  catch (std::exception const& e)
340  {
341  fail(
342  std::string(". Exception caught in function ") + __func__ +
343  ". Error: " + e.what());
344  return false;
345  }
346 
347  result.count += batch.size();
348  result.size += sz;
349  batch.clear();
350  return true;
351  };
352 
353  // Store ledger header
354  {
355  Serializer s(sizeof(std::uint32_t) + sizeof(LedgerInfo));
357  addRaw(srcLedger->info(), s);
358  auto nodeObject = NodeObject::createObject(
359  hotLEDGER, std::move(s.modData()), srcLedger->info().hash);
360  batch.emplace_back(std::move(nodeObject));
361  }
362 
363  bool error = false;
364  auto visit = [&](SHAMapTreeNode const& node) {
365  if (!stop_)
366  {
367  if (auto nodeObject = srcDB.fetchNodeObject(
368  node.getHash().as_uint256(), srcLedger->info().seq))
369  {
370  batch.emplace_back(std::move(nodeObject));
371  if (batch.size() < batchWritePreallocationSize || storeBatch())
372  return true;
373  }
374  }
375 
376  error = true;
377  return false;
378  };
379 
380  // Store the state map
381  if (srcLedger->stateMap().getHash().isNonZero())
382  {
383  if (!srcLedger->stateMap().isValid())
384  return fail("Invalid state map");
385 
386  if (next && next->info().parentHash == srcLedger->info().hash)
387  {
388  auto have = next->stateMap().snapShot(false);
389  srcLedger->stateMap().snapShot(false)->visitDifferences(
390  &(*have), visit);
391  }
392  else
393  srcLedger->stateMap().snapShot(false)->visitNodes(visit);
394  if (error)
395  return fail("Failed to store state map");
396  }
397 
398  // Store the transaction map
399  if (srcLedger->info().txHash.isNonZero())
400  {
401  if (!srcLedger->txMap().isValid())
402  return fail("Invalid transaction map");
403 
404  srcLedger->txMap().snapShot(false)->visitNodes(visit);
405  if (error)
406  return fail("Failed to store transaction map");
407  }
408 
409  if (!batch.empty() && !storeBatch())
410  return fail("Failed to store");
411 
412  return result;
413 }
414 
415 bool
417 {
419  {
420  // Ignore residual calls from InboundLedgers
421  JLOG(j_.trace()) << "shard " << index_ << " not acquiring";
422  return false;
423  }
424 
425  auto fail = [&](std::string const& msg) {
426  JLOG(j_.error()) << "shard " << index_ << ". " << msg;
427  return false;
428  };
429 
430  auto const ledgerSeq{ledger->info().seq};
431  if (ledgerSeq < firstSeq_ || ledgerSeq > lastSeq_)
432  return fail("Invalid ledger sequence " + std::to_string(ledgerSeq));
433 
434  auto const scopedCount{makeBackendCount()};
435  if (!scopedCount)
436  return false;
437 
438  // This lock is used as an optimization to prevent unneeded
439  // calls to storeSQLite before acquireInfo_ is updated
440  std::lock_guard storedLock(storedMutex_);
441 
442  {
443  std::lock_guard lock(mutex_);
444  if (!acquireInfo_)
445  return fail("Missing acquire SQLite database");
446 
447  if (boost::icl::contains(acquireInfo_->storedSeqs, ledgerSeq))
448  {
449  // Ignore redundant calls
450  JLOG(j_.debug()) << "shard " << index_ << " ledger sequence "
451  << ledgerSeq << " already stored";
452  return true;
453  }
454  }
455 
456  if (!storeSQLite(ledger))
457  return fail("Failed to store ledger");
458 
459  std::lock_guard lock(mutex_);
460 
461  // Update the acquire database
462  acquireInfo_->storedSeqs.insert(ledgerSeq);
463 
464  try
465  {
466  auto session{acquireInfo_->SQLiteDB->checkoutDb()};
467  soci::blob sociBlob(*session);
468  convert(to_string(acquireInfo_->storedSeqs), sociBlob);
469  if (ledgerSeq == lastSeq_)
470  {
471  // Store shard's last ledger hash
472  auto const sHash{to_string(ledger->info().hash)};
473  *session << "UPDATE Shard "
474  "SET LastLedgerHash = :lastLedgerHash,"
475  "StoredLedgerSeqs = :storedLedgerSeqs "
476  "WHERE ShardIndex = :shardIndex;",
477  soci::use(sHash), soci::use(sociBlob), soci::use(index_);
478  }
479  else
480  {
481  *session << "UPDATE Shard "
482  "SET StoredLedgerSeqs = :storedLedgerSeqs "
483  "WHERE ShardIndex = :shardIndex;",
484  soci::use(sociBlob), soci::use(index_);
485  }
486  }
487  catch (std::exception const& e)
488  {
489  acquireInfo_->storedSeqs.erase(ledgerSeq);
490  return fail(
491  std::string(". Exception caught in function ") + __func__ +
492  ". Error: " + e.what());
493  }
494 
495  // Update progress
496  progress_ = boost::icl::length(acquireInfo_->storedSeqs);
497  if (progress_ == maxLedgers_)
499 
500  setFileStats(lock);
501  JLOG(j_.trace()) << "shard " << index_ << " stored ledger sequence "
502  << ledgerSeq;
503  return true;
504 }
505 
506 bool
508 {
509  if (ledgerSeq < firstSeq_ || ledgerSeq > lastSeq_)
510  return false;
512  return true;
513 
514  std::lock_guard lock(mutex_);
515  if (!acquireInfo_)
516  {
517  JLOG(j_.error()) << "shard " << index_
518  << " missing acquire SQLite database";
519  return false;
520  }
521  return boost::icl::contains(acquireInfo_->storedSeqs, ledgerSeq);
522 }
523 
524 std::chrono::steady_clock::time_point
526 {
527  std::lock_guard lock(mutex_);
528  return lastAccess_;
529 }
530 
533 {
534  std::lock_guard lock(mutex_);
535  return {fileSz_, fdRequired_};
536 }
537 
540 {
541  auto const scopedCount{makeBackendCount()};
542  if (!scopedCount)
543  return 0;
544  std::lock_guard lock(mutex_);
545  return backend_->getWriteLoad();
546 }
547 
548 bool
550 {
551  std::lock_guard lock(mutex_);
552  return legacy_;
553 }
554 
555 bool
556 Shard::finalize(bool writeSQLite, std::optional<uint256> const& referenceHash)
557 {
558  auto const scopedCount{makeBackendCount()};
559  if (!scopedCount)
560  return false;
561 
562  uint256 hash{0};
563  std::uint32_t ledgerSeq{0};
564  auto fail = [&](std::string const& msg) {
565  JLOG(j_.fatal()) << "shard " << index_ << ". " << msg
566  << (hash.isZero() ? ""
567  : ". Ledger hash " + to_string(hash))
568  << (ledgerSeq == 0 ? ""
569  : ". Ledger sequence " +
570  std::to_string(ledgerSeq));
572  progress_ = 0;
573  busy_ = false;
574  return false;
575  };
576 
577  try
578  {
579  std::lock_guard lock(mutex_);
580 
582  progress_ = 0;
583 
584  // Check if a final key has been stored
585  if (std::shared_ptr<NodeObject> nodeObject;
586  backend_->fetch(finalKey.data(), &nodeObject) == Status::ok)
587  {
588  // Check final key's value
589  SerialIter sIt(
590  nodeObject->getData().data(), nodeObject->getData().size());
591  if (sIt.get32() != version)
592  return fail("invalid version");
593 
594  if (sIt.get32() != firstSeq_ || sIt.get32() != lastSeq_)
595  return fail("out of range ledger sequences");
596 
597  if (hash = sIt.get256(); hash.isZero())
598  return fail("invalid last ledger hash");
599  }
600  else
601  {
602  // In the absence of a final key, an acquire SQLite database
603  // must be present in order to verify the shard
604  if (!acquireInfo_)
605  return fail("missing acquire SQLite database");
606 
607  auto [res, seqshash] = selectAcquireDBLedgerSeqsHash(
608  *acquireInfo_->SQLiteDB->checkoutDb(), index_);
609 
610  if (!res)
611  return fail("missing or invalid ShardIndex");
612 
613  if (!seqshash.hash)
614  return fail("missing LastLedgerHash");
615 
616  if (!hash.parseHex(*seqshash.hash) || hash.isZero())
617  return fail("invalid LastLedgerHash");
618 
619  if (!seqshash.sequences)
620  return fail("missing StoredLedgerSeqs");
621 
622  auto& storedSeqs{acquireInfo_->storedSeqs};
623  if (!from_string(storedSeqs, *seqshash.sequences) ||
624  boost::icl::first(storedSeqs) != firstSeq_ ||
625  boost::icl::last(storedSeqs) != lastSeq_ ||
626  storedSeqs.size() != maxLedgers_)
627  {
628  return fail("invalid StoredLedgerSeqs");
629  }
630  }
631  }
632  catch (std::exception const& e)
633  {
634  return fail(
635  std::string(". Exception caught in function ") + __func__ +
636  ". Error: " + e.what());
637  }
638 
639  // Verify the last ledger hash of a downloaded shard
640  // using a ledger hash obtained from the peer network
641  if (referenceHash && *referenceHash != hash)
642  return fail("invalid last ledger hash");
643 
644  // Verify every ledger stored in the backend
645  Config const& config{app_.config()};
648  auto const lastLedgerHash{hash};
649  auto& shardFamily{*app_.getShardFamily()};
650  auto const fullBelowCache{shardFamily.getFullBelowCache(lastSeq_)};
651  auto const treeNodeCache{shardFamily.getTreeNodeCache(lastSeq_)};
652 
653  // Reset caches to reduce memory usage
654  fullBelowCache->reset();
655  treeNodeCache->reset();
656 
657  Serializer s;
658  s.add32(version);
659  s.add32(firstSeq_);
660  s.add32(lastSeq_);
661  s.addBitString(lastLedgerHash);
662 
665  if (!dShard)
666  return fail("Failed to create deterministic shard");
667 
668  // Start with the last ledger in the shard and walk backwards from
669  // child to parent until we reach the first ledger
670  ledgerSeq = lastSeq_;
671  while (ledgerSeq >= firstSeq_)
672  {
673  if (stop_)
674  return false;
675 
676  auto nodeObject{verifyFetch(hash)};
677  if (!nodeObject)
678  return fail("invalid ledger");
679 
680  ledger = std::make_shared<Ledger>(
681  deserializePrefixedHeader(makeSlice(nodeObject->getData())),
682  config,
683  shardFamily);
684  if (ledger->info().seq != ledgerSeq)
685  return fail("invalid ledger sequence");
686  if (ledger->info().hash != hash)
687  return fail("invalid ledger hash");
688 
689  ledger->stateMap().setLedgerSeq(ledgerSeq);
690  ledger->txMap().setLedgerSeq(ledgerSeq);
691  ledger->setImmutable();
692  if (!ledger->stateMap().fetchRoot(
693  SHAMapHash{ledger->info().accountHash}, nullptr))
694  {
695  return fail("missing root STATE node");
696  }
697  if (ledger->info().txHash.isNonZero() &&
698  !ledger->txMap().fetchRoot(
699  SHAMapHash{ledger->info().txHash}, nullptr))
700  {
701  return fail("missing root TXN node");
702  }
703 
704  if (!verifyLedger(ledger, next, dShard))
705  return fail("failed to verify ledger");
706 
707  if (!dShard->store(nodeObject))
708  return fail("failed to store node object");
709 
710  if (writeSQLite && !storeSQLite(ledger))
711  return fail("failed storing to SQLite databases");
712 
713  assert(
714  ledger->info().seq == ledgerSeq &&
715  (ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
716  ledger->read(keylet::fees())));
717 
718  hash = ledger->info().parentHash;
719  next = std::move(ledger);
720 
721  // Update progress
722  progress_ = maxLedgers_ - (ledgerSeq - firstSeq_);
723 
724  --ledgerSeq;
725 
726  fullBelowCache->reset();
727  treeNodeCache->reset();
728  }
729 
730  JLOG(j_.debug()) << "shard " << index_ << " is valid";
731 
732  /*
733  TODO MP
734  SQLite VACUUM blocks all database access while processing.
735  Depending on the file size, that can take a while. Until we find
736  a non-blocking way of doing this, we cannot enable vacuum as
737  it can desync a server.
738 
739  try
740  {
741  // VACUUM the SQLite databases
742  auto const tmpDir {dir_ / "tmp_vacuum"};
743  create_directory(tmpDir);
744 
745  auto vacuum = [&tmpDir](std::unique_ptr<DatabaseCon>& sqliteDB)
746  {
747  auto session {sqliteDB->checkoutDb()};
748  *session << "PRAGMA synchronous=OFF;";
749  *session << "PRAGMA journal_mode=OFF;";
750  *session << "PRAGMA temp_store_directory='" <<
751  tmpDir.string() << "';";
752  *session << "VACUUM;";
753  };
754  vacuum(lgrSQLiteDB_);
755  vacuum(txSQLiteDB_);
756  remove_all(tmpDir);
757  }
758  catch (std::exception const& e)
759  {
760  return fail(
761  std::string(". Exception caught in function ") + __func__ +
762  ". Error: " + e.what());
763  }
764  */
765 
766  auto const nodeObject{
768  if (!dShard->store(nodeObject))
769  return fail("failed to store node object");
770 
771  try
772  {
773  {
774  // Store final key's value, may already be stored
775  std::lock_guard lock(mutex_);
776  backend_->store(nodeObject);
777  }
778 
779  // Do not allow all other threads work with the shard
780  busy_ = true;
781 
782  // Wait until all other threads leave the shard
783  while (backendCount_ > 1)
785 
786  std::lock_guard lock(mutex_);
787 
788  // Close original backend
789  backend_->close();
790 
791  // Close SQL databases
792  lgrSQLiteDB_.reset();
793  txSQLiteDB_.reset();
794 
795  // Remove the acquire SQLite database
796  if (acquireInfo_)
797  {
798  acquireInfo_.reset();
799  remove_all(dir_ / AcquireShardDBName);
800  }
801 
802  // Close deterministic backend
803  dShard->close();
804 
805  // Replace original backend with deterministic backend
806  remove(dir_ / "nudb.key");
807  remove(dir_ / "nudb.dat");
808  rename(dShard->getDir() / "nudb.key", dir_ / "nudb.key");
809  rename(dShard->getDir() / "nudb.dat", dir_ / "nudb.dat");
810 
811  // Re-open deterministic shard
812  if (!open(lock))
813  return fail("failed to open");
814 
815  assert(state_ == ShardState::finalized);
816 
817  // Allow all other threads work with the shard
818  busy_ = false;
819  }
820  catch (std::exception const& e)
821  {
822  return fail(
823  std::string(". Exception caught in function ") + __func__ +
824  ". Error: " + e.what());
825  }
826 
827  return true;
828 }
829 
830 bool
832 {
833  using namespace boost::filesystem;
834  Config const& config{app_.config()};
835  auto preexist{false};
836  auto fail = [this, &preexist](std::string const& msg) REQUIRES(mutex_) {
837  backend_->close();
838  lgrSQLiteDB_.reset();
839  txSQLiteDB_.reset();
840  acquireInfo_.reset();
841 
843  progress_ = 0;
844 
845  if (!preexist)
846  remove_all(dir_);
847 
848  if (!msg.empty())
849  {
850  JLOG(j_.fatal()) << "shard " << index_ << " " << msg;
851  }
852  return false;
853  };
854  auto createAcquireInfo = [this, &config]() REQUIRES(mutex_) {
855  DatabaseCon::Setup setup;
856  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
857  setup.standAlone = config.standalone();
858  setup.dataDir = dir_;
859  setup.useGlobalPragma = true;
860 
861  acquireInfo_ = std::make_unique<AcquireInfo>();
862  acquireInfo_->SQLiteDB = makeAcquireDB(
863  setup,
865 
867  progress_ = 0;
868  };
869 
870  try
871  {
872  // Open or create the NuDB key/value store
873  preexist = exists(dir_);
874  backend_->open(!preexist);
875 
876  if (!preexist)
877  {
878  // A new shard
879  createAcquireInfo();
880  insertAcquireDBIndex(acquireInfo_->SQLiteDB->getSession(), index_);
881  }
882  else if (exists(dir_ / AcquireShardDBName))
883  {
884  // A shard being acquired, backend is likely incomplete
885  createAcquireInfo();
886  auto [res, s] = selectAcquireDBLedgerSeqs(
887  acquireInfo_->SQLiteDB->getSession(), index_);
888 
889  if (!res)
890  return fail("invalid acquire SQLite database");
891 
892  if (s)
893  {
894  auto& storedSeqs{acquireInfo_->storedSeqs};
895  if (!from_string(storedSeqs, *s))
896  return fail("invalid StoredLedgerSeqs");
897 
898  if (boost::icl::first(storedSeqs) < firstSeq_ ||
899  boost::icl::last(storedSeqs) > lastSeq_)
900  {
901  return fail("invalid StoredLedgerSeqs");
902  }
903 
904  // Check if backend is complete
905  progress_ = boost::icl::length(storedSeqs);
906  if (progress_ == maxLedgers_)
908  }
909  }
910  else
911  {
912  // A shard with a finalized or complete state
913  std::shared_ptr<NodeObject> nodeObject;
914  if (backend_->fetch(finalKey.data(), &nodeObject) != Status::ok)
915  {
916  legacy_ = true;
917  return fail("incompatible, missing backend final key");
918  }
919 
920  // Check final key's value
921  SerialIter sIt(
922  nodeObject->getData().data(), nodeObject->getData().size());
923  if (sIt.get32() != version)
924  return fail("invalid version");
925 
926  if (sIt.get32() != firstSeq_ || sIt.get32() != lastSeq_)
927  return fail("out of range ledger sequences");
928 
929  if (sIt.get256().isZero())
930  return fail("invalid last ledger hash");
931 
932  if (exists(dir_ / LgrDBName) && exists(dir_ / TxDBName))
933  {
934  lastAccess_ = std::chrono::steady_clock::now();
936  }
937  else
939 
941  }
942  }
943  catch (std::exception const& e)
944  {
945  return fail(
946  std::string(". Exception caught in function ") + __func__ +
947  ". Error: " + e.what());
948  }
949 
950  if (!initSQLite(lock))
951  return fail({});
952 
953  setFileStats(lock);
954  return true;
955 }
956 
957 bool
959 {
960  Config const& config{app_.config()};
961  DatabaseCon::Setup const setup = [&]() {
962  DatabaseCon::Setup setup;
963  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
964  setup.standAlone = config.standalone();
965  setup.dataDir = dir_;
967  return setup;
968  }();
969 
970  try
971  {
972  if (lgrSQLiteDB_)
973  lgrSQLiteDB_.reset();
974 
975  if (txSQLiteDB_)
976  txSQLiteDB_.reset();
977 
978  switch (state_)
979  {
982  case ShardState::finalized: {
983  auto [lgr, tx] = makeShardCompleteLedgerDBs(config, setup);
984 
985  lgrSQLiteDB_ = std::move(lgr);
986  lgrSQLiteDB_->getSession() << boost::str(
987  boost::format("PRAGMA cache_size=-%d;") %
988  kilobytes(config.getValueFor(
989  SizedItem::lgrDBCache, std::nullopt)));
990 
991  txSQLiteDB_ = std::move(tx);
992  txSQLiteDB_->getSession() << boost::str(
993  boost::format("PRAGMA cache_size=-%d;") %
994  kilobytes(config.getValueFor(
995  SizedItem::txnDBCache, std::nullopt)));
996  break;
997  }
998 
999  // case ShardState::acquire:
1000  // case ShardState::queued:
1001  default: {
1002  // Incomplete shards use a Write Ahead Log for performance
1003  auto [lgr, tx] = makeShardIncompleteLedgerDBs(
1004  config,
1005  setup,
1007  &app_.getJobQueue(), &app_.logs()});
1008 
1009  lgrSQLiteDB_ = std::move(lgr);
1010  lgrSQLiteDB_->getSession() << boost::str(
1011  boost::format("PRAGMA cache_size=-%d;") %
1012  kilobytes(config.getValueFor(SizedItem::lgrDBCache)));
1013 
1014  txSQLiteDB_ = std::move(tx);
1015  txSQLiteDB_->getSession() << boost::str(
1016  boost::format("PRAGMA cache_size=-%d;") %
1017  kilobytes(config.getValueFor(SizedItem::txnDBCache)));
1018  break;
1019  }
1020  }
1021  }
1022  catch (std::exception const& e)
1023  {
1024  JLOG(j_.fatal()) << "shard " << index_
1025  << ". Exception caught in function " << __func__
1026  << ". Error: " << e.what();
1027  return false;
1028  }
1029 
1030  return true;
1031 }
1032 
1033 bool
1035 {
1036  if (stop_)
1037  return false;
1038 
1039  try
1040  {
1041  std::lock_guard lock(mutex_);
1042 
1043  auto res = updateLedgerDBs(
1044  *txSQLiteDB_->checkoutDb(),
1045  *lgrSQLiteDB_->checkoutDb(),
1046  ledger,
1047  index_,
1048  stop_,
1049  j_);
1050 
1051  if (!res)
1052  return false;
1053 
1054  // Update the acquire database if present
1055  if (acquireInfo_)
1056  {
1058  if (!acquireInfo_->storedSeqs.empty())
1059  s = to_string(acquireInfo_->storedSeqs);
1060 
1062  acquireInfo_->SQLiteDB->getSession(),
1063  ledger,
1064  index_,
1065  lastSeq_,
1066  s);
1067  }
1068  }
1069  catch (std::exception const& e)
1070  {
1071  JLOG(j_.fatal()) << "shard " << index_
1072  << ". Exception caught in function " << __func__
1073  << ". Error: " << e.what();
1074  return false;
1075  }
1076 
1077  return true;
1078 }
1079 
1080 void
1082 {
1083  fileSz_ = 0;
1084  fdRequired_ = 0;
1085  try
1086  {
1087  using namespace boost::filesystem;
1088  for (auto const& d : directory_iterator(dir_))
1089  {
1090  if (is_regular_file(d))
1091  {
1092  fileSz_ += file_size(d);
1093  ++fdRequired_;
1094  }
1095  }
1096  }
1097  catch (std::exception const& e)
1098  {
1099  JLOG(j_.fatal()) << "shard " << index_
1100  << ". Exception caught in function " << __func__
1101  << ". Error: " << e.what();
1102  }
1103 }
1104 
1105 bool
1107  std::shared_ptr<Ledger const> const& ledger,
1108  std::shared_ptr<Ledger const> const& next,
1109  std::shared_ptr<DeterministicShard> const& dShard) const
1110 {
1111  auto fail = [j = j_, index = index_, &ledger](std::string const& msg) {
1112  JLOG(j.error()) << "shard " << index << ". " << msg
1113  << (ledger->info().hash.isZero() ? ""
1114  : ". Ledger hash " +
1115  to_string(ledger->info().hash))
1116  << (ledger->info().seq == 0 ? ""
1117  : ". Ledger sequence " +
1118  std::to_string(ledger->info().seq));
1119  return false;
1120  };
1121 
1122  if (ledger->info().hash.isZero())
1123  return fail("Invalid ledger hash");
1124  if (ledger->info().accountHash.isZero())
1125  return fail("Invalid ledger account hash");
1126 
1127  bool error{false};
1128  auto visit = [this, &error, &dShard](SHAMapTreeNode const& node) {
1129  if (stop_)
1130  return false;
1131 
1132  auto nodeObject{verifyFetch(node.getHash().as_uint256())};
1133  if (!nodeObject || !dShard->store(nodeObject))
1134  error = true;
1135 
1136  return !error;
1137  };
1138 
1139  // Verify the state map
1140  if (ledger->stateMap().getHash().isNonZero())
1141  {
1142  if (!ledger->stateMap().isValid())
1143  return fail("Invalid state map");
1144 
1145  try
1146  {
1147  if (next && next->info().parentHash == ledger->info().hash)
1148  ledger->stateMap().visitDifferences(&next->stateMap(), visit);
1149  else
1150  ledger->stateMap().visitNodes(visit);
1151  }
1152  catch (std::exception const& e)
1153  {
1154  return fail(
1155  std::string(". Exception caught in function ") + __func__ +
1156  ". Error: " + e.what());
1157  }
1158 
1159  if (stop_)
1160  return false;
1161  if (error)
1162  return fail("Invalid state map");
1163  }
1164 
1165  // Verify the transaction map
1166  if (ledger->info().txHash.isNonZero())
1167  {
1168  if (!ledger->txMap().isValid())
1169  return fail("Invalid transaction map");
1170 
1171  try
1172  {
1173  ledger->txMap().visitNodes(visit);
1174  }
1175  catch (std::exception const& e)
1176  {
1177  return fail(
1178  std::string(". Exception caught in function ") + __func__ +
1179  ". Error: " + e.what());
1180  }
1181 
1182  if (stop_)
1183  return false;
1184  if (error)
1185  return fail("Invalid transaction map");
1186  }
1187 
1188  return true;
1189 }
1190 
1192 Shard::verifyFetch(uint256 const& hash) const
1193 {
1194  std::shared_ptr<NodeObject> nodeObject;
1195  auto fail =
1196  [j = j_, index = index_, &hash, &nodeObject](std::string const& msg) {
1197  JLOG(j.error()) << "shard " << index << ". " << msg
1198  << ". Node object hash " << to_string(hash);
1199  nodeObject.reset();
1200  return nodeObject;
1201  };
1202 
1203  try
1204  {
1205  std::lock_guard lock(mutex_);
1206  switch (backend_->fetch(hash.data(), &nodeObject))
1207  {
1208  case ok:
1209  // Verify that the hash of node object matches the payload
1210  if (nodeObject->getHash() !=
1211  sha512Half(makeSlice(nodeObject->getData())))
1212  return fail("Node object hash does not match payload");
1213  return nodeObject;
1214  case notFound:
1215  return fail("Missing node object");
1216  case dataCorrupt:
1217  return fail("Corrupt node object");
1218  default:
1219  return fail("Unknown error");
1220  }
1221  }
1222  catch (std::exception const& e)
1223  {
1224  return fail(
1225  std::string(". Exception caught in function ") + __func__ +
1226  ". Error: " + e.what());
1227  }
1228 }
1229 
1232 {
1233  if (stop_ || busy_)
1234  return Shard::Count{nullptr};
1235 
1236  std::lock_guard lock(mutex_);
1237  if (!backend_)
1238  {
1239  JLOG(j_.error()) << "shard " << index_ << " not initialized";
1240  return Shard::Count{nullptr};
1241  }
1242  if (!backend_->isOpen())
1243  {
1244  if (!open(lock))
1245  return Shard::Count{nullptr};
1246  }
1247  else if (state_ == ShardState::finalized)
1248  lastAccess_ = std::chrono::steady_clock::now();
1249 
1250  return Shard::Count(&backendCount_);
1251 }
1252 
1253 bool
1255  std::function<bool(soci::session& session)> const& callback,
1256  LockedSociSession&& db)
1257 {
1258  return callback(*db);
1259 }
1260 
1261 bool
1263  std::function<bool(soci::session& session, std::uint32_t shardIndex)> const&
1264  callback,
1265  LockedSociSession&& db)
1266 {
1267  return callback(*db, index_);
1268 }
1269 
1270 } // namespace NodeStore
1271 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:42
ripple::NodeStore::Shard::dir_
const boost::filesystem::path dir_
Definition: nodestore/impl/Shard.h:318
ripple::Application
Definition: Application.h:115
ripple::AcquireShardDBName
constexpr auto AcquireShardDBName
Definition: DBInit.h:196
ripple::hotUNKNOWN
@ hotUNKNOWN
Definition: NodeObject.h:33
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::Family::getTreeNodeCache
virtual std::shared_ptr< TreeNodeCache > getTreeNodeCache(std::uint32_t ledgerSeq)=0
Return a pointer to the Family Tree Node Cache.
ripple::makeAcquireDB
std::unique_ptr< DatabaseCon > makeAcquireDB(DatabaseCon::Setup const &setup, DatabaseCon::CheckpointerSetup const &checkpointerSetup)
makeAcquireDB Opens the shard acquire database and returns its descriptor.
Definition: UnitaryShard.cpp:208
ripple::NodeStore::Shard::mutex_
std::mutex mutex_
Definition: nodestore/impl/Shard.h:301
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::ShardState::complete
@ complete
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:51
std::string
STL class.
std::shared_ptr< NodeObject >
ripple::NodeStore::Shard::removeOnDestroy_
std::atomic< bool > removeOnDestroy_
Definition: nodestore/impl/Shard.h:359
std::exception
STL class.
ripple::NodeStore::Shard::storeLedger
StoreLedgerResult storeLedger(std::shared_ptr< Ledger const > const &srcLedger, std::shared_ptr< Ledger const > const &next)
Definition: nodestore/impl/Shard.cpp:290
ripple::DatabaseCon::Setup
Definition: DatabaseCon.h:84
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::NodeStore::Shard::prepare
std::optional< std::uint32_t > prepare()
Definition: nodestore/impl/Shard.cpp:184
ripple::NodeStore::ok
@ ok
Definition: nodestore/Types.h:45
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:178
std::pair
ripple::NodeStore::Shard::open
bool open(std::lock_guard< std::mutex > const &lock) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:831
std::vector::reserve
T reserve(T... args)
ripple::convert
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Definition: SociDB.cpp:154
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s, bool includeHash)
Definition: View.cpp:162
ripple::selectAcquireDBLedgerSeqsHash
std::pair< bool, AcquireShardSeqsHash > selectAcquireDBLedgerSeqsHash(soci::session &session, std::uint32_t index)
selectAcquireDBLedgerSeqsHash Returns the set of acquired ledger sequences and the last ledger hash f...
Definition: UnitaryShard.cpp:256
ripple::insertAcquireDBIndex
void insertAcquireDBIndex(soci::session &session, std::uint32_t index)
insertAcquireDBIndex Adds a new shard index to the shard acquire database.
Definition: UnitaryShard.cpp:221
ripple::DatabaseCon::Setup::startUp
Config::StartUpType startUp
Definition: DatabaseCon.h:88
std::vector< std::shared_ptr< NodeObject > >
ripple::ConfigSection::shardDatabase
static std::string shardDatabase()
Definition: ConfigSections.h:38
ripple::NodeStore::Shard::Shard
Shard(Shard const &)=delete
Copy constructor (disallowed)
std::vector::size
T size(T... args)
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::make_DeterministicShard
std::shared_ptr< DeterministicShard > make_DeterministicShard(Application &app, boost::filesystem::path const &shardDir, std::uint32_t shardIndex, Serializer const &finalKey, beast::Journal j)
Creates shared pointer to deterministic shard and initializes it.
Definition: DeterministicShard.cpp:151
ripple::DatabaseCon::CheckpointerSetup
Definition: DatabaseCon.h:107
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::NodeStore::Shard::getFileInfo
std::pair< std::uint64_t, std::uint32_t > getFileInfo() const
Returns a pair where the first item describes the storage space utilized and the second item is the n...
Definition: nodestore/impl/Shard.cpp:532
std::lock_guard
STL class.
ripple::kilobytes
constexpr auto kilobytes(T value) noexcept
Definition: ByteUtilities.h:27
ripple::NodeStore::FetchReport
Contains information about a fetch operation.
Definition: ripple/nodestore/Scheduler.h:32
ripple::NodeStore::Shard::isOpen
bool isOpen() const
Returns true if the database are open.
Definition: nodestore/impl/Shard.cpp:127
ripple::DatabaseCon::Setup::dataDir
boost::filesystem::path dataDir
Definition: DatabaseCon.h:91
ripple::from_string
bool from_string(RangeSet< T > &rs, std::string const &s)
Convert the given styled string to a RangeSet.
Definition: RangeSet.h:123
std::function
ripple::Family::getFullBelowCache
virtual std::shared_ptr< FullBelowCache > getFullBelowCache(std::uint32_t ledgerSeq)=0
Return a pointer to the Family Full Below Cache.
ripple::NodeStore::Shard::finalKey
static const uint256 finalKey
Definition: nodestore/impl/Shard.h:251
ripple::NodeStore::Shard::lastSeq_
const std::uint32_t lastSeq_
Definition: nodestore/impl/Shard.h:311
ripple::NodeStore::Shard::storedMutex_
std::mutex storedMutex_
Definition: nodestore/impl/Shard.h:302
ripple::deserializePrefixedHeader
LedgerInfo deserializePrefixedHeader(Slice data, bool hasHash)
Deserialize a ledger header (prefixed with 4 bytes) from a byte array.
Definition: InboundLedger.cpp:299
ripple::Family::db
virtual NodeStore::Database & db()=0
ripple::NodeStore::Shard::verifyFetch
std::shared_ptr< NodeObject > verifyFetch(uint256 const &hash) const
Definition: nodestore/impl/Shard.cpp:1192
ripple::XRP_LEDGER_EARLIEST_FEES
static constexpr std::uint32_t XRP_LEDGER_EARLIEST_FEES
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
Definition: SystemParameters.h:73
std::shared_ptr::reset
T reset(T... args)
ripple::base_uint::data
pointer data()
Definition: base_uint.h:122
ripple::SHAMapHash
Definition: SHAMapHash.h:32
ripple::NodeStore::Shard::tryClose
bool tryClose()
Try to close databases if not in use.
Definition: nodestore/impl/Shard.cpp:140
ripple::NodeStore::Shard::StoreLedgerResult::size
std::uint64_t size
Definition: nodestore/impl/Shard.h:133
ripple::NodeStore::batchWritePreallocationSize
@ batchWritePreallocationSize
Definition: nodestore/Types.h:34
ripple::NodeStore::Shard::isLegacy
bool isLegacy() const
Returns true if shard is older, without final key data.
Definition: nodestore/impl/Shard.cpp:549
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:550
ripple::NodeStore::Shard::version
static constexpr std::uint32_t version
Definition: nodestore/impl/Shard.h:246
ripple::NodeStore::Shard::storeSQLite
bool storeSQLite(std::shared_ptr< Ledger const > const &ledger)
Definition: nodestore/impl/Shard.cpp:1034
ripple::NodeStore::notFound
@ notFound
Definition: nodestore/Types.h:46
ripple::TxDBName
constexpr auto TxDBName
Definition: DBInit.h:73
ripple::base_uint< 256 >
ripple::updateAcquireDB
void updateAcquireDB(soci::session &session, std::shared_ptr< Ledger const > const &ledger, std::uint32_t index, std::uint32_t lastSeq, std::optional< std::string > const &seqs)
updateAcquireDB Updates information in the acquire DB.
Definition: UnitaryShard.cpp:287
ripple::DatabaseCon::Setup::useGlobalPragma
bool useGlobalPragma
Definition: DatabaseCon.h:94
ripple::NodeStore::Shard::j_
const beast::Journal j_
Definition: nodestore/impl/Shard.h:300
ripple::NodeStore::Shard::containsLedger
bool containsLedger(std::uint32_t ledgerSeq) const
Definition: nodestore/impl/Shard.cpp:507
ripple::NodeStore::Shard::StoreLedgerResult::error
bool error
Definition: nodestore/impl/Shard.h:134
ripple::DatabaseCon::Setup::standAlone
bool standAlone
Definition: DatabaseCon.h:89
ripple::Config::getValueFor
int getValueFor(SizedItem item, std::optional< std::size_t > node=std::nullopt) const
Retrieve the default value for the item at the specified node size.
Definition: Config.cpp:1022
ripple::NodeStore::Shard::storeNodeObject
bool storeNodeObject(std::shared_ptr< NodeObject > const &nodeObject)
Definition: nodestore/impl/Shard.cpp:207
ripple::NodeStore::Shard::initSQLite
bool initSQLite(std::lock_guard< std::mutex > const &) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:958
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:532
ripple::SerialIter::get256
uint256 get256()
Definition: Serializer.h:376
ripple::Config
Definition: Config.h:89
ripple::Application::config
virtual Config & config()=0
ripple::NodeStore::Shard::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, FetchReport &fetchReport)
Definition: nodestore/impl/Shard.cpp:241
ripple::megabytes
constexpr auto megabytes(T value) noexcept
Definition: ByteUtilities.h:34
ripple::NodeStore::Shard::setFileStats
void setFileStats(std::lock_guard< std::mutex > const &) REQUIRES(mutex_)
Definition: nodestore/impl/Shard.cpp:1081
ripple::NodeStore::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
ripple::SHAMapTreeNode
Definition: SHAMapTreeNode.h:53
std::to_string
T to_string(T... args)
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::NodeStore::Shard::firstSeq_
const std::uint32_t firstSeq_
Definition: nodestore/impl/Shard.h:308
beast::Journal::error
Stream error() const
Definition: Journal.h:333
ripple::ShardState::finalized
@ finalized
ripple::Application::logs
virtual Logs & logs()=0
ripple::NodeStore::Shard::maxLedgers_
const std::uint32_t maxLedgers_
Definition: nodestore/impl/Shard.h:315
ripple::SerialIter
Definition: Serializer.h:310
ripple::SizedItem::lgrDBCache
@ lgrDBCache
ripple::NodeStore::Shard::~Shard
~Shard()
Definition: nodestore/impl/Shard.cpp:60
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::SizedItem::burstSize
@ burstSize
ripple::NodeStore::Shard::verifyLedger
bool verifyLedger(std::shared_ptr< Ledger const > const &ledger, std::shared_ptr< Ledger const > const &next, std::shared_ptr< DeterministicShard > const &dShard) const
Definition: nodestore/impl/Shard.cpp:1106
ripple::NodeStore::dataCorrupt
@ dataCorrupt
Definition: nodestore/Types.h:47
std::uint32_t
ripple::ShardState::finalizing
@ finalizing
ripple::NodeStore::Scheduler
Scheduling for asynchronous backend activity.
Definition: ripple/nodestore/Scheduler.h:60
ripple::NodeStore::Shard::StoreLedgerResult
Store a ledger.
Definition: nodestore/impl/Shard.h:130
ripple::SizedItem::txnDBCache
@ txnDBCache
ripple::prevMissing
std::optional< T > prevMissing(RangeSet< T > const &rs, T t, T minVal=0)
Find the largest value not in the set that is less than a given value.
Definition: RangeSet.h:182
ripple::NodeStore::Shard::index
std::uint32_t index() const noexcept
Definition: nodestore/impl/Shard.h:149
ripple::NodeStore::Shard::app_
Application & app_
Definition: nodestore/impl/Shard.h:299
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
ripple::Serializer
Definition: Serializer.h:39
ripple::updateLedgerDBs
bool updateLedgerDBs(soci::session &txsession, soci::session &lgrsession, std::shared_ptr< Ledger const > const &ledger, std::uint32_t index, std::atomic< bool > &stop, beast::Journal j)
updateLedgerDBs Saves the given ledger to shard databases.
Definition: UnitaryShard.cpp:71
ripple::NodeStore::Manager::find
virtual Factory * find(std::string const &name)=0
Return a pointer to the matching factory if it exists.
ripple::NodeStore::Shard::progress_
std::atomic< std::uint32_t > progress_
Definition: nodestore/impl/Shard.h:356
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::LockedSociSession
Definition: DatabaseCon.h:37
ripple::Serializer::addBitString
int addBitString(base_uint< Bits, Tag > const &v)
Definition: Serializer.h:97
ripple::NodeObject::keyBytes
static constexpr std::size_t keyBytes
Definition: NodeObject.h:52
ripple::NodeStore::Shard::makeBackendCount
Shard::Count makeBackendCount()
Definition: nodestore/impl/Shard.cpp:1231
ripple::ShardState::acquire
@ acquire
ripple::Application::getShardFamily
virtual Family * getShardFamily()=0
ripple::NodeStore::Shard::StoreLedgerResult::count
std::uint64_t count
Definition: nodestore/impl/Shard.h:132
ripple::NodeStore::FetchReport::wasFound
bool wasFound
Definition: ripple/nodestore/Scheduler.h:40
std
STL namespace.
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
ripple::NodeStore::Shard::state_
std::atomic< ShardState > state_
Definition: nodestore/impl/Shard.h:353
ripple::NodeStore::Shard::doCallForSQL
bool doCallForSQL(std::function< bool(soci::session &session)> const &callback, LockedSociSession &&db)
Definition: nodestore/impl/Shard.cpp:1254
std::vector::empty
T empty(T... args)
ripple::makeShardIncompleteLedgerDBs
DatabasePair makeShardIncompleteLedgerDBs(Config const &config, DatabaseCon::Setup const &setup, DatabaseCon::CheckpointerSetup const &checkpointerSetup)
makeShardIncompleteLedgerDBs Opens shard databases for partially downloaded or unverified shards and ...
Definition: UnitaryShard.cpp:48
std::optional< std::uint32_t >
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::NodeStore::Shard::init
bool init(Scheduler &scheduler, nudb::context &context)
Initialize shard.
Definition: nodestore/impl/Shard.cpp:95
ripple::keylet::fees
Keylet const & fees() noexcept
The (fixed) index of the object containing the ledger fees.
Definition: Indexes.cpp:171
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::LedgerInfo
Information about the notional ledger backing the view.
Definition: ReadView.h:75
ripple::NodeStore::Shard::finalize
bool finalize(bool writeSQLite, std::optional< uint256 > const &referenceHash)
Finalize shard by walking its ledgers, verifying each Merkle tree and creating a deterministic backen...
Definition: nodestore/impl/Shard.cpp:556
ripple::selectAcquireDBLedgerSeqs
std::pair< bool, std::optional< std::string > > selectAcquireDBLedgerSeqs(soci::session &session, std::uint32_t index)
selectAcquireDBLedgerSeqs Returns the set of acquired ledgers for the given shard.
Definition: UnitaryShard.cpp:229
ripple::NodeStore::Manager::instance
static Manager & instance()
Returns the instance of the manager singleton.
Definition: ManagerImp.cpp:120
ripple::NodeStore::Shard::setLedgerStored
bool setLedgerStored(std::shared_ptr< Ledger const > const &ledger)
Definition: nodestore/impl/Shard.cpp:416
ripple::NodeStore::Shard
Definition: nodestore/impl/Shard.h:55
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:386
ripple::NodeStore::Shard::Count
Definition: nodestore/impl/Shard.h:254
ripple::NodeStore::Shard::index_
const std::uint32_t index_
Definition: nodestore/impl/Shard.h:305
ripple::NodeStore::Shard::stop_
std::atomic< bool > stop_
Definition: nodestore/impl/Shard.h:347
ripple::NodeStore::Shard::backendCount_
std::atomic< std::uint32_t > backendCount_
Definition: nodestore/impl/Shard.h:329
ripple::NodeStore::Shard::getLastUse
std::chrono::steady_clock::time_point getLastUse() const
Definition: nodestore/impl/Shard.cpp:525
ripple::NodeStore::Shard::getWriteLoad
std::int32_t getWriteLoad()
Definition: nodestore/impl/Shard.cpp:539
std::this_thread::yield
T yield(T... args)
std::exception::what
T what(T... args)
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
ripple::makeShardCompleteLedgerDBs
DatabasePair makeShardCompleteLedgerDBs(Config const &config, DatabaseCon::Setup const &setup)
makeShardCompleteLedgerDBs Opens shard databases for verified shards and returns their descriptors.
Definition: UnitaryShard.cpp:28
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:127
ripple::NodeStore::Shard::busy_
std::atomic< bool > busy_
Definition: nodestore/impl/Shard.h:350
ripple::LgrDBName
constexpr auto LgrDBName
Definition: DBInit.h:43
std::chrono::steady_clock::now
T now(T... args)