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