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