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/basics/StringUtilities.h>
23 #include <ripple/core/ConfigSections.h>
24 #include <ripple/nodestore/Manager.h>
25 #include <ripple/nodestore/impl/Shard.h>
26 #include <ripple/protocol/digest.h>
27 
28 #include <boost/algorithm/string.hpp>
29 #include <boost/range/adaptor/transformed.hpp>
30 
31 namespace ripple {
32 namespace NodeStore {
33 
34 uint256 const Shard::finalKey{0};
35 
37  Application& app,
38  DatabaseShard const& db,
39  std::uint32_t index,
41  : Shard(app, db, index, "", j)
42 {
43 }
44 
46  Application& app,
47  DatabaseShard const& db,
48  std::uint32_t index,
49  boost::filesystem::path const& dir,
51  : app_(app)
52  , j_(j)
53  , index_(index)
54  , firstSeq_(db.firstLedgerSeq(index))
55  , lastSeq_(std::max(firstSeq_, db.lastLedgerSeq(index)))
56  , maxLedgers_(
57  index == db.earliestShardIndex() ? lastSeq_ - firstSeq_ + 1
58  : db.ledgersPerShard())
59  , dir_((dir.empty() ? db.getRootDir() : dir) / std::to_string(index_))
60 {
61 }
62 
64 {
65  if (!removeOnDestroy_)
66  return;
67 
68  if (backend_)
69  {
70  // Abort removal if the backend is in use
71  if (backendCount_ > 0)
72  {
73  JLOG(j_.error()) << "shard " << index_
74  << " backend in use, unable to remove directory";
75  return;
76  }
77 
78  // Release database files first otherwise remove_all may fail
79  backend_.reset();
80  lgrSQLiteDB_.reset();
81  txSQLiteDB_.reset();
82  acquireInfo_.reset();
83  }
84 
85  try
86  {
87  boost::filesystem::remove_all(dir_);
88  }
89  catch (std::exception const& e)
90  {
91  JLOG(j_.fatal()) << "shard " << index_
92  << ". Exception caught in function " << __func__
93  << ". Error: " << e.what();
94  }
95 }
96 
97 bool
98 Shard::init(Scheduler& scheduler, nudb::context& context)
99 {
101  std::string const type{get<std::string>(section, "type", "nudb")};
102  auto const factory{Manager::instance().find(type)};
103  if (!factory)
104  {
105  JLOG(j_.error()) << "shard " << index_ << " failed to find factory for "
106  << type;
107  return false;
108  }
109  section.set("path", dir_.string());
110 
111  std::lock_guard lock{mutex_};
112  if (backend_)
113  {
114  JLOG(j_.error()) << "shard " << index_ << " already initialized";
115  return false;
116  }
117  backend_ = factory->createInstance(
119  section,
121  scheduler,
122  context,
123  j_);
124 
125  return open(lock);
126 }
127 
128 bool
130 {
131  std::lock_guard lock(mutex_);
132  if (!backend_)
133  {
134  JLOG(j_.error()) << "shard " << index_ << " not initialized";
135  return false;
136  }
137 
138  return backend_->isOpen();
139 }
140 
141 bool
143 {
144  // Keep database open if being acquired or finalized
145  if (state_ != final)
146  return false;
147 
148  std::lock_guard lock(mutex_);
149 
150  // Keep database open if in use
151  if (backendCount_ > 0)
152  return false;
153 
154  if (!backend_)
155  {
156  JLOG(j_.error()) << "shard " << index_ << " not initialized";
157  return false;
158  }
159  if (!backend_->isOpen())
160  return false;
161 
162  try
163  {
164  backend_->close();
165  }
166  catch (std::exception const& e)
167  {
168  JLOG(j_.fatal()) << "shard " << index_
169  << ". Exception caught in function " << __func__
170  << ". Error: " << e.what();
171  return false;
172  }
173 
174  lgrSQLiteDB_.reset();
175  txSQLiteDB_.reset();
176  acquireInfo_.reset();
177 
178  // Reset caches to reduce memory use
181 
182  return true;
183 }
184 
185 boost::optional<std::uint32_t>
187 {
188  if (state_ != acquire)
189  {
190  JLOG(j_.warn()) << "shard " << index_
191  << " prepare called when not acquiring";
192  return boost::none;
193  }
194 
195  std::lock_guard lock(mutex_);
196  if (!acquireInfo_)
197  {
198  JLOG(j_.error()) << "shard " << index_
199  << " missing acquire SQLite database";
200  return boost::none;
201  }
202 
203  if (acquireInfo_->storedSeqs.empty())
204  return lastSeq_;
205  return prevMissing(acquireInfo_->storedSeqs, 1 + lastSeq_, firstSeq_);
206 }
207 
208 bool
210 {
211  if (state_ != acquire)
212  {
213  // The import node store case is an exception
214  if (nodeObject->getHash() != finalKey)
215  {
216  // Ignore residual calls from InboundLedgers
217  JLOG(j_.trace()) << "shard " << index_ << " not acquiring";
218  return false;
219  }
220  }
221 
222  auto const scopedCount{makeBackendCount()};
223  if (!scopedCount)
224  return false;
225 
226  try
227  {
228  backend_->store(nodeObject);
229  }
230  catch (std::exception const& e)
231  {
232  JLOG(j_.fatal()) << "shard " << index_
233  << ". Exception caught in function " << __func__
234  << ". Error: " << e.what();
235  return false;
236  }
237 
238  return true;
239 }
240 
242 Shard::fetchNodeObject(uint256 const& hash, FetchReport& fetchReport)
243 {
244  auto const scopedCount{makeBackendCount()};
245  if (!scopedCount)
246  return nullptr;
247 
248  std::shared_ptr<NodeObject> nodeObject;
249 
250  // Try the backend
251  Status status;
252  try
253  {
254  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;
295  if (state_ != acquire)
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  backend_->storeBatch(batch);
337  }
338  catch (std::exception const& e)
339  {
340  fail(
341  std::string(". Exception caught in function ") + __func__ +
342  ". Error: " + e.what());
343  return false;
344  }
345 
346  result.count += batch.size();
347  result.size += sz;
348  batch.clear();
349  return true;
350  };
351 
352  // Store ledger header
353  {
354  Serializer s(sizeof(std::uint32_t) + sizeof(LedgerInfo));
356  addRaw(srcLedger->info(), s);
357  auto nodeObject = NodeObject::createObject(
358  hotLEDGER, std::move(s.modData()), srcLedger->info().hash);
359  batch.emplace_back(std::move(nodeObject));
360  }
361 
362  bool error = false;
363  auto visit = [&](SHAMapTreeNode const& node) {
364  if (!stop_)
365  {
366  if (auto nodeObject = srcDB.fetchNodeObject(
367  node.getHash().as_uint256(), srcLedger->info().seq))
368  {
369  batch.emplace_back(std::move(nodeObject));
370  if (batch.size() < batchWritePreallocationSize || storeBatch())
371  return true;
372  }
373  }
374 
375  error = true;
376  return false;
377  };
378 
379  // Store the state map
380  if (srcLedger->stateMap().getHash().isNonZero())
381  {
382  if (!srcLedger->stateMap().isValid())
383  return fail("Invalid state map");
384 
385  if (next && next->info().parentHash == srcLedger->info().hash)
386  {
387  auto have = next->stateMap().snapShot(false);
388  srcLedger->stateMap().snapShot(false)->visitDifferences(
389  &(*have), visit);
390  }
391  else
392  srcLedger->stateMap().snapShot(false)->visitNodes(visit);
393  if (error)
394  return fail("Failed to store state map");
395  }
396 
397  // Store the transaction map
398  if (srcLedger->info().txHash.isNonZero())
399  {
400  if (!srcLedger->txMap().isValid())
401  return fail("Invalid transaction map");
402 
403  srcLedger->txMap().snapShot(false)->visitNodes(visit);
404  if (error)
405  return fail("Failed to store transaction map");
406  }
407 
408  if (!batch.empty() && !storeBatch())
409  return fail("Failed to store");
410 
411  return result;
412 }
413 
414 bool
416 {
417  if (state_ != acquire)
418  {
419  // Ignore residual calls from InboundLedgers
420  JLOG(j_.trace()) << "shard " << index_ << " not acquiring";
421  return false;
422  }
423 
424  auto const ledgerSeq{ledger->info().seq};
425  if (ledgerSeq < firstSeq_ || ledgerSeq > lastSeq_)
426  {
427  JLOG(j_.error()) << "shard " << index_ << " invalid ledger sequence "
428  << ledgerSeq;
429  return false;
430  }
431 
432  auto const scopedCount{makeBackendCount()};
433  if (!scopedCount)
434  return false;
435 
436  // This lock is used as an optimization to prevent unneeded
437  // calls to storeSQLite before acquireInfo_ is updated
438  std::lock_guard storedLock(storedMutex_);
439 
440  {
441  std::lock_guard lock(mutex_);
442  if (!acquireInfo_)
443  {
444  JLOG(j_.error())
445  << "shard " << index_ << " missing acquire SQLite database";
446  return false;
447  }
448  if (boost::icl::contains(acquireInfo_->storedSeqs, ledgerSeq))
449  {
450  // Ignore redundant calls
451  JLOG(j_.debug()) << "shard " << index_ << " ledger sequence "
452  << ledgerSeq << " already stored";
453  return true;
454  }
455  }
456 
457  if (!storeSQLite(ledger))
458  return false;
459 
460  std::lock_guard lock(mutex_);
461 
462  // Update the acquire database
463  acquireInfo_->storedSeqs.insert(ledgerSeq);
464 
465  try
466  {
467  auto session{acquireInfo_->SQLiteDB->checkoutDb()};
468  soci::blob sociBlob(*session);
469  convert(to_string(acquireInfo_->storedSeqs), sociBlob);
470  if (ledgerSeq == lastSeq_)
471  {
472  // Store shard's last ledger hash
473  auto const sHash{to_string(ledger->info().hash)};
474  *session << "UPDATE Shard "
475  "SET LastLedgerHash = :lastLedgerHash,"
476  "StoredLedgerSeqs = :storedLedgerSeqs "
477  "WHERE ShardIndex = :shardIndex;",
478  soci::use(sHash), soci::use(sociBlob), soci::use(index_);
479  }
480  else
481  {
482  *session << "UPDATE Shard "
483  "SET StoredLedgerSeqs = :storedLedgerSeqs "
484  "WHERE ShardIndex = :shardIndex;",
485  soci::use(sociBlob), soci::use(index_);
486  }
487  }
488  catch (std::exception const& e)
489  {
490  JLOG(j_.fatal()) << "shard " << index_
491  << ". Exception caught in function " << __func__
492  << ". Error: " << e.what();
493  acquireInfo_->storedSeqs.erase(ledgerSeq);
494  return false;
495  }
496 
497  if (boost::icl::length(acquireInfo_->storedSeqs) >= maxLedgers_)
498  state_ = complete;
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;
511  if (state_ != acquire)
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 void
526 {
527  // nothing to do
528 }
529 
530 std::chrono::steady_clock::time_point
532 {
533  std::lock_guard lock(mutex_);
534  return lastAccess_;
535 }
536 
539 {
540  std::lock_guard lock(mutex_);
541  return {fileSz_, fdRequired_};
542 }
543 
546 {
547  auto const scopedCount{makeBackendCount()};
548  if (!scopedCount)
549  return 0;
550  return backend_->getWriteLoad();
551 }
552 
553 bool
555 {
556  std::lock_guard lock(mutex_);
557  return legacy_;
558 }
559 
560 bool
562  bool const writeSQLite,
563  boost::optional<uint256> const& expectedHash)
564 {
565  uint256 hash{0};
566  std::uint32_t ledgerSeq{0};
567  auto fail = [&](std::string const& msg) {
568  JLOG(j_.fatal()) << "shard " << index_ << ". " << msg
569  << (hash.isZero() ? ""
570  : ". Ledger hash " + to_string(hash))
571  << (ledgerSeq == 0 ? ""
572  : ". Ledger sequence " +
573  std::to_string(ledgerSeq));
574  state_ = finalizing;
575  return false;
576  };
577 
578  auto const scopedCount{makeBackendCount()};
579  if (!scopedCount)
580  return false;
581 
582  try
583  {
584  state_ = finalizing;
585 
586  /*
587  TODO MP
588  A lock is required when calling the NuDB verify function. Because
589  this can be a time consuming process, the server may desync.
590  Until this function is modified to work on an open database, we
591  are unable to use it from rippled.
592 
593  // Verify backend integrity
594  backend_->verify();
595  */
596 
597  // Check if a final key has been stored
598  if (std::shared_ptr<NodeObject> nodeObject;
599  backend_->fetch(finalKey.data(), &nodeObject) == Status::ok)
600  {
601  // Check final key's value
602  SerialIter sIt(
603  nodeObject->getData().data(), nodeObject->getData().size());
604  if (sIt.get32() != version)
605  return fail("invalid version");
606 
607  if (sIt.get32() != firstSeq_ || sIt.get32() != lastSeq_)
608  return fail("out of range ledger sequences");
609 
610  if (hash = sIt.get256(); hash.isZero())
611  return fail("invalid last ledger hash");
612  }
613  else
614  {
615  // In the absence of a final key, an acquire SQLite database
616  // must be present in order to validate the shard
617  if (!acquireInfo_)
618  return fail("missing acquire SQLite database");
619 
620  auto session{acquireInfo_->SQLiteDB->checkoutDb()};
621  boost::optional<std::uint32_t> index;
622  boost::optional<std::string> sHash;
623  soci::blob sociBlob(*session);
624  soci::indicator blobPresent;
625  *session << "SELECT ShardIndex, LastLedgerHash, StoredLedgerSeqs "
626  "FROM Shard "
627  "WHERE ShardIndex = :index;",
628  soci::into(index), soci::into(sHash),
629  soci::into(sociBlob, blobPresent), soci::use(index_);
630 
631  if (!index || index != index_)
632  return fail("missing or invalid ShardIndex");
633 
634  if (!sHash)
635  return fail("missing LastLedgerHash");
636 
637  if (!hash.parseHex(*sHash) || hash.isZero())
638  return fail("invalid LastLedgerHash");
639 
640  if (blobPresent != soci::i_ok)
641  return fail("missing StoredLedgerSeqs");
642 
643  std::string s;
644  convert(sociBlob, s);
645 
646  auto& storedSeqs{acquireInfo_->storedSeqs};
647  if (!from_string(storedSeqs, s) ||
648  boost::icl::first(storedSeqs) != firstSeq_ ||
649  boost::icl::last(storedSeqs) != lastSeq_ ||
650  storedSeqs.size() != maxLedgers_)
651  {
652  return fail("invalid StoredLedgerSeqs");
653  }
654  }
655  }
656  catch (std::exception const& e)
657  {
658  return fail(
659  std::string(". Exception caught in function ") + __func__ +
660  ". Error: " + e.what());
661  }
662 
663  // Validate the last ledger hash of a downloaded shard
664  // using a ledger hash obtained from the peer network
665  if (expectedHash && *expectedHash != hash)
666  return fail("invalid last ledger hash");
667 
668  // Validate every ledger stored in the backend
669  Config const& config{app_.config()};
672  auto const lastLedgerHash{hash};
673  auto& shardFamily{*app_.getShardFamily()};
674  auto const fullBelowCache{shardFamily.getFullBelowCache(lastSeq_)};
675  auto const treeNodeCache{shardFamily.getTreeNodeCache(lastSeq_)};
676 
677  // Reset caches to reduce memory usage
678  fullBelowCache->reset();
679  treeNodeCache->reset();
680 
681  // Start with the last ledger in the shard and walk backwards from
682  // child to parent until we reach the first ledger
683  ledgerSeq = lastSeq_;
684  while (ledgerSeq >= firstSeq_)
685  {
686  if (stop_)
687  return false;
688 
689  auto nodeObject{verifyFetch(hash)};
690  if (!nodeObject)
691  return fail("invalid ledger");
692 
693  ledger = std::make_shared<Ledger>(
694  deserializePrefixedHeader(makeSlice(nodeObject->getData())),
695  config,
696  shardFamily);
697  if (ledger->info().seq != ledgerSeq)
698  return fail("invalid ledger sequence");
699  if (ledger->info().hash != hash)
700  return fail("invalid ledger hash");
701 
702  ledger->stateMap().setLedgerSeq(ledgerSeq);
703  ledger->txMap().setLedgerSeq(ledgerSeq);
704  ledger->setImmutable(config);
705  if (!ledger->stateMap().fetchRoot(
706  SHAMapHash{ledger->info().accountHash}, nullptr))
707  {
708  return fail("missing root STATE node");
709  }
710  if (ledger->info().txHash.isNonZero() &&
711  !ledger->txMap().fetchRoot(
712  SHAMapHash{ledger->info().txHash}, nullptr))
713  {
714  return fail("missing root TXN node");
715  }
716 
717  if (!verifyLedger(ledger, next))
718  return fail("failed to validate ledger");
719 
720  if (writeSQLite && !storeSQLite(ledger))
721  return fail("failed storing to SQLite databases");
722 
723  hash = ledger->info().parentHash;
724  next = std::move(ledger);
725  --ledgerSeq;
726 
727  fullBelowCache->reset();
728  treeNodeCache->reset();
729  }
730 
731  JLOG(j_.debug()) << "shard " << index_ << " is valid";
732 
733  /*
734  TODO MP
735  SQLite VACUUM blocks all database access while processing.
736  Depending on the file size, that can take a while. Until we find
737  a non-blocking way of doing this, we cannot enable vacuum as
738  it can desync a server.
739 
740  try
741  {
742  // VACUUM the SQLite databases
743  auto const tmpDir {dir_ / "tmp_vacuum"};
744  create_directory(tmpDir);
745 
746  auto vacuum = [&tmpDir](std::unique_ptr<DatabaseCon>& sqliteDB)
747  {
748  auto session {sqliteDB->checkoutDb()};
749  *session << "PRAGMA synchronous=OFF;";
750  *session << "PRAGMA journal_mode=OFF;";
751  *session << "PRAGMA temp_store_directory='" <<
752  tmpDir.string() << "';";
753  *session << "VACUUM;";
754  };
755  vacuum(lgrSQLiteDB_);
756  vacuum(txSQLiteDB_);
757  remove_all(tmpDir);
758  }
759  catch (std::exception const& e)
760  {
761  return fail(
762  std::string(". Exception caught in function ") + __func__ +
763  ". Error: " + e.what());
764  }
765  */
766 
767  // Store final key's value, may already be stored
768  Serializer s;
769  s.add32(version);
770  s.add32(firstSeq_);
771  s.add32(lastSeq_);
772  s.addBitString(lastLedgerHash);
773  auto nodeObject{
775  try
776  {
777  backend_->store(nodeObject);
778 
779  std::lock_guard lock(mutex_);
780 
781  // Remove the acquire SQLite database
782  if (acquireInfo_)
783  {
784  acquireInfo_.reset();
785  remove_all(dir_ / AcquireShardDBName);
786  }
787 
789  state_ = final;
790 
791  if (!initSQLite(lock))
792  return fail("failed to initialize SQLite databases");
793 
794  setFileStats(lock);
795  }
796  catch (std::exception const& e)
797  {
798  return fail(
799  std::string(". Exception caught in function ") + __func__ +
800  ". Error: " + e.what());
801  }
802 
803  return true;
804 }
805 
806 bool
808 {
809  using namespace boost::filesystem;
810  Config const& config{app_.config()};
811  auto preexist{false};
812  auto fail = [this, &preexist](std::string const& msg) {
813  backend_->close();
814  lgrSQLiteDB_.reset();
815  txSQLiteDB_.reset();
816  acquireInfo_.reset();
817 
818  state_ = acquire;
819 
820  if (!preexist)
821  remove_all(dir_);
822 
823  if (!msg.empty())
824  {
825  JLOG(j_.fatal()) << "shard " << index_ << " " << msg;
826  }
827  return false;
828  };
829  auto createAcquireInfo = [this, &config]() {
830  acquireInfo_ = std::make_unique<AcquireInfo>();
831 
832  DatabaseCon::Setup setup;
833  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
834  setup.standAlone = config.standalone();
835  setup.dataDir = dir_;
836  setup.useGlobalPragma = true;
837 
838  acquireInfo_->SQLiteDB = std::make_unique<DatabaseCon>(
839  setup,
844  state_ = acquire;
845  };
846 
847  try
848  {
849  // Open or create the NuDB key/value store
850  preexist = exists(dir_);
851  backend_->open(!preexist);
852 
853  if (!preexist)
854  {
855  // A new shard
856  createAcquireInfo();
857  acquireInfo_->SQLiteDB->getSession()
858  << "INSERT INTO Shard (ShardIndex) "
859  "VALUES (:shardIndex);",
860  soci::use(index_);
861  }
862  else if (exists(dir_ / AcquireShardDBName))
863  {
864  // A shard being acquired, backend is likely incomplete
865  createAcquireInfo();
866 
867  auto& session{acquireInfo_->SQLiteDB->getSession()};
868  boost::optional<std::uint32_t> index;
869  soci::blob sociBlob(session);
870  soci::indicator blobPresent;
871 
872  session << "SELECT ShardIndex, StoredLedgerSeqs "
873  "FROM Shard "
874  "WHERE ShardIndex = :index;",
875  soci::into(index), soci::into(sociBlob, blobPresent),
876  soci::use(index_);
877 
878  if (!index || index != index_)
879  return fail("invalid acquire SQLite database");
880 
881  if (blobPresent == soci::i_ok)
882  {
883  std::string s;
884  auto& storedSeqs{acquireInfo_->storedSeqs};
885  if (convert(sociBlob, s); !from_string(storedSeqs, s))
886  return fail("invalid StoredLedgerSeqs");
887 
888  if (boost::icl::first(storedSeqs) < firstSeq_ ||
889  boost::icl::last(storedSeqs) > lastSeq_)
890  {
891  return fail("invalid StoredLedgerSeqs");
892  }
893 
894  // Check if backend is complete
895  if (boost::icl::length(storedSeqs) == maxLedgers_)
896  state_ = complete;
897  }
898  }
899  else
900  {
901  // A shard that is final or its backend is complete
902  // and ready to be finalized
903  std::shared_ptr<NodeObject> nodeObject;
904  if (backend_->fetch(finalKey.data(), &nodeObject) != Status::ok)
905  {
906  legacy_ = true;
907  return fail("incompatible, missing backend final key");
908  }
909 
910  // Check final key's value
911  SerialIter sIt(
912  nodeObject->getData().data(), nodeObject->getData().size());
913  if (sIt.get32() != version)
914  return fail("invalid version");
915 
916  if (sIt.get32() != firstSeq_ || sIt.get32() != lastSeq_)
917  return fail("out of range ledger sequences");
918 
919  if (sIt.get256().isZero())
920  return fail("invalid last ledger hash");
921 
922  if (exists(dir_ / LgrDBName) && exists(dir_ / TxDBName))
923  {
925  state_ = final;
926  }
927  else
928  state_ = complete;
929  }
930  }
931  catch (std::exception const& e)
932  {
933  return fail(
934  std::string(". Exception caught in function ") + __func__ +
935  ". Error: " + e.what());
936  }
937 
938  if (!initSQLite(lock))
939  return fail({});
940 
941  setFileStats(lock);
942  return true;
943 }
944 
945 bool
947 {
948  Config const& config{app_.config()};
949  DatabaseCon::Setup const setup = [&]() {
950  DatabaseCon::Setup setup;
951  setup.startUp = config.standalone() ? config.LOAD : config.START_UP;
952  setup.standAlone = config.standalone();
953  setup.dataDir = dir_;
954  setup.useGlobalPragma = (state_ != complete);
955  return setup;
956  }();
957 
958  try
959  {
960  if (lgrSQLiteDB_)
961  lgrSQLiteDB_.reset();
962 
963  if (txSQLiteDB_)
964  txSQLiteDB_.reset();
965 
966  if (state_ == final)
967  {
968  lgrSQLiteDB_ = std::make_unique<DatabaseCon>(
970  lgrSQLiteDB_->getSession() << boost::str(
971  boost::format("PRAGMA cache_size=-%d;") %
972  kilobytes(
973  config.getValueFor(SizedItem::lgrDBCache, boost::none)));
974 
975  txSQLiteDB_ = std::make_unique<DatabaseCon>(
977  txSQLiteDB_->getSession() << boost::str(
978  boost::format("PRAGMA cache_size=-%d;") %
979  kilobytes(
980  config.getValueFor(SizedItem::txnDBCache, boost::none)));
981  }
982  else
983  {
984  // Non final shards use a Write Ahead Log for performance
985  lgrSQLiteDB_ = std::make_unique<DatabaseCon>(
986  setup,
987  LgrDBName,
988  LgrDBPragma,
989  LgrDBInit,
991  &app_.getJobQueue(), &app_.logs()});
992  lgrSQLiteDB_->getSession() << boost::str(
993  boost::format("PRAGMA cache_size=-%d;") %
994  kilobytes(config.getValueFor(SizedItem::lgrDBCache)));
995 
996  txSQLiteDB_ = std::make_unique<DatabaseCon>(
997  setup,
998  TxDBName,
999  TxDBPragma,
1000  TxDBInit,
1002  &app_.getJobQueue(), &app_.logs()});
1003  txSQLiteDB_->getSession() << boost::str(
1004  boost::format("PRAGMA cache_size=-%d;") %
1005  kilobytes(config.getValueFor(SizedItem::txnDBCache)));
1006  }
1007  }
1008  catch (std::exception const& e)
1009  {
1010  JLOG(j_.fatal()) << "shard " << index_
1011  << ". Exception caught in function " << __func__
1012  << ". Error: " << e.what();
1013  return false;
1014  }
1015 
1016  return true;
1017 }
1018 
1019 bool
1021 {
1022  if (stop_)
1023  return false;
1024 
1025  auto const ledgerSeq{ledger->info().seq};
1026 
1027  try
1028  {
1029  // Update the transactions database
1030  {
1031  auto session{txSQLiteDB_->checkoutDb()};
1032  soci::transaction tr(*session);
1033 
1034  *session << "DELETE FROM Transactions "
1035  "WHERE LedgerSeq = :seq;",
1036  soci::use(ledgerSeq);
1037  *session << "DELETE FROM AccountTransactions "
1038  "WHERE LedgerSeq = :seq;",
1039  soci::use(ledgerSeq);
1040 
1041  if (ledger->info().txHash.isNonZero())
1042  {
1043  auto const sSeq{std::to_string(ledgerSeq)};
1044  if (!ledger->txMap().isValid())
1045  {
1046  JLOG(j_.error()) << "shard " << index_
1047  << " has an invalid transaction map"
1048  << " on sequence " << sSeq;
1049  return false;
1050  }
1051 
1052  for (auto const& item : ledger->txs)
1053  {
1054  if (stop_)
1055  return false;
1056 
1057  auto const txID{item.first->getTransactionID()};
1058  auto const sTxID{to_string(txID)};
1059  auto const txMeta{std::make_shared<TxMeta>(
1060  txID, ledger->seq(), *item.second)};
1061 
1062  *session << "DELETE FROM AccountTransactions "
1063  "WHERE TransID = :txID;",
1064  soci::use(sTxID);
1065 
1066  auto const& accounts = txMeta->getAffectedAccounts(j_);
1067  if (!accounts.empty())
1068  {
1069  auto const sTxnSeq{std::to_string(txMeta->getIndex())};
1070  auto const s{boost::str(
1071  boost::format("('%s','%s',%s,%s)") % sTxID % "%s" %
1072  sSeq % sTxnSeq)};
1073  std::string sql;
1074  sql.reserve((accounts.size() + 1) * 128);
1075  sql =
1076  "INSERT INTO AccountTransactions "
1077  "(TransID, Account, LedgerSeq, TxnSeq) VALUES ";
1078  sql += boost::algorithm::join(
1079  accounts |
1080  boost::adaptors::transformed(
1081  [&](AccountID const& accountID) {
1082  return boost::str(
1083  boost::format(s) %
1084  ripple::toBase58(accountID));
1085  }),
1086  ",");
1087  sql += ';';
1088  *session << sql;
1089 
1090  JLOG(j_.trace()) << "shard " << index_
1091  << " account transaction: " << sql;
1092  }
1093  else
1094  {
1095  JLOG(j_.warn())
1096  << "shard " << index_ << " transaction in ledger "
1097  << sSeq << " affects no accounts";
1098  }
1099 
1100  Serializer s;
1101  item.second->add(s);
1102  *session
1104  item.first->getMetaSQL(
1105  ledgerSeq, sqlBlobLiteral(s.modData())) +
1106  ';');
1107  }
1108  }
1109 
1110  tr.commit();
1111  }
1112 
1113  // Update the ledger database
1114  {
1115  auto const sParentHash{to_string(ledger->info().parentHash)};
1116  auto const sDrops{to_string(ledger->info().drops)};
1117  auto const sAccountHash{to_string(ledger->info().accountHash)};
1118  auto const sTxHash{to_string(ledger->info().txHash)};
1119  auto const sHash{to_string(ledger->info().hash)};
1120 
1121  auto session{lgrSQLiteDB_->checkoutDb()};
1122  soci::transaction tr(*session);
1123 
1124  *session << "DELETE FROM Ledgers "
1125  "WHERE LedgerSeq = :seq;",
1126  soci::use(ledgerSeq);
1127  *session
1128  << "INSERT OR REPLACE INTO Ledgers ("
1129  "LedgerHash, LedgerSeq, PrevHash, TotalCoins, ClosingTime,"
1130  "PrevClosingTime, CloseTimeRes, CloseFlags, AccountSetHash,"
1131  "TransSetHash)"
1132  "VALUES ("
1133  ":ledgerHash, :ledgerSeq, :prevHash, :totalCoins,"
1134  ":closingTime, :prevClosingTime, :closeTimeRes,"
1135  ":closeFlags, :accountSetHash, :transSetHash);",
1136  soci::use(sHash), soci::use(ledgerSeq), soci::use(sParentHash),
1137  soci::use(sDrops),
1138  soci::use(ledger->info().closeTime.time_since_epoch().count()),
1139  soci::use(
1140  ledger->info().parentCloseTime.time_since_epoch().count()),
1141  soci::use(ledger->info().closeTimeResolution.count()),
1142  soci::use(ledger->info().closeFlags), soci::use(sAccountHash),
1143  soci::use(sTxHash);
1144 
1145  tr.commit();
1146  }
1147  }
1148  catch (std::exception const& e)
1149  {
1150  JLOG(j_.fatal()) << "shard " << index_
1151  << ". Exception caught in function " << __func__
1152  << ". Error: " << e.what();
1153  return false;
1154  }
1155 
1156  return true;
1157 }
1158 
1159 void
1161 {
1162  fileSz_ = 0;
1163  fdRequired_ = 0;
1164  try
1165  {
1166  using namespace boost::filesystem;
1167  for (auto const& d : directory_iterator(dir_))
1168  {
1169  if (is_regular_file(d))
1170  {
1171  fileSz_ += file_size(d);
1172  ++fdRequired_;
1173  }
1174  }
1175  }
1176  catch (std::exception const& e)
1177  {
1178  JLOG(j_.fatal()) << "shard " << index_
1179  << ". Exception caught in function " << __func__
1180  << ". Error: " << e.what();
1181  }
1182 }
1183 
1184 bool
1186  std::shared_ptr<Ledger const> const& ledger,
1187  std::shared_ptr<Ledger const> const& next) const
1188 {
1189  auto fail = [j = j_, index = index_, &ledger](std::string const& msg) {
1190  JLOG(j.error()) << "shard " << index << ". " << msg
1191  << (ledger->info().hash.isZero() ? ""
1192  : ". Ledger hash " +
1193  to_string(ledger->info().hash))
1194  << (ledger->info().seq == 0 ? ""
1195  : ". Ledger sequence " +
1196  std::to_string(ledger->info().seq));
1197  return false;
1198  };
1199 
1200  if (ledger->info().hash.isZero())
1201  return fail("Invalid ledger hash");
1202  if (ledger->info().accountHash.isZero())
1203  return fail("Invalid ledger account hash");
1204 
1205  bool error{false};
1206  auto visit = [this, &error](SHAMapTreeNode const& node) {
1207  if (stop_)
1208  return false;
1209  if (!verifyFetch(node.getHash().as_uint256()))
1210  error = true;
1211  return !error;
1212  };
1213 
1214  // Validate the state map
1215  if (ledger->stateMap().getHash().isNonZero())
1216  {
1217  if (!ledger->stateMap().isValid())
1218  return fail("Invalid state map");
1219 
1220  try
1221  {
1222  if (next && next->info().parentHash == ledger->info().hash)
1223  ledger->stateMap().visitDifferences(&next->stateMap(), visit);
1224  else
1225  ledger->stateMap().visitNodes(visit);
1226  }
1227  catch (std::exception const& e)
1228  {
1229  return fail(
1230  std::string(". Exception caught in function ") + __func__ +
1231  ". Error: " + e.what());
1232  }
1233 
1234  if (stop_)
1235  return false;
1236  if (error)
1237  return fail("Invalid state map");
1238  }
1239 
1240  // Validate the transaction map
1241  if (ledger->info().txHash.isNonZero())
1242  {
1243  if (!ledger->txMap().isValid())
1244  return fail("Invalid transaction map");
1245 
1246  try
1247  {
1248  ledger->txMap().visitNodes(visit);
1249  }
1250  catch (std::exception const& e)
1251  {
1252  return fail(
1253  std::string(". Exception caught in function ") + __func__ +
1254  ". Error: " + e.what());
1255  }
1256  if (stop_)
1257  return false;
1258  if (error)
1259  return fail("Invalid transaction map");
1260  }
1261 
1262  return true;
1263 }
1264 
1266 Shard::verifyFetch(uint256 const& hash) const
1267 {
1268  std::shared_ptr<NodeObject> nodeObject;
1269  auto fail =
1270  [j = j_, index = index_, &hash, &nodeObject](std::string const& msg) {
1271  JLOG(j.error()) << "shard " << index << ". " << msg
1272  << ". Node object hash " << to_string(hash);
1273  nodeObject.reset();
1274  return nodeObject;
1275  };
1276 
1277  try
1278  {
1279  switch (backend_->fetch(hash.data(), &nodeObject))
1280  {
1281  case ok:
1282  // Verify that the hash of node object matches the payload
1283  if (nodeObject->getHash() !=
1284  sha512Half(makeSlice(nodeObject->getData())))
1285  return fail("Node object hash does not match payload");
1286  return nodeObject;
1287  case notFound:
1288  return fail("Missing node object");
1289  case dataCorrupt:
1290  return fail("Corrupt node object");
1291  default:
1292  return fail("Unknown error");
1293  }
1294  }
1295  catch (std::exception const& e)
1296  {
1297  return fail(
1298  std::string(". Exception caught in function ") + __func__ +
1299  ". Error: " + e.what());
1300  }
1301 }
1302 
1305 {
1306  if (stop_)
1307  return {nullptr};
1308 
1309  std::lock_guard lock(mutex_);
1310  if (!backend_)
1311  {
1312  JLOG(j_.error()) << "shard " << index_ << " not initialized";
1313  return {nullptr};
1314  }
1315  if (!backend_->isOpen())
1316  {
1317  if (!open(lock))
1318  return {nullptr};
1319  }
1320  else if (state_ == final)
1322 
1323  return Shard::Count(&backendCount_);
1324 }
1325 
1326 } // namespace NodeStore
1327 } // namespace ripple
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::AcquireShardDBPragma
constexpr std::array< char const *, 1 > AcquireShardDBPragma
Definition: DBInit.h:120
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
ripple::NodeStore::Shard::dir_
const boost::filesystem::path dir_
Definition: Shard.h:271
ripple::Application
Definition: Application.h:97
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::NodeStore::Shard::mutex_
std::mutex mutex_
Definition: Shard.h:254
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:52
ripple::NodeStore::Shard::acquire
static constexpr State acquire
Definition: Shard.h:60
std::string
STL class.
std::shared_ptr< NodeObject >
ripple::NodeStore::Shard::lgrSQLiteDB_
std::unique_ptr< DatabaseCon > lgrSQLiteDB_
Definition: Shard.h:285
ripple::NodeStore::Shard::removeOnDestroy_
std::atomic< bool > removeOnDestroy_
Definition: Shard.h:304
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: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::finalizing
static constexpr State finalizing
Definition: Shard.h:62
ripple::NodeStore::ok
@ ok
Definition: nodestore/Types.h:45
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:176
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:45
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:156
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::Config::getValueFor
int getValueFor(SizedItem item, boost::optional< std::size_t > node=boost::none) const
Retrieve the default value for the item at the specified node size.
Definition: Config.cpp:812
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::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:29
ripple::DatabaseCon::CheckpointerSetup
Definition: DatabaseCon.h:106
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:538
std::lock_guard
STL class.
ripple::kilobytes
constexpr auto kilobytes(T value) noexcept
Definition: ByteUtilities.h:27
ripple::AcquireShardDBInit
constexpr std::array< char const *, 1 > AcquireShardDBInit
Definition: DBInit.h:123
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:129
ripple::addRaw
void addRaw(LedgerInfo const &info, Serializer &s)
Definition: View.cpp:43
ripple::DatabaseCon::Setup::dataDir
boost::filesystem::path dataDir
Definition: DatabaseCon.h:90
ripple::STTx::getMetaSQLInsertReplaceHeader
static std::string const & getMetaSQLInsertReplaceHeader()
Definition: STTx.cpp:232
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
ripple::Family::getFullBelowCache
virtual std::shared_ptr< FullBelowCache > getFullBelowCache(std::uint32_t ledgerSeq)=0
Return a pointer to the Family Full Below Cache.
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:45
ripple::NodeStore::Shard::finalKey
static const uint256 finalKey
Definition: Shard.h:205
ripple::NodeStore::Shard::lastSeq_
const std::uint32_t lastSeq_
Definition: Shard.h:264
ripple::NodeStore::Shard::storedMutex_
std::mutex storedMutex_
Definition: Shard.h:255
ripple::NodeStore::Shard::complete
static constexpr State complete
Definition: Shard.h:61
ripple::Family::db
virtual NodeStore::Database & db()=0
ripple::NodeStore::Shard::verifyFetch
std::shared_ptr< NodeObject > verifyFetch(uint256 const &hash) const
Definition: Shard.cpp:1266
std::shared_ptr::reset
T reset(T... args)
ripple::base_uint::data
pointer data()
Definition: base_uint.h:113
ripple::LgrDBInit
constexpr std::array< char const *, 5 > LgrDBInit
Definition: DBInit.h:48
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:47
ripple::NodeStore::Shard::tryClose
bool tryClose()
Try to close databases if not in use.
Definition: Shard.cpp:142
ripple::NodeStore::Shard::StoreLedgerResult::size
std::uint64_t size
Definition: Shard.h:126
ripple::NodeStore::Shard::backend_
std::unique_ptr< Backend > backend_
Definition: Shard.h:280
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:554
ripple::uint256
base_uint< 256 > uint256
Definition: base_uint.h:457
ripple::deserializePrefixedHeader
LedgerInfo deserializePrefixedHeader(Slice data)
Deserialize a ledger header (prefixed with 4 bytes) from a byte array.
Definition: InboundLedger.cpp:298
ripple::NodeStore::Shard::version
static constexpr std::uint32_t version
Definition: Shard.h:200
ripple::NodeStore::Shard::storeSQLite
bool storeSQLite(std::shared_ptr< Ledger const > const &ledger)
Definition: Shard.cpp:1020
ripple::NodeStore::notFound
@ notFound
Definition: nodestore/Types.h:46
ripple::TxDBName
constexpr auto TxDBName
Definition: DBInit.h:73
ripple::base_uint< 256 >
ripple::DatabaseCon::Setup::useGlobalPragma
bool useGlobalPragma
Definition: DatabaseCon.h:93
ripple::NodeStore::Shard::j_
const beast::Journal j_
Definition: Shard.h:253
ripple::NodeStore::Shard::finalize
bool finalize(bool const writeSQLite, boost::optional< uint256 > const &referenceHash)
Finalize shard by walking its ledgers and verifying each Merkle tree.
Definition: Shard.cpp:561
ripple::NodeStore::Shard::containsLedger
bool containsLedger(std::uint32_t ledgerSeq) const
Definition: Shard.cpp:507
ripple::NodeStore::Shard::fileSz_
std::uint64_t fileSz_
Definition: Shard.h:274
ripple::NodeStore::Shard::StoreLedgerResult::error
bool error
Definition: Shard.h:127
ripple::DatabaseCon::Setup::standAlone
bool standAlone
Definition: DatabaseCon.h:89
ripple::NodeStore::Shard::storeNodeObject
bool storeNodeObject(std::shared_ptr< NodeObject > const &nodeObject)
Definition: Shard.cpp:209
ripple::base_uint::isZero
bool isZero() const
Definition: base_uint.h:439
ripple::LgrDBPragma
constexpr std::array< char const *, 1 > LgrDBPragma
Definition: DBInit.h:45
ripple::NodeStore::Shard::sweep
void sweep()
Definition: Shard.cpp:525
ripple::SerialIter::get256
uint256 get256()
Definition: Serializer.h:374
ripple::Config
Definition: Config.h:67
ripple::NodeStore::Shard::initSQLite
bool initSQLite(std::lock_guard< std::mutex > const &)
Definition: Shard.cpp:946
ripple::Application::config
virtual Config & config()=0
ripple::NodeStore::Shard::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, FetchReport &fetchReport)
Definition: Shard.cpp:242
ripple::NodeStore::Shard::state_
std::atomic< State > state_
Definition: Shard.h:301
ripple::megabytes
constexpr auto megabytes(T value) noexcept
Definition: ByteUtilities.h:34
ripple::prevMissing
boost::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::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
ripple::SHAMapTreeNode
Definition: SHAMapTreeNode.h:133
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:261
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:268
ripple::SerialIter
Definition: Serializer.h:308
ripple::SizedItem::lgrDBCache
@ lgrDBCache
ripple::NodeStore::Shard::~Shard
~Shard()
Definition: Shard.cpp:63
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::SizedItem::burstSize
@ burstSize
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:123
ripple::SizedItem::txnDBCache
@ txnDBCache
ripple::FinalShardDBPragma
constexpr std::array< char const *, 2 > FinalShardDBPragma
Definition: DBInit.h:134
ripple::NodeStore::Shard::acquireInfo_
std::unique_ptr< AcquireInfo > acquireInfo_
Definition: Shard.h:292
ripple::NodeStore::Shard::app_
Application & app_
Definition: Shard.h:252
ripple::NodeStore::Status
Status
Return codes from Backend operations.
Definition: nodestore/Types.h:44
ripple::Serializer
Definition: Serializer.h:39
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:307
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:1304
ripple::Application::getShardFamily
virtual Family * getShardFamily()=0
ripple::NodeStore::Shard::StoreLedgerResult::count
std::uint64_t count
Definition: Shard.h:125
ripple::NodeStore::Shard::prepare
boost::optional< std::uint32_t > prepare()
Definition: Shard.cpp:186
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::open
bool open(std::lock_guard< std::mutex > const &lock)
Definition: Shard.cpp:807
ripple::TxDBPragma
constexpr std::array TxDBPragma
Definition: DBInit.h:76
ripple::NodeStore::Shard::legacy_
bool legacy_
Definition: Shard.h:296
std::vector::empty
T empty(T... args)
ripple::NodeStore::Shard::fdRequired_
std::uint32_t fdRequired_
Definition: Shard.h:277
ripple::NodeStore::Shard::index
std::uint32_t index() const
Definition: Shard.h:145
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:98
ripple::NodeStore::Shard::verifyLedger
bool verifyLedger(std::shared_ptr< Ledger const > const &ledger, std::shared_ptr< Ledger const > const &next) const
Definition: Shard.cpp:1185
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:1160
ripple::TxDBInit
constexpr std::array< char const *, 8 > TxDBInit
Definition: DBInit.h:84
ripple::NodeStore::Manager::instance
static Manager & instance()
Returns the instance of the manager singleton.
Definition: ManagerImp.cpp:119
ripple::NodeStore::Shard::setLedgerStored
bool setLedgerStored(std::shared_ptr< Ledger const > const &ledger)
Definition: Shard.cpp:415
ripple::NodeStore::Shard
Definition: Shard.h:50
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:378
ripple::NodeStore::Shard::txSQLiteDB_
std::unique_ptr< DatabaseCon > txSQLiteDB_
Definition: Shard.h:288
ripple::NodeStore::Shard::Count
Definition: Shard.h:208
ripple::NodeStore::Shard::index_
const std::uint32_t index_
Definition: Shard.h:258
ripple::NodeStore::Shard::stop_
std::atomic< bool > stop_
Definition: Shard.h:299
ripple::NodeStore::Shard::backendCount_
std::atomic< std::uint32_t > backendCount_
Definition: Shard.h:282
ripple::NodeStore::Shard::getLastUse
std::chrono::steady_clock::time_point getLastUse() const
Definition: Shard.cpp:531
ripple::sqlBlobLiteral
std::string sqlBlobLiteral(Blob const &blob)
Format arbitrary binary data as an SQLite "blob literal".
Definition: StringUtilities.cpp:33
ripple::NodeStore::Shard::getWriteLoad
std::int32_t getWriteLoad()
Definition: Shard.cpp:545
std::exception::what
T what(T... args)
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:138
ripple::LgrDBName
constexpr auto LgrDBName
Definition: DBInit.h:43
std::chrono::steady_clock::now
T now(T... args)