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