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  assert(
692  ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
693  ledger->read(keylet::fees()));
694  ledger->setImmutable();
695  if (!ledger->stateMap().fetchRoot(
696  SHAMapHash{ledger->info().accountHash}, nullptr))
697  {
698  return fail("missing root STATE node");
699  }
700  if (ledger->info().txHash.isNonZero() &&
701  !ledger->txMap().fetchRoot(
702  SHAMapHash{ledger->info().txHash}, nullptr))
703  {
704  return fail("missing root TXN node");
705  }
706 
707  if (!verifyLedger(ledger, next, dShard))
708  return fail("failed to verify ledger");
709 
710  if (!dShard->store(nodeObject))
711  return fail("failed to store node object");
712 
713  if (writeSQLite && !storeSQLite(ledger))
714  return fail("failed storing to SQLite databases");
715 
716  hash = ledger->info().parentHash;
717  next = std::move(ledger);
718 
719  // Update progress
720  progress_ = maxLedgers_ - (ledgerSeq - firstSeq_);
721 
722  --ledgerSeq;
723 
724  fullBelowCache->reset();
725  treeNodeCache->reset();
726  }
727 
728  JLOG(j_.debug()) << "shard " << index_ << " is valid";
729 
730  /*
731  TODO MP
732  SQLite VACUUM blocks all database access while processing.
733  Depending on the file size, that can take a while. Until we find
734  a non-blocking way of doing this, we cannot enable vacuum as
735  it can desync a server.
736 
737  try
738  {
739  // VACUUM the SQLite databases
740  auto const tmpDir {dir_ / "tmp_vacuum"};
741  create_directory(tmpDir);
742 
743  auto vacuum = [&tmpDir](std::unique_ptr<DatabaseCon>& sqliteDB)
744  {
745  auto session {sqliteDB->checkoutDb()};
746  *session << "PRAGMA synchronous=OFF;";
747  *session << "PRAGMA journal_mode=OFF;";
748  *session << "PRAGMA temp_store_directory='" <<
749  tmpDir.string() << "';";
750  *session << "VACUUM;";
751  };
752  vacuum(lgrSQLiteDB_);
753  vacuum(txSQLiteDB_);
754  remove_all(tmpDir);
755  }
756  catch (std::exception const& e)
757  {
758  return fail(
759  std::string(". Exception caught in function ") + __func__ +
760  ". Error: " + e.what());
761  }
762  */
763 
764  auto const nodeObject{
766  if (!dShard->store(nodeObject))
767  return fail("failed to store node object");
768 
769  try
770  {
771  {
772  // Store final key's value, may already be stored
773  std::lock_guard lock(mutex_);
774  backend_->store(nodeObject);
775  }
776 
777  // Do not allow all other threads work with the shard
778  busy_ = true;
779 
780  // Wait until all other threads leave the shard
781  while (backendCount_ > 1)
783 
784  std::lock_guard lock(mutex_);
785 
786  // Close original backend
787  backend_->close();
788 
789  // Close SQL databases
790  lgrSQLiteDB_.reset();
791  txSQLiteDB_.reset();
792 
793  // Remove the acquire SQLite database
794  if (acquireInfo_)
795  {
796  acquireInfo_.reset();
797  remove_all(dir_ / AcquireShardDBName);
798  }
799 
800  // Close deterministic backend
801  dShard->close();
802 
803  // Replace original backend with deterministic backend
804  remove(dir_ / "nudb.key");
805  remove(dir_ / "nudb.dat");
806  rename(dShard->getDir() / "nudb.key", dir_ / "nudb.key");
807  rename(dShard->getDir() / "nudb.dat", dir_ / "nudb.dat");
808 
809  // Re-open deterministic shard
810  if (!open(lock))
811  return fail("failed to open");
812 
813  assert(state_ == ShardState::finalized);
814 
815  // Allow all other threads work with the shard
816  busy_ = false;
817  }
818  catch (std::exception const& e)
819  {
820  return fail(
821  std::string(". Exception caught in function ") + __func__ +
822  ". Error: " + e.what());
823  }
824 
825  return true;
826 }
827 
828 bool
830 {
831  using namespace boost::filesystem;
832  Config const& config{app_.config()};
833  auto preexist{false};
834  auto fail = [this, &preexist](std::string const& msg) REQUIRES(mutex_) {
835  backend_->close();
836  lgrSQLiteDB_.reset();
837  txSQLiteDB_.reset();
838  acquireInfo_.reset();
839 
841  progress_ = 0;
842 
843  if (!preexist)
844  remove_all(dir_);
845 
846  if (!msg.empty())
847  {
848  JLOG(j_.fatal()) << "shard " << index_ << " " << msg;
849  }
850  return false;
851  };
852  auto createAcquireInfo = [this, &config]() REQUIRES(mutex_) {
853  DatabaseCon::Setup setup;
854  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
855  setup.standAlone = config.standalone();
856  setup.dataDir = dir_;
857  setup.useGlobalPragma = true;
858 
859  acquireInfo_ = std::make_unique<AcquireInfo>();
860  acquireInfo_->SQLiteDB = makeAcquireDB(
861  setup,
863 
865  progress_ = 0;
866  };
867 
868  try
869  {
870  // Open or create the NuDB key/value store
871  preexist = exists(dir_);
872  backend_->open(!preexist);
873 
874  if (!preexist)
875  {
876  // A new shard
877  createAcquireInfo();
878  insertAcquireDBIndex(acquireInfo_->SQLiteDB->getSession(), index_);
879  }
880  else if (exists(dir_ / AcquireShardDBName))
881  {
882  // A shard being acquired, backend is likely incomplete
883  createAcquireInfo();
884  auto [res, s] = selectAcquireDBLedgerSeqs(
885  acquireInfo_->SQLiteDB->getSession(), index_);
886 
887  if (!res)
888  return fail("invalid acquire SQLite database");
889 
890  if (s)
891  {
892  auto& storedSeqs{acquireInfo_->storedSeqs};
893  if (!from_string(storedSeqs, *s))
894  return fail("invalid StoredLedgerSeqs");
895 
896  if (boost::icl::first(storedSeqs) < firstSeq_ ||
897  boost::icl::last(storedSeqs) > lastSeq_)
898  {
899  return fail("invalid StoredLedgerSeqs");
900  }
901 
902  // Check if backend is complete
903  progress_ = boost::icl::length(storedSeqs);
904  if (progress_ == maxLedgers_)
906  }
907  }
908  else
909  {
910  // A shard with a finalized or complete state
911  std::shared_ptr<NodeObject> nodeObject;
912  if (backend_->fetch(finalKey.data(), &nodeObject) != Status::ok)
913  {
914  legacy_ = true;
915  return fail("incompatible, missing backend final key");
916  }
917 
918  // Check final key's value
919  SerialIter sIt(
920  nodeObject->getData().data(), nodeObject->getData().size());
921  if (sIt.get32() != version)
922  return fail("invalid version");
923 
924  if (sIt.get32() != firstSeq_ || sIt.get32() != lastSeq_)
925  return fail("out of range ledger sequences");
926 
927  if (sIt.get256().isZero())
928  return fail("invalid last ledger hash");
929 
930  if (exists(dir_ / LgrDBName) && exists(dir_ / TxDBName))
931  {
932  lastAccess_ = std::chrono::steady_clock::now();
934  }
935  else
937 
939  }
940  }
941  catch (std::exception const& e)
942  {
943  return fail(
944  std::string(". Exception caught in function ") + __func__ +
945  ". Error: " + e.what());
946  }
947 
948  if (!initSQLite(lock))
949  return fail({});
950 
951  setFileStats(lock);
952  return true;
953 }
954 
955 bool
957 {
958  Config const& config{app_.config()};
959  DatabaseCon::Setup const setup = [&]() {
960  DatabaseCon::Setup setup;
961  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
962  setup.standAlone = config.standalone();
963  setup.dataDir = dir_;
965  return setup;
966  }();
967 
968  try
969  {
970  if (lgrSQLiteDB_)
971  lgrSQLiteDB_.reset();
972 
973  if (txSQLiteDB_)
974  txSQLiteDB_.reset();
975 
976  switch (state_)
977  {
980  case ShardState::finalized: {
981  auto [lgr, tx] = makeShardCompleteLedgerDBs(config, setup);
982 
983  lgrSQLiteDB_ = std::move(lgr);
984  lgrSQLiteDB_->getSession() << boost::str(
985  boost::format("PRAGMA cache_size=-%d;") %
986  kilobytes(config.getValueFor(
987  SizedItem::lgrDBCache, std::nullopt)));
988 
989  txSQLiteDB_ = std::move(tx);
990  txSQLiteDB_->getSession() << boost::str(
991  boost::format("PRAGMA cache_size=-%d;") %
992  kilobytes(config.getValueFor(
993  SizedItem::txnDBCache, std::nullopt)));
994  break;
995  }
996 
997  // case ShardState::acquire:
998  // case ShardState::queued:
999  default: {
1000  // Incomplete shards use a Write Ahead Log for performance
1001  auto [lgr, tx] = makeShardIncompleteLedgerDBs(
1002  config,
1003  setup,
1005  &app_.getJobQueue(), &app_.logs()});
1006 
1007  lgrSQLiteDB_ = std::move(lgr);
1008  lgrSQLiteDB_->getSession() << boost::str(
1009  boost::format("PRAGMA cache_size=-%d;") %
1010  kilobytes(config.getValueFor(SizedItem::lgrDBCache)));
1011 
1012  txSQLiteDB_ = std::move(tx);
1013  txSQLiteDB_->getSession() << boost::str(
1014  boost::format("PRAGMA cache_size=-%d;") %
1015  kilobytes(config.getValueFor(SizedItem::txnDBCache)));
1016  break;
1017  }
1018  }
1019  }
1020  catch (std::exception const& e)
1021  {
1022  JLOG(j_.fatal()) << "shard " << index_
1023  << ". Exception caught in function " << __func__
1024  << ". Error: " << e.what();
1025  return false;
1026  }
1027 
1028  return true;
1029 }
1030 
1031 bool
1033 {
1034  if (stop_)
1035  return false;
1036 
1037  try
1038  {
1039  std::lock_guard lock(mutex_);
1040 
1041  auto res = updateLedgerDBs(
1042  *txSQLiteDB_->checkoutDb(),
1043  *lgrSQLiteDB_->checkoutDb(),
1044  ledger,
1045  index_,
1046  stop_,
1047  j_);
1048 
1049  if (!res)
1050  return false;
1051 
1052  // Update the acquire database if present
1053  if (acquireInfo_)
1054  {
1056  if (!acquireInfo_->storedSeqs.empty())
1057  s = to_string(acquireInfo_->storedSeqs);
1058 
1060  acquireInfo_->SQLiteDB->getSession(),
1061  ledger,
1062  index_,
1063  lastSeq_,
1064  s);
1065  }
1066  }
1067  catch (std::exception const& e)
1068  {
1069  JLOG(j_.fatal()) << "shard " << index_
1070  << ". Exception caught in function " << __func__
1071  << ". Error: " << e.what();
1072  return false;
1073  }
1074 
1075  return true;
1076 }
1077 
1078 void
1080 {
1081  fileSz_ = 0;
1082  fdRequired_ = 0;
1083  try
1084  {
1085  using namespace boost::filesystem;
1086  for (auto const& d : directory_iterator(dir_))
1087  {
1088  if (is_regular_file(d))
1089  {
1090  fileSz_ += file_size(d);
1091  ++fdRequired_;
1092  }
1093  }
1094  }
1095  catch (std::exception const& e)
1096  {
1097  JLOG(j_.fatal()) << "shard " << index_
1098  << ". Exception caught in function " << __func__
1099  << ". Error: " << e.what();
1100  }
1101 }
1102 
1103 bool
1105  std::shared_ptr<Ledger const> const& ledger,
1106  std::shared_ptr<Ledger const> const& next,
1107  std::shared_ptr<DeterministicShard> const& dShard) const
1108 {
1109  auto fail = [j = j_, index = index_, &ledger](std::string const& msg) {
1110  JLOG(j.error()) << "shard " << index << ". " << msg
1111  << (ledger->info().hash.isZero() ? ""
1112  : ". Ledger hash " +
1113  to_string(ledger->info().hash))
1114  << (ledger->info().seq == 0 ? ""
1115  : ". Ledger sequence " +
1116  std::to_string(ledger->info().seq));
1117  return false;
1118  };
1119 
1120  if (ledger->info().hash.isZero())
1121  return fail("Invalid ledger hash");
1122  if (ledger->info().accountHash.isZero())
1123  return fail("Invalid ledger account hash");
1124 
1125  bool error{false};
1126  auto visit = [this, &error, &dShard](SHAMapTreeNode const& node) {
1127  if (stop_)
1128  return false;
1129 
1130  auto nodeObject{verifyFetch(node.getHash().as_uint256())};
1131  if (!nodeObject || !dShard->store(nodeObject))
1132  error = true;
1133 
1134  return !error;
1135  };
1136 
1137  // Verify the state map
1138  if (ledger->stateMap().getHash().isNonZero())
1139  {
1140  if (!ledger->stateMap().isValid())
1141  return fail("Invalid state map");
1142 
1143  try
1144  {
1145  if (next && next->info().parentHash == ledger->info().hash)
1146  ledger->stateMap().visitDifferences(&next->stateMap(), visit);
1147  else
1148  ledger->stateMap().visitNodes(visit);
1149  }
1150  catch (std::exception const& e)
1151  {
1152  return fail(
1153  std::string(". Exception caught in function ") + __func__ +
1154  ". Error: " + e.what());
1155  }
1156 
1157  if (stop_)
1158  return false;
1159  if (error)
1160  return fail("Invalid state map");
1161  }
1162 
1163  // Verify the transaction map
1164  if (ledger->info().txHash.isNonZero())
1165  {
1166  if (!ledger->txMap().isValid())
1167  return fail("Invalid transaction map");
1168 
1169  try
1170  {
1171  ledger->txMap().visitNodes(visit);
1172  }
1173  catch (std::exception const& e)
1174  {
1175  return fail(
1176  std::string(". Exception caught in function ") + __func__ +
1177  ". Error: " + e.what());
1178  }
1179 
1180  if (stop_)
1181  return false;
1182  if (error)
1183  return fail("Invalid transaction map");
1184  }
1185 
1186  return true;
1187 }
1188 
1190 Shard::verifyFetch(uint256 const& hash) const
1191 {
1192  std::shared_ptr<NodeObject> nodeObject;
1193  auto fail =
1194  [j = j_, index = index_, &hash, &nodeObject](std::string const& msg) {
1195  JLOG(j.error()) << "shard " << index << ". " << msg
1196  << ". Node object hash " << to_string(hash);
1197  nodeObject.reset();
1198  return nodeObject;
1199  };
1200 
1201  try
1202  {
1203  std::lock_guard lock(mutex_);
1204  switch (backend_->fetch(hash.data(), &nodeObject))
1205  {
1206  case ok:
1207  // Verify that the hash of node object matches the payload
1208  if (nodeObject->getHash() !=
1209  sha512Half(makeSlice(nodeObject->getData())))
1210  return fail("Node object hash does not match payload");
1211  return nodeObject;
1212  case notFound:
1213  return fail("Missing node object");
1214  case dataCorrupt:
1215  return fail("Corrupt node object");
1216  default:
1217  return fail("Unknown error");
1218  }
1219  }
1220  catch (std::exception const& e)
1221  {
1222  return fail(
1223  std::string(". Exception caught in function ") + __func__ +
1224  ". Error: " + e.what());
1225  }
1226 }
1227 
1230 {
1231  if (stop_ || busy_)
1232  return Shard::Count{nullptr};
1233 
1234  std::lock_guard lock(mutex_);
1235  if (!backend_)
1236  {
1237  JLOG(j_.error()) << "shard " << index_ << " not initialized";
1238  return Shard::Count{nullptr};
1239  }
1240  if (!backend_->isOpen())
1241  {
1242  if (!open(lock))
1243  return Shard::Count{nullptr};
1244  }
1245  else if (state_ == ShardState::finalized)
1246  lastAccess_ = std::chrono::steady_clock::now();
1247 
1248  return Shard::Count(&backendCount_);
1249 }
1250 
1251 bool
1253  std::function<bool(soci::session& session)> const& callback,
1254  LockedSociSession&& db)
1255 {
1256  return callback(*db);
1257 }
1258 
1259 bool
1261  std::function<bool(soci::session& session, std::uint32_t shardIndex)> const&
1262  callback,
1263  LockedSociSession&& db)
1264 {
1265  return callback(*db, index_);
1266 }
1267 
1268 } // namespace NodeStore
1269 } // 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:829
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:1190
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:1032
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:956
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:1079
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:1104
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:1229
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:1252
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)