rippled
DatabaseShardImp.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/nodestore/impl/DatabaseShardImp.h>
21 #include <ripple/app/ledger/InboundLedgers.h>
22 #include <ripple/app/ledger/LedgerMaster.h>
23 #include <ripple/app/misc/NetworkOPs.h>
24 #include <ripple/basics/ByteUtilities.h>
25 #include <ripple/basics/chrono.h>
26 #include <ripple/basics/random.h>
27 #include <ripple/core/ConfigSections.h>
28 #include <ripple/nodestore/DummyScheduler.h>
29 #include <ripple/overlay/Overlay.h>
30 #include <ripple/overlay/predicates.h>
31 #include <ripple/protocol/HashPrefix.h>
32 
33 #include <boost/algorithm/string/predicate.hpp>
34 
35 namespace ripple {
36 namespace NodeStore {
37 
39  Application& app,
40  Stoppable& parent,
41  std::string const& name,
42  Scheduler& scheduler,
43  int readThreads,
45  : DatabaseShard(
46  name,
47  parent,
48  scheduler,
49  readThreads,
50  app.config().section(ConfigSection::shardDatabase()),
51  j)
52  , app_(app)
53  , parent_(parent)
54  , taskQueue_(std::make_unique<TaskQueue>(*this))
55  , earliestShardIndex_(seqToShardIndex(earliestLedgerSeq()))
56  , avgShardFileSz_(ledgersPerShard_ * kilobytes(192))
57 {
58 }
59 
61 {
62  onStop();
63 }
64 
65 bool
67 {
68  {
69  std::lock_guard lock(mutex_);
70  if (init_)
71  {
72  JLOG(j_.error()) << "already initialized";
73  return false;
74  }
75 
76  if (!initConfig(lock))
77  {
78  JLOG(j_.error()) << "invalid configuration file settings";
79  return false;
80  }
81 
82  try
83  {
84  using namespace boost::filesystem;
85  if (exists(dir_))
86  {
87  if (!is_directory(dir_))
88  {
89  JLOG(j_.error()) << "'path' must be a directory";
90  return false;
91  }
92  }
93  else
94  create_directories(dir_);
95 
96  ctx_ = std::make_unique<nudb::context>();
97  ctx_->start();
98 
99  // Find shards
100  for (auto const& d : directory_iterator(dir_))
101  {
102  if (!is_directory(d))
103  continue;
104 
105  // Check shard directory name is numeric
106  auto dirName = d.path().stem().string();
107  if (!std::all_of(
108  dirName.begin(),
109  dirName.end(),
110  [](auto c) {
111  return ::isdigit(static_cast<unsigned char>(c));
112  }))
113  {
114  continue;
115  }
116 
117  auto const shardIndex {std::stoul(dirName)};
118  if (shardIndex < earliestShardIndex())
119  {
120  JLOG(j_.error()) <<
121  "shard " << shardIndex <<
122  " comes before earliest shard index " <<
124  return false;
125  }
126 
127  auto const shardDir {dir_ / std::to_string(shardIndex)};
128 
129  // Check if a previous import failed
130  if (is_regular_file(shardDir / importMarker_))
131  {
132  JLOG(j_.warn()) <<
133  "shard " << shardIndex <<
134  " previously failed import, removing";
135  remove_all(shardDir);
136  continue;
137  }
138 
139  auto shard {std::make_unique<Shard>(
140  app_,
141  *this,
142  shardIndex,
143  j_)};
144  if (!shard->open(scheduler_, *ctx_))
145  {
146  if (!shard->isLegacy())
147  return false;
148 
149  // Remove legacy shard
150  shard->removeOnDestroy();
151  JLOG(j_.warn()) <<
152  "shard " << shardIndex <<
153  " removed, legacy shard";
154  continue;
155  }
156 
157  if (shard->isFinal())
158  {
159  shards_.emplace(
160  shardIndex,
161  ShardInfo(std::move(shard), ShardInfo::State::final));
162  }
163  else if (shard->isBackendComplete())
164  {
165  auto const result {shards_.emplace(
166  shardIndex,
167  ShardInfo(std::move(shard), ShardInfo::State::none))};
168  finalizeShard(result.first->second, true, lock);
169  }
170  else
171  {
172  if (acquireIndex_ != 0)
173  {
174  JLOG(j_.error()) <<
175  "more than one shard being acquired";
176  return false;
177  }
178 
179  shards_.emplace(
180  shardIndex,
181  ShardInfo(std::move(shard), ShardInfo::State::acquire));
182  acquireIndex_ = shardIndex;
183  }
184  }
185  }
186  catch (std::exception const& e)
187  {
188  JLOG(j_.error()) <<
189  "exception " << e.what() << " in function " << __func__;
190  }
191 
192  updateStatus(lock);
194  init_ = true;
195  }
196 
197  setFileStats();
198  return true;
199 }
200 
201 boost::optional<std::uint32_t>
203 {
204  boost::optional<std::uint32_t> shardIndex;
205 
206  {
207  std::lock_guard lock(mutex_);
208  assert(init_);
209 
210  if (acquireIndex_ != 0)
211  {
212  if (auto it {shards_.find(acquireIndex_)}; it != shards_.end())
213  return it->second.shard->prepare();
214  assert(false);
215  return boost::none;
216  }
217 
218  if (!canAdd_)
219  return boost::none;
220 
221  // Check available storage space
223  {
224  JLOG(j_.debug()) << "maximum storage size reached";
225  canAdd_ = false;
226  return boost::none;
227  }
228  if (avgShardFileSz_ > available())
229  {
230  JLOG(j_.error()) << "insufficient storage space available";
231  canAdd_ = false;
232  return boost::none;
233  }
234 
235  shardIndex = findAcquireIndex(validLedgerSeq, lock);
236  }
237 
238  if (!shardIndex)
239  {
240  JLOG(j_.debug()) << "no new shards to add";
241  {
242  std::lock_guard lock(mutex_);
243  canAdd_ = false;
244  }
245  return boost::none;
246  }
247 
248  auto shard {std::make_unique<Shard>(app_, *this, *shardIndex, j_)};
249  if (!shard->open(scheduler_, *ctx_))
250  return boost::none;
251 
252  auto const seq {shard->prepare()};
253  {
254  std::lock_guard lock(mutex_);
255  shards_.emplace(
256  *shardIndex,
257  ShardInfo(std::move(shard), ShardInfo::State::acquire));
258  acquireIndex_ = *shardIndex;
259  }
260  return seq;
261 }
262 
263 bool
265 {
266  auto fail = [j = j_, shardIndex](std::string const& msg)
267  {
268  JLOG(j.error()) << "shard " << shardIndex << " " << msg;
269  return false;
270  };
271  std::lock_guard lock(mutex_);
272  assert(init_);
273 
274  if (!canAdd_)
275  return fail("cannot be stored at this time");
276 
277  if (shardIndex < earliestShardIndex())
278  {
279  return fail("comes before earliest shard index " +
281  }
282 
283  // If we are synced to the network, check if the shard index
284  // is greater or equal to the current shard.
285  auto seqCheck = [&](std::uint32_t seq)
286  {
287  // seq will be greater than zero if valid
288  if (seq > earliestLedgerSeq() && shardIndex >= seqToShardIndex(seq))
289  return fail("has an invalid index");
290  return true;
291  };
292  if (!seqCheck(app_.getLedgerMaster().getValidLedgerIndex()) ||
294  {
295  return false;
296  }
297 
298  if (shards_.find(shardIndex) != shards_.end())
299  {
300  JLOG(j_.debug()) <<
301  "shard " << shardIndex <<
302  " is already stored or queued for import";
303  return false;
304  }
305 
306  // Check available storage space
308  return fail("maximum storage size reached");
309  if (avgShardFileSz_ > available())
310  return fail("insufficient storage space available");
311 
312  shards_.emplace(shardIndex, ShardInfo(nullptr, ShardInfo::State::import));
313  return true;
314 }
315 
316 void
318 {
319  std::lock_guard lock(mutex_);
320  assert(init_);
321 
322  if (auto const it {shards_.find(shardIndex)};
323  it != shards_.end() && it->second.state == ShardInfo::State::import)
324  {
325  shards_.erase(it);
326  }
327 }
328 
331 {
333  {
334  std::lock_guard lock(mutex_);
335  assert(init_);
336 
337  for (auto const& e : shards_)
338  if (e.second.state == ShardInfo::State::import)
339  rs.insert(e.first);
340  }
341 
342  if (rs.empty())
343  return {};
344 
345  return to_string(rs);
346 };
347 
348 bool
350  std::uint32_t shardIndex,
351  boost::filesystem::path const& srcDir)
352 {
353  using namespace boost::filesystem;
354  try
355  {
356  if (!is_directory(srcDir) || is_empty(srcDir))
357  {
358  JLOG(j_.error()) <<
359  "invalid source directory " << srcDir.string();
360  return false;
361  }
362  }
363  catch (std::exception const& e)
364  {
365  JLOG(j_.error()) <<
366  "exception " << e.what() << " in function " << __func__;
367  return false;
368  }
369 
370  auto renameDir = [&](path const& src, path const& dst)
371  {
372  try
373  {
374  rename(src, dst);
375  }
376  catch (std::exception const& e)
377  {
378  JLOG(j_.error()) <<
379  "exception " << e.what() << " in function " << __func__;
380  return false;
381  }
382  return true;
383  };
384 
385  path dstDir;
386  {
387  std::lock_guard lock(mutex_);
388  assert(init_);
389 
390  // Check shard is prepared
391  if (auto const it {shards_.find(shardIndex)};
392  it == shards_.end() ||
393  it->second.shard ||
394  it->second.state != ShardInfo::State::import)
395  {
396  JLOG(j_.error()) <<
397  "shard " << shardIndex << " failed to import";
398  return false;
399  }
400 
401  dstDir = dir_ / std::to_string(shardIndex);
402  }
403 
404  // Rename source directory to the shard database directory
405  if (!renameDir(srcDir, dstDir))
406  return false;
407 
408  // Create the new shard
409  auto shard {std::make_unique<Shard>(app_, *this, shardIndex, j_)};
410  if (!shard->open(scheduler_, *ctx_) || !shard->isBackendComplete())
411  {
412  JLOG(j_.error()) <<
413  "shard " << shardIndex << " failed to import";
414  shard.reset();
415  renameDir(dstDir, srcDir);
416  return false;
417  }
418 
419  std::lock_guard lock(mutex_);
420  auto const it {shards_.find(shardIndex)};
421  if (it == shards_.end() ||
422  it->second.shard ||
423  it->second.state != ShardInfo::State::import)
424  {
425  JLOG(j_.error()) <<
426  "shard " << shardIndex << " failed to import";
427  return false;
428  }
429 
430  it->second.shard = std::move(shard);
431  finalizeShard(it->second, true, lock);
432  return true;
433 }
434 
437 {
438  auto const shardIndex {seqToShardIndex(seq)};
439  {
440  ShardInfo shardInfo;
441  {
442  std::lock_guard lock(mutex_);
443  assert(init_);
444 
445  if (auto const it {shards_.find(shardIndex)}; it != shards_.end())
446  shardInfo = it->second;
447  else
448  return {};
449  }
450 
451  // Check if the ledger is stored in a final shard
452  // or in the shard being acquired
453  switch (shardInfo.state)
454  {
456  break;
458  if (shardInfo.shard->containsLedger(seq))
459  break;
460  [[fallthrough]];
461  default:
462  return {};
463  }
464  }
465 
466  auto nObj {fetch(hash, seq)};
467  if (!nObj)
468  return {};
469 
470  auto fail = [this, seq](std::string const& msg)-> std::shared_ptr<Ledger>
471  {
472  JLOG(j_.error()) << "shard " << seqToShardIndex(seq) << " " << msg;
473  return {};
474  };
475 
476  auto ledger {std::make_shared<Ledger>(
477  InboundLedger::deserializeHeader(makeSlice(nObj->getData()), true),
478  app_.config(),
479  *app_.shardFamily())};
480 
481  if (ledger->info().seq != seq)
482  {
483  return fail("encountered invalid ledger sequence " +
484  std::to_string(seq));
485  }
486  if (ledger->info().hash != hash)
487  {
488  return fail("encountered invalid ledger hash " +
489  to_string(hash) + " on sequence " + std::to_string(seq));
490  }
491 
492  ledger->setFull();
493  if (!ledger->stateMap().fetchRoot(
494  SHAMapHash {ledger->info().accountHash}, nullptr))
495  {
496  return fail("is missing root STATE node on hash " +
497  to_string(hash) + " on sequence " + std::to_string(seq));
498  }
499 
500  if (ledger->info().txHash.isNonZero())
501  {
502  if (!ledger->txMap().fetchRoot(
503  SHAMapHash {ledger->info().txHash}, nullptr))
504  {
505  return fail("is missing root TXN node on hash " +
506  to_string(hash) + " on sequence " + std::to_string(seq));
507  }
508  }
509  return ledger;
510 }
511 
512 void
514 {
515  if (ledger->info().hash.isZero())
516  {
517  JLOG(j_.error()) <<
518  "zero ledger hash for ledger sequence " << ledger->info().seq;
519  return;
520  }
521  if (ledger->info().accountHash.isZero())
522  {
523  JLOG(j_.error()) <<
524  "zero account hash for ledger sequence " << ledger->info().seq;
525  return;
526  }
527  if (ledger->stateMap().getHash().isNonZero() &&
528  !ledger->stateMap().isValid())
529  {
530  JLOG(j_.error()) <<
531  "invalid state map for ledger sequence " << ledger->info().seq;
532  return;
533  }
534  if (ledger->info().txHash.isNonZero() && !ledger->txMap().isValid())
535  {
536  JLOG(j_.error()) <<
537  "invalid transaction map for ledger sequence " <<
538  ledger->info().seq;
539  return;
540  }
541 
542  auto const shardIndex {seqToShardIndex(ledger->info().seq)};
544  {
545  std::lock_guard lock(mutex_);
546  assert(init_);
547 
548  if (shardIndex != acquireIndex_)
549  {
550  JLOG(j_.trace()) <<
551  "shard " << shardIndex << " is not being acquired";
552  return;
553  }
554 
555  if (auto const it {shards_.find(shardIndex)}; it != shards_.end())
556  shard = it->second.shard;
557  else
558  {
559  JLOG(j_.error()) <<
560  "shard " << shardIndex << " is not being acquired";
561  return;
562  }
563  }
564 
565  storeLedgerInShard(shard, ledger);
566 }
567 
570 {
571  std::lock_guard lock(mutex_);
572  assert(init_);
573 
574  return status_;
575 }
576 
577 void
579 {
581  {
582  std::lock_guard lock(mutex_);
583  assert(init_);
584 
585  // Only shards with a state of final should be validated
586  for (auto& e : shards_)
587  if (e.second.state == ShardInfo::State::final)
588  shards.push_back(e.second.shard);
589 
590  if (shards.empty())
591  return;
592 
593  JLOG(j_.debug()) << "Validating shards " << status_;
594  }
595 
596  for (auto const& e : shards)
597  {
598  if (auto shard {e.lock()}; shard)
599  shard->finalize(true);
600  }
601 
602  app_.shardFamily()->reset();
603 }
604 
605 void
607 {
608  // Stop read threads in base before data members are destroyed
609  stopThreads();
610 
611  std::lock_guard lock(mutex_);
612  if (shards_.empty())
613  return;
614 
615  // Notify shards to stop
616  for (auto const& e : shards_)
617  if (e.second.shard)
618  e.second.shard->stop();
619  shards_.clear();
620 }
621 
622 void
624 {
625  {
626  std::lock_guard lock(mutex_);
627  assert(init_);
628 
629  // Only the application local node store can be imported
630  if (&source != &app_.getNodeStore())
631  {
632  assert(false);
633  JLOG(j_.error()) << "invalid source database";
634  return;
635  }
636 
637  std::uint32_t earliestIndex;
638  std::uint32_t latestIndex;
639  {
640  auto loadLedger = [&](bool ascendSort = true) ->
641  boost::optional<std::uint32_t>
642  {
644  std::uint32_t seq;
645  std::tie(ledger, seq, std::ignore) = loadLedgerHelper(
646  "WHERE LedgerSeq >= " + std::to_string(earliestLedgerSeq()) +
647  " order by LedgerSeq " + (ascendSort ? "asc" : "desc") +
648  " limit 1", app_, false);
649  if (!ledger || seq == 0)
650  {
651  JLOG(j_.error()) <<
652  "no suitable ledgers were found in"
653  " the SQLite database to import";
654  return boost::none;
655  }
656  return seq;
657  };
658 
659  // Find earliest ledger sequence stored
660  auto seq {loadLedger()};
661  if (!seq)
662  return;
663  earliestIndex = seqToShardIndex(*seq);
664 
665  // Consider only complete shards
666  if (seq != firstLedgerSeq(earliestIndex))
667  ++earliestIndex;
668 
669  // Find last ledger sequence stored
670  seq = loadLedger(false);
671  if (!seq)
672  return;
673  latestIndex = seqToShardIndex(*seq);
674 
675  // Consider only complete shards
676  if (seq != lastLedgerSeq(latestIndex))
677  --latestIndex;
678 
679  if (latestIndex < earliestIndex)
680  {
681  JLOG(j_.error()) <<
682  "no suitable ledgers were found in"
683  " the SQLite database to import";
684  return;
685  }
686  }
687 
688  // Import the shards
689  for (std::uint32_t shardIndex = earliestIndex;
690  shardIndex <= latestIndex; ++shardIndex)
691  {
693  {
694  JLOG(j_.error()) << "maximum storage size reached";
695  canAdd_ = false;
696  break;
697  }
698  if (avgShardFileSz_ > available())
699  {
700  JLOG(j_.error()) << "insufficient storage space available";
701  canAdd_ = false;
702  break;
703  }
704 
705  // Skip if already stored
706  if (shardIndex == acquireIndex_ ||
707  shards_.find(shardIndex) != shards_.end())
708  {
709  JLOG(j_.debug()) <<
710  "shard " << shardIndex << " already exists";
711  continue;
712  }
713 
714  // Verify SQLite ledgers are in the node store
715  {
716  auto const firstSeq {firstLedgerSeq(shardIndex)};
717  auto const lastSeq {
718  std::max(firstSeq, lastLedgerSeq(shardIndex))};
719  auto const numLedgers {shardIndex == earliestShardIndex()
720  ? lastSeq - firstSeq + 1 : ledgersPerShard_};
721  auto ledgerHashes {getHashesByIndex(firstSeq, lastSeq, app_)};
722  if (ledgerHashes.size() != numLedgers)
723  continue;
724 
725  bool valid {true};
726  for (std::uint32_t n = firstSeq; n <= lastSeq; n += 256)
727  {
728  if (!source.fetch(ledgerHashes[n].first, n))
729  {
730  JLOG(j_.warn()) <<
731  "SQLite ledger sequence " << n <<
732  " mismatches node store";
733  valid = false;
734  break;
735  }
736  }
737  if (!valid)
738  continue;
739  }
740 
741  // Create the new shard
742  app_.shardFamily()->reset();
743  auto shard {std::make_unique<Shard>(app_, *this, shardIndex, j_)};
744  if (!shard->open(scheduler_, *ctx_))
745  continue;
746 
747  // Create a marker file to signify an import in progress
748  auto const shardDir {dir_ / std::to_string(shardIndex)};
749  auto const markerFile {shardDir / importMarker_};
750  {
751  std::ofstream ofs {markerFile.string()};
752  if (!ofs.is_open())
753  {
754  JLOG(j_.error()) <<
755  "shard " << shardIndex <<
756  " failed to create temp marker file";
757  shard->removeOnDestroy();
758  continue;
759  }
760  ofs.close();
761  }
762 
763  // Copy the ledgers from node store
764  std::shared_ptr<Ledger> recentStored;
765  boost::optional<uint256> lastLedgerHash;
766 
767  while (auto seq = shard->prepare())
768  {
769  auto ledger {loadByIndex(*seq, app_, false)};
770  if (!ledger || ledger->info().seq != seq)
771  break;
772 
774  *ledger,
775  shard->getBackend(),
776  nullptr,
777  nullptr,
778  recentStored))
779  {
780  break;
781  }
782 
783  if (!shard->store(ledger))
784  break;
785 
786  if (!lastLedgerHash && seq == lastLedgerSeq(shardIndex))
787  lastLedgerHash = ledger->info().hash;
788 
789  recentStored = ledger;
790  }
791 
792  using namespace boost::filesystem;
793  if (lastLedgerHash && shard->isBackendComplete())
794  {
795  // Store shard final key
796  Serializer s;
798  s.add32(firstLedgerSeq(shardIndex));
799  s.add32(lastLedgerSeq(shardIndex));
800  s.add256(*lastLedgerHash);
801  auto nObj {NodeObject::createObject(
802  hotUNKNOWN,
803  std::move(s.modData()),
804  Shard::finalKey)};
805 
806  try
807  {
808  shard->getBackend()->store(nObj);
809 
810  // The import process is complete and the
811  // marker file is no longer required
812  remove_all(markerFile);
813 
814  JLOG(j_.debug()) <<
815  "shard " << shardIndex <<
816  " was successfully imported";
817 
818  auto const result {shards_.emplace(
819  shardIndex,
820  ShardInfo(std::move(shard), ShardInfo::State::none))};
821  finalizeShard(result.first->second, true, lock);
822  }
823  catch (std::exception const& e)
824  {
825  JLOG(j_.error()) <<
826  "exception " << e.what() <<
827  " in function " << __func__;
828  shard->removeOnDestroy();
829  }
830  }
831  else
832  {
833  JLOG(j_.error()) <<
834  "shard " << shardIndex << " failed to import";
835  shard->removeOnDestroy();
836  }
837  }
838 
839  updateStatus(lock);
840  }
841 
842  setFileStats();
843 }
844 
847 {
849  {
850  std::lock_guard lock(mutex_);
851  assert(init_);
852 
853  if (auto const it {shards_.find(acquireIndex_)}; it != shards_.end())
854  shard = it->second.shard;
855  else
856  return 0;
857  }
858 
859  return shard->getBackend()->getWriteLoad();
860 }
861 
862 void
864  NodeObjectType type,
865  Blob&& data,
866  uint256 const& hash,
867  std::uint32_t seq)
868 {
869  auto const shardIndex {seqToShardIndex(seq)};
871  {
872  std::lock_guard lock(mutex_);
873  assert(init_);
874 
875  if (shardIndex != acquireIndex_)
876  {
877  JLOG(j_.trace()) <<
878  "shard " << shardIndex << " is not being acquired";
879  return;
880  }
881 
882  if (auto const it {shards_.find(shardIndex)}; it != shards_.end())
883  shard = it->second.shard;
884  else
885  {
886  JLOG(j_.error()) <<
887  "shard " << shardIndex << " is not being acquired";
888  return;
889  }
890  }
891 
892  auto [backend, pCache, nCache] = shard->getBackendAll();
893  auto nObj {NodeObject::createObject(type, std::move(data), hash)};
894 
895  pCache->canonicalize_replace_cache(hash, nObj);
896  backend->store(nObj);
897  nCache->erase(hash);
898 
899  storeStats(nObj->getData().size());
900 }
901 
904 {
905  auto cache {getCache(seq)};
906  if (cache.first)
907  return doFetch(hash, seq, *cache.first, *cache.second, false);
908  return {};
909 }
910 
911 bool
913  uint256 const& hash,
914  std::uint32_t seq,
916 {
917  auto cache {getCache(seq)};
918  if (cache.first)
919  {
920  // See if the object is in cache
921  object = cache.first->fetch(hash);
922  if (object || cache.second->touch_if_exists(hash))
923  return true;
924  // Otherwise post a read
925  Database::asyncFetch(hash, seq, cache.first, cache.second);
926  }
927  return false;
928 }
929 
930 bool
932 {
933  auto const seq {srcLedger->info().seq};
934  auto const shardIndex {seqToShardIndex(seq)};
936  {
937  std::lock_guard lock(mutex_);
938  assert(init_);
939 
940  if (shardIndex != acquireIndex_)
941  {
942  JLOG(j_.trace()) <<
943  "shard " << shardIndex << " is not being acquired";
944  return false;
945  }
946 
947  if (auto const it {shards_.find(shardIndex)}; it != shards_.end())
948  shard = it->second.shard;
949  else
950  {
951  JLOG(j_.error()) <<
952  "shard " << shardIndex << " is not being acquired";
953  return false;
954  }
955  }
956 
957  if (shard->containsLedger(seq))
958  {
959  JLOG(j_.trace()) <<
960  "shard " << shardIndex << " ledger already stored";
961  return false;
962  }
963 
964  {
965  auto [backend, pCache, nCache] = shard->getBackendAll();
967  *srcLedger,
968  backend,
969  pCache,
970  nCache,
971  nullptr))
972  {
973  return false;
974  }
975  }
976 
977  return storeLedgerInShard(shard, srcLedger);
978 }
979 
980 int
982 {
983  auto const shardIndex {seqToShardIndex(seq)};
985  {
986  std::lock_guard lock(mutex_);
987  assert(init_);
988 
989  if (auto const it {shards_.find(shardIndex)};
990  it != shards_.end() &&
991  (it->second.state == ShardInfo::State::final ||
992  it->second.state == ShardInfo::State::acquire))
993  {
994  shard = it->second.shard;
995  }
996  else
997  return 0;
998  }
999 
1000  return shard->pCache()->getTargetSize() / asyncDivider;
1001 }
1002 
1003 float
1005 {
1006  std::shared_ptr<Shard> shard;
1007  {
1008  std::lock_guard lock(mutex_);
1009  assert(init_);
1010 
1011  if (auto const it {shards_.find(acquireIndex_)}; it != shards_.end())
1012  shard = it->second.shard;
1013  else
1014  return 0;
1015  }
1016 
1017  return shard->pCache()->getHitRate();
1018 }
1019 
1020 void
1022 {
1024  {
1025  std::lock_guard lock(mutex_);
1026  assert(init_);
1027 
1028  for (auto const& e : shards_)
1029  if (e.second.state == ShardInfo::State::final ||
1030  e.second.state == ShardInfo::State::acquire)
1031  {
1032  shards.push_back(e.second.shard);
1033  }
1034  }
1035 
1036  for (auto const& e : shards)
1037  {
1038  if (auto shard {e.lock()}; shard)
1039  shard->sweep();
1040  }
1041 }
1042 
1043 bool
1045 {
1046  auto fail = [j = j_](std::string const& msg)
1047  {
1048  JLOG(j.error()) <<
1049  "[" << ConfigSection::shardDatabase() << "] " << msg;
1050  return false;
1051  };
1052 
1053  Config const& config {app_.config()};
1054  Section const& section {config.section(ConfigSection::shardDatabase())};
1055 
1056  {
1057  // The earliest ledger sequence defaults to XRP_LEDGER_EARLIEST_SEQ.
1058  // A custom earliest ledger sequence can be set through the
1059  // configuration file using the 'earliest_seq' field under the
1060  // 'node_db' and 'shard_db' stanzas. If specified, this field must
1061  // have a value greater than zero and be equally assigned in
1062  // both stanzas.
1063 
1064  std::uint32_t shardDBEarliestSeq {0};
1065  get_if_exists<std::uint32_t>(
1066  section,
1067  "earliest_seq",
1068  shardDBEarliestSeq);
1069 
1070  std::uint32_t nodeDBEarliestSeq {0};
1071  get_if_exists<std::uint32_t>(
1072  config.section(ConfigSection::nodeDatabase()),
1073  "earliest_seq",
1074  nodeDBEarliestSeq);
1075 
1076  if (shardDBEarliestSeq != nodeDBEarliestSeq)
1077  {
1078  return fail("and [" + ConfigSection::nodeDatabase() +
1079  "] define different 'earliest_seq' values");
1080  }
1081  }
1082 
1083  using namespace boost::filesystem;
1084  if (!get_if_exists<path>(section, "path", dir_))
1085  return fail("'path' missing");
1086 
1087  {
1088  std::uint64_t sz;
1089  if (!get_if_exists<std::uint64_t>(section, "max_size_gb", sz))
1090  return fail("'max_size_gb' missing");
1091 
1092  if ((sz << 30) < sz)
1093  return fail("'max_size_gb' overflow");
1094 
1095  // Minimum storage space required (in gigabytes)
1096  if (sz < 10)
1097  return fail("'max_size_gb' must be at least 10");
1098 
1099  // Convert to bytes
1100  maxFileSz_ = sz << 30;
1101  }
1102 
1103  if (section.exists("ledgers_per_shard"))
1104  {
1105  // To be set only in standalone for testing
1106  if (!config.standalone())
1107  return fail("'ledgers_per_shard' only honored in stand alone");
1108 
1109  ledgersPerShard_ = get<std::uint32_t>(section, "ledgers_per_shard");
1110  if (ledgersPerShard_ == 0 || ledgersPerShard_ % 256 != 0)
1111  return fail("'ledgers_per_shard' must be a multiple of 256");
1112  }
1113 
1114  // NuDB is the default and only supported permanent storage backend
1115  backendName_ = get<std::string>(section, "type", "nudb");
1116  if (!boost::iequals(backendName_, "NuDB"))
1117  return fail("'type' value unsupported");
1118 
1119  return true;
1120 }
1121 
1124 {
1125  auto const shardIndex {seqToShardIndex(seq)};
1126  std::shared_ptr<Shard> shard;
1127  {
1128  std::lock_guard lock(mutex_);
1129  assert(init_);
1130 
1131  if (auto const it {shards_.find(shardIndex)};
1132  it != shards_.end() &&
1133  it->second.shard)
1134  {
1135  shard = it->second.shard;
1136  }
1137  else
1138  return {};
1139  }
1140 
1141  return fetchInternal(hash, shard->getBackend());
1142 }
1143 
1144 boost::optional<std::uint32_t>
1146  std::uint32_t validLedgerSeq,
1148 {
1149  if (validLedgerSeq < earliestLedgerSeq())
1150  return boost::none;
1151 
1152  auto const maxShardIndex {[this, validLedgerSeq]()
1153  {
1154  auto shardIndex {seqToShardIndex(validLedgerSeq)};
1155  if (validLedgerSeq != lastLedgerSeq(shardIndex))
1156  --shardIndex;
1157  return shardIndex;
1158  }()};
1159  auto const maxNumShards {maxShardIndex - earliestShardIndex() + 1};
1160 
1161  // Check if the shard store has all shards
1162  if (shards_.size() >= maxNumShards)
1163  return boost::none;
1164 
1165  if (maxShardIndex < 1024 ||
1166  static_cast<float>(shards_.size()) / maxNumShards > 0.5f)
1167  {
1168  // Small or mostly full index space to sample
1169  // Find the available indexes and select one at random
1171  available.reserve(maxNumShards - shards_.size());
1172 
1173  for (auto shardIndex = earliestShardIndex();
1174  shardIndex <= maxShardIndex;
1175  ++shardIndex)
1176  {
1177  if (shards_.find(shardIndex) == shards_.end())
1178  available.push_back(shardIndex);
1179  }
1180 
1181  if (available.empty())
1182  return boost::none;
1183 
1184  if (available.size() == 1)
1185  return available.front();
1186 
1187  return available[rand_int(0u,
1188  static_cast<std::uint32_t>(available.size() - 1))];
1189  }
1190 
1191  // Large, sparse index space to sample
1192  // Keep choosing indexes at random until an available one is found
1193  // chances of running more than 30 times is less than 1 in a billion
1194  for (int i = 0; i < 40; ++i)
1195  {
1196  auto const shardIndex {rand_int(earliestShardIndex(), maxShardIndex)};
1197  if (shards_.find(shardIndex) == shards_.end())
1198  return shardIndex;
1199  }
1200 
1201  assert(false);
1202  return boost::none;
1203 }
1204 
1205 void
1207  ShardInfo& shardInfo,
1208  bool writeSQLite,
1210 {
1211  assert(shardInfo.shard);
1212  assert(shardInfo.shard->index() != acquireIndex_);
1213  assert(shardInfo.shard->isBackendComplete());
1214  assert(shardInfo.state != ShardInfo::State::finalize);
1215 
1216  auto const shardIndex {shardInfo.shard->index()};
1217 
1218  shardInfo.state = ShardInfo::State::finalize;
1219  taskQueue_->addTask([this, shardIndex, writeSQLite]()
1220  {
1221  if (isStopping())
1222  return;
1223 
1224  std::shared_ptr<Shard> shard;
1225  {
1226  std::lock_guard lock(mutex_);
1227  if (auto const it {shards_.find(shardIndex)}; it != shards_.end())
1228  shard = it->second.shard;
1229  else
1230  {
1231  JLOG(j_.error()) <<
1232  "Unable to finalize shard " << shardIndex;
1233  return;
1234  }
1235  }
1236 
1237  if (!shard->finalize(writeSQLite))
1238  {
1239  if (isStopping())
1240  return;
1241 
1242  // Invalid or corrupt shard, remove it
1243  {
1244  std::lock_guard lock(mutex_);
1245  shards_.erase(shardIndex);
1246  updateStatus(lock);
1247  }
1248 
1249  shard->removeOnDestroy();
1250  shard.reset();
1251  setFileStats();
1252  return;
1253  }
1254 
1255  if (isStopping())
1256  return;
1257 
1258  {
1259  std::lock_guard lock(mutex_);
1260  auto const it {shards_.find(shardIndex)};
1261  if (it == shards_.end())
1262  return;
1263  it->second.state = ShardInfo::State::final;
1264  updateStatus(lock);
1265  }
1266 
1267  setFileStats();
1268 
1269  // Update peers with new shard index
1270  if (!app_.config().standalone() &&
1272  {
1273  protocol::TMPeerShardInfo message;
1274  PublicKey const& publicKey {app_.nodeIdentity().first};
1275  message.set_nodepubkey(publicKey.data(), publicKey.size());
1276  message.set_shardindexes(std::to_string(shardIndex));
1278  std::make_shared<Message>(
1279  message,
1280  protocol::mtPEER_SHARD_INFO)));
1281  }
1282  });
1283 }
1284 
1285 void
1287 {
1289  {
1290  std::lock_guard lock(mutex_);
1291  assert(init_);
1292 
1293  if (shards_.empty())
1294  return;
1295 
1296  for (auto const& e : shards_)
1297  if (e.second.shard)
1298  shards.push_back(e.second.shard);
1299  }
1300 
1301  std::uint64_t sumSz {0};
1302  std::uint32_t sumFd {0};
1303  std::uint32_t numShards {0};
1304  for (auto const& e : shards)
1305  {
1306  if (auto shard {e.lock()}; shard)
1307  {
1308  auto[sz, fd] = shard->fileInfo();
1309  sumSz += sz;
1310  sumFd += fd;
1311  ++numShards;
1312  }
1313  }
1314 
1315  std::lock_guard lock(mutex_);
1316  fileSz_ = sumSz;
1317  fdRequired_ = sumFd;
1318  avgShardFileSz_ = (numShards == 0 ? fileSz_ : fileSz_ / numShards);
1319 
1320  if (fileSz_ >= maxFileSz_)
1321  {
1322  JLOG(j_.warn()) << "maximum storage size reached";
1323  canAdd_ = false;
1324  }
1325  else if (maxFileSz_ - fileSz_ > available())
1326  {
1327  JLOG(j_.warn()) <<
1328  "maximum shard store size exceeds available storage space";
1329  }
1330 }
1331 
1332 void
1334 {
1335  if (!shards_.empty())
1336  {
1338  for (auto const& e : shards_)
1339  if (e.second.state == ShardInfo::State::final)
1340  rs.insert(e.second.shard->index());
1341  status_ = to_string(rs);
1342  }
1343  else
1344  status_.clear();
1345 }
1346 
1349 {
1350  auto const shardIndex {seqToShardIndex(seq)};
1351  std::shared_ptr<Shard> shard;
1352  {
1353  std::lock_guard lock(mutex_);
1354  assert(init_);
1355 
1356  if (auto const it {shards_.find(shardIndex)};
1357  it != shards_.end() && it->second.shard)
1358  {
1359  shard = it->second.shard;
1360  }
1361  else
1362  return {};
1363  }
1364 
1365  std::shared_ptr<PCache> pCache;
1366  std::shared_ptr<NCache> nCache;
1367  std::tie(std::ignore, pCache, nCache) = shard->getBackendAll();
1368 
1369  return std::make_pair(pCache, nCache);
1370 }
1371 
1374 {
1375  try
1376  {
1377  return boost::filesystem::space(dir_).available;
1378  }
1379  catch (std::exception const& e)
1380  {
1381  JLOG(j_.error()) <<
1382  "exception " << e.what() << " in function " << __func__;
1383  return 0;
1384  }
1385 }
1386 
1387 bool
1389  std::shared_ptr<Shard>& shard,
1390  std::shared_ptr<Ledger const> const& ledger)
1391 {
1392  bool result {true};
1393 
1394  if (!shard->store(ledger))
1395  {
1396  // Invalid or corrupt shard, remove it
1397  {
1398  std::lock_guard lock(mutex_);
1399  shards_.erase(shard->index());
1400 
1401  if (shard->index() == acquireIndex_)
1402  acquireIndex_ = 0;
1403 
1404  updateStatus(lock);
1405  }
1406 
1407  shard->removeOnDestroy();
1408  shard.reset();
1409  result = false;
1410  }
1411  else if (shard->isBackendComplete())
1412  {
1413  std::lock_guard lock(mutex_);
1414 
1415  if (auto const it {shards_.find(shard->index())};
1416  it != shards_.end())
1417  {
1418  if (shard->index() == acquireIndex_)
1419  acquireIndex_ = 0;
1420 
1421  if (it->second.state != ShardInfo::State::finalize)
1422  finalizeShard(it->second, false, lock);
1423  }
1424  else
1425  {
1426  JLOG(j_.debug()) <<
1427  "shard " << shard->index() <<
1428  " is no longer being acquired";
1429  }
1430  }
1431 
1432  setFileStats();
1433  return result;
1434 }
1435 
1436 //------------------------------------------------------------------------------
1437 
1440  Application& app,
1441  Stoppable& parent,
1442  Scheduler& scheduler,
1443  int readThreads,
1444  beast::Journal j)
1445 {
1446  // The shard store is optional. Future changes will require it.
1447  Section const& section {
1449  if (section.empty())
1450  return nullptr;
1451 
1452  return std::make_unique<DatabaseShardImp>(
1453  app,
1454  parent,
1455  "ShardStore",
1456  scheduler,
1457  readThreads,
1458  j);
1459 }
1460 
1461 } // NodeStore
1462 } // ripple
ripple::NodeStore::make_ShardStore
std::unique_ptr< DatabaseShard > make_ShardStore(Application &app, Stoppable &parent, Scheduler &scheduler, int readThreads, beast::Journal j)
Definition: DatabaseShardImp.cpp:1439
ripple::Section
Holds a collection of configuration values.
Definition: BasicConfig.h:43
ripple::loadLedgerHelper
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > loadLedgerHelper(std::string const &sqlSuffix, Application &app, bool acquire)
Definition: Ledger.cpp:1056
ripple::Application
Definition: Application.h:85
ripple::NodeStore::DatabaseShardImp::ledgersPerShard_
std::uint32_t ledgersPerShard_
Definition: DatabaseShardImp.h:232
ripple::hotUNKNOWN
@ hotUNKNOWN
Definition: NodeObject.h:35
ripple::NodeStore::DatabaseShardImp::lastLedgerSeq
std::uint32_t lastLedgerSeq(std::uint32_t shardIndex) const override
Calculates the last ledger sequence for a given shard index.
Definition: DatabaseShardImp.h:110
ripple::NodeStore::DatabaseShardImp::earliestShardIndex
std::uint32_t earliestShardIndex() const override
Definition: DatabaseShardImp.h:88
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:199
ripple::NodeStore::DatabaseShardImp::mutex_
std::mutex mutex_
Definition: DatabaseShardImp.h:196
ripple::NodeStore::DatabaseShardImp::prepareLedger
boost::optional< std::uint32_t > prepareLedger(std::uint32_t validLedgerSeq) override
Prepare to store a new ledger in the shard being acquired.
Definition: DatabaseShardImp.cpp:202
ripple::NodeStore::DatabaseShardImp::app_
Application & app_
Definition: DatabaseShardImp.h:194
ripple::NodeStore::DatabaseShardImp::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger) override
Copies a ledger stored in a different database to this one.
Definition: DatabaseShardImp.cpp:931
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:53
std::string
STL class.
ripple::NodeStore::DatabaseShardImp::fetch
std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq) override
Fetch an object.
Definition: DatabaseShardImp.cpp:903
std::shared_ptr
STL class.
ripple::NodeStore::Database::doFetch
std::shared_ptr< NodeObject > doFetch(uint256 const &hash, std::uint32_t seq, TaggedCache< uint256, NodeObject > &pCache, KeyCache< uint256 > &nCache, bool isAsync)
Definition: Database.cpp:189
ripple::loadByIndex
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
Definition: Ledger.cpp:1159
ripple::NodeStore::DatabaseShardImp::seqToShardIndex
std::uint32_t seqToShardIndex(std::uint32_t seq) const override
Calculates the shard index for a given ledger sequence.
Definition: DatabaseShardImp.h:94
std::exception
STL class.
std::stoul
T stoul(T... args)
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:287
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::none
@ none
ripple::Family::reset
virtual void reset()=0
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:181
std::pair
ripple::NodeStore::DatabaseShardImp::getCache
std::pair< std::shared_ptr< PCache >, std::shared_ptr< NCache > > getCache(std::uint32_t seq)
Definition: DatabaseShardImp.cpp:1348
ripple::NodeStore::DatabaseShardImp::removePreShard
void removePreShard(std::uint32_t shardIndex) override
Remove a previously prepared shard index for import.
Definition: DatabaseShardImp.cpp:317
ripple::LedgerMaster::getValidLedgerIndex
LedgerIndex getValidLedgerIndex()
Definition: LedgerMaster.cpp:223
ripple::NodeStore::Database::fdRequired_
int fdRequired_
Definition: Database.h:228
ripple::NodeStore::DatabaseShardImp::fileSz_
std::uint64_t fileSz_
Definition: DatabaseShardImp.h:227
std::vector
STL class.
ripple::ConfigSection::shardDatabase
static std::string shardDatabase()
Definition: ConfigSections.h:33
ripple::NodeObjectType
NodeObjectType
The types of node objects.
Definition: NodeObject.h:32
ripple::Overlay::foreach
std::enable_if_t<! std::is_void< typename UnaryFunc::return_type >::value, typename UnaryFunc::return_type > foreach(UnaryFunc f)
Visit every active peer and return a value The functor must:
Definition: Overlay.h:195
ripple::NodeObject::createObject
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
Definition: NodeObject.cpp:39
ripple::NodeStore::DatabaseShardImp::taskQueue_
std::unique_ptr< TaskQueue > taskQueue_
Definition: DatabaseShardImp.h:203
ripple::NodeStore::DatabaseShardImp::ShardInfo::state
State state
Definition: DatabaseShardImp.h:191
ripple::NodeStore::DatabaseShardImp::setStored
void setStored(std::shared_ptr< Ledger const > const &ledger) override
Notifies the database that the given ledger has been fully acquired and stored.
Definition: DatabaseShardImp.cpp:513
ripple::rand_int
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
Definition: ripple/basics/random.h:121
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::acquire
@ acquire
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::NodeStore::DatabaseShardImp::prepareShard
bool prepareShard(std::uint32_t shardIndex) override
Prepare a shard index to be imported into the database.
Definition: DatabaseShardImp.cpp:264
std::lock_guard
STL class.
ripple::kilobytes
constexpr auto kilobytes(T value) noexcept
Definition: ByteUtilities.h:26
ripple::NetworkOPs::getOperatingMode
virtual OperatingMode getOperatingMode() const =0
ripple::Serializer::add32
int add32(std::uint32_t)
Definition: Serializer.cpp:46
ripple::NodeStore::DatabaseShardImp::available
std::uint64_t available() const
Definition: DatabaseShardImp.cpp:1373
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::final
@ final
ripple::NodeStore::DatabaseShardImp::asyncFetch
bool asyncFetch(uint256 const &hash, std::uint32_t seq, std::shared_ptr< NodeObject > &object) override
Fetch an object without waiting.
Definition: DatabaseShardImp.cpp:912
std::all_of
T all_of(T... args)
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::NodeStore::Shard::finalKey
static const uint256 finalKey
Definition: Shard.h:142
std::shared_ptr::reset
T reset(T... args)
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:44
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::NodeStore::DatabaseShardImp::sweep
void sweep() override
Remove expired entries from the positive and negative caches.
Definition: DatabaseShardImp.cpp:1021
std::string::clear
T clear(T... args)
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::finalize
@ finalize
ripple::send_always
Sends a message to all peers.
Definition: predicates.h:31
ripple::Stoppable::setParent
void setParent(Stoppable &parent)
Set the parent of this Stoppable.
Definition: Stoppable.cpp:46
ripple::NodeStore::Shard::version
static constexpr std::uint32_t version
Definition: Shard.h:137
std::tie
T tie(T... args)
std::vector::push_back
T push_back(T... args)
ripple::NodeStore::DatabaseShardImp::getDesiredAsyncReadCount
int getDesiredAsyncReadCount(std::uint32_t seq) override
Get the maximum number of async reads the node store prefers.
Definition: DatabaseShardImp.cpp:981
ripple::NodeStore::DatabaseShardImp::firstLedgerSeq
std::uint32_t firstLedgerSeq(std::uint32_t shardIndex) const override
Calculates the first ledger sequence for a given shard index.
Definition: DatabaseShardImp.h:101
ripple::NodeStore::DatabaseShardImp::getCacheHitRate
float getCacheHitRate() override
Get the positive cache hits to total attempts ratio.
Definition: DatabaseShardImp.cpp:1004
ripple::NodeStore::DatabaseShardImp::avgShardFileSz_
std::uint64_t avgShardFileSz_
Definition: DatabaseShardImp.h:238
ripple::base_uint< 256 >
ripple::NodeStore::DatabaseShardImp::status_
std::string status_
Definition: DatabaseShardImp.h:218
ripple::NodeStore::DatabaseShardImp::fetchFrom
std::shared_ptr< NodeObject > fetchFrom(uint256 const &hash, std::uint32_t seq) override
Definition: DatabaseShardImp.cpp:1123
ripple::NodeStore::DatabaseShardImp::getPreShards
std::string getPreShards() override
Get shard indexes being imported.
Definition: DatabaseShardImp.cpp:330
ripple::NodeStore::DatabaseShardImp::getWriteLoad
std::int32_t getWriteLoad() const override
Retrieve the estimated number of pending write operations.
Definition: DatabaseShardImp.cpp:846
ripple::NodeStore::DatabaseShardImp::maxFileSz_
std::uint64_t maxFileSz_
Definition: DatabaseShardImp.h:224
ripple::NodeStore::TaskQueue
Definition: TaskQueue.h:32
ripple::OperatingMode::DISCONNECTED
@ DISCONNECTED
not ready to process requests
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:200
ripple::Application::shardFamily
virtual Family * shardFamily()=0
ripple::NodeStore::DatabaseShardImp::ShardInfo::shard
std::shared_ptr< Shard > shard
Definition: DatabaseShardImp.h:190
ripple::NodeStore::DatabaseShardImp::initConfig
bool initConfig(std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1044
ripple::InboundLedger::deserializeHeader
static LedgerInfo deserializeHeader(Slice data, bool hasPrefix)
Definition: InboundLedger.cpp:251
ripple::NodeStore::DatabaseShardImp::init_
bool init_
Definition: DatabaseShardImp.h:197
ripple::NodeStore::DatabaseShardImp::getCompleteShards
std::string getCompleteShards() override
Query which complete shards are stored.
Definition: DatabaseShardImp.cpp:569
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::Config
Definition: Config.h:67
ripple::NodeStore::DatabaseShardImp::shards_
std::map< std::uint32_t, ShardInfo > shards_
Definition: DatabaseShardImp.h:206
std::ofstream
STL class.
ripple::NodeStore::Database::fetch
virtual std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq)=0
Fetch an object.
ripple::NodeStore::DatabaseShardImp::~DatabaseShardImp
~DatabaseShardImp() override
Definition: DatabaseShardImp.cpp:60
ripple::Application::config
virtual Config & config()=0
ripple::NodeStore::DatabaseShardImp::dir_
boost::filesystem::path dir_
Definition: DatabaseShardImp.h:212
ripple::NodeStore::DatabaseShardImp::updateStatus
void updateStatus(std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1333
ripple::Config::standalone
bool standalone() const
Definition: Config.h:204
ripple::NodeStore::seqToShardIndex
constexpr std::uint32_t seqToShardIndex(std::uint32_t seq, std::uint32_t ledgersPerShard=DatabaseShard::ledgersPerShardDefault)
Definition: DatabaseShard.h:207
ripple::Application::nodeIdentity
virtual std::pair< PublicKey, SecretKey > const & nodeIdentity()=0
ripple::NodeStore::DatabaseShard
A collection of historical shards.
Definition: DatabaseShard.h:37
std::to_string
T to_string(T... args)
ripple::NodeStore::DatabaseShardImp::importShard
bool importShard(std::uint32_t shardIndex, boost::filesystem::path const &srcDir) override
Import a shard into the shard database.
Definition: DatabaseShardImp.cpp:349
ripple::NodeStore::Database::storeStats
void storeStats(size_t sz)
Definition: Database.h:234
beast::Journal::error
Stream error() const
Definition: Journal.h:307
ripple::ConfigSection
Definition: ConfigSections.h:28
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
std::uint32_t
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const
Definition: Database.h:220
ripple::NodeStore::DatabaseShardImp::setFileStats
void setFileStats()
Definition: DatabaseShardImp.cpp:1286
ripple::NodeStore::DatabaseShardImp::acquireIndex_
std::uint32_t acquireIndex_
Definition: DatabaseShardImp.h:209
ripple::NodeStore::Scheduler
Scheduling for asynchronous backend activity.
Definition: ripple/nodestore/Scheduler.h:57
ripple::NodeStore::DatabaseShardImp::findAcquireIndex
boost::optional< std::uint32_t > findAcquireIndex(std::uint32_t validLedgerSeq, std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1145
ripple::NodeStore::Database::fetchInternal
std::shared_ptr< NodeObject > fetchInternal(uint256 const &hash, std::shared_ptr< Backend > backend)
Definition: Database.cpp:123
ripple::NodeStore::DatabaseShardImp::init
bool init() override
Initialize the database.
Definition: DatabaseShardImp.cpp:66
ripple::Serializer
Definition: Serializer.h:43
ripple::NodeStore::DatabaseShardImp::store
void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq) override
Store the object.
Definition: DatabaseShardImp.cpp:863
ripple::NodeStore::DatabaseShardImp::parent_
Stoppable & parent_
Definition: DatabaseShardImp.h:195
ripple::NodeStore::DatabaseShardImp::importMarker_
static constexpr auto importMarker_
Definition: DatabaseShardImp.h:241
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::Database::storeLedger
virtual bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger)=0
Copies a ledger stored in a different database to this one.
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::NodeStore::DatabaseShardImp::import
void import(Database &source) override
Import the application local node store.
Definition: DatabaseShardImp.cpp:623
ripple::NodeStore::Database::j_
const beast::Journal j_
Definition: Database.h:226
ripple::NodeStore::DatabaseShardImp::fetchLedger
std::shared_ptr< Ledger > fetchLedger(uint256 const &hash, std::uint32_t seq) override
Fetch a ledger from the shard store.
Definition: DatabaseShardImp.cpp:436
ripple::NodeStore::Database::stopThreads
void stopThreads()
Definition: Database.cpp:95
std
STL namespace.
ripple::NodeStore::Database::asyncFetch
virtual bool asyncFetch(uint256 const &hash, std::uint32_t seq, std::shared_ptr< NodeObject > &object)=0
Fetch an object without waiting.
ripple::LedgerMaster::getCurrentLedgerIndex
LedgerIndex getCurrentLedgerIndex()
Definition: LedgerMaster.cpp:217
ripple::Application::overlay
virtual Overlay & overlay()=0
std::vector::empty
T empty(T... args)
ripple::NodeStore::DatabaseShardImp::validate
void validate() override
Verifies shard store data is valid.
Definition: DatabaseShardImp.cpp:578
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
ripple::getHashesByIndex
bool getHashesByIndex(std::uint32_t ledgerIndex, uint256 &ledgerHash, uint256 &parentHash, Application &app)
Definition: Ledger.cpp:1226
ripple::NodeStore::DatabaseShardImp::canAdd_
bool canAdd_
Definition: DatabaseShardImp.h:215
std::make_pair
T make_pair(T... args)
ripple::NodeStore::Database::scheduler_
Scheduler & scheduler_
Definition: Database.h:227
ripple::RangeSet
boost::icl::interval_set< T, std::less, ClosedInterval< T > > RangeSet
A set of closed intervals over the domain T.
Definition: RangeSet.h:70
std::max
T max(T... args)
ripple::NodeStore::DatabaseShardImp::DatabaseShardImp
DatabaseShardImp()=delete
std::unique_ptr
STL class.
ripple::NodeStore::DatabaseShardImp::ShardInfo::State::import
@ import
ripple::NodeStore::asyncDivider
@ asyncDivider
Definition: nodestore/impl/Tuning.h:32
ripple::ConfigSection::nodeDatabase
static std::string nodeDatabase()
Definition: ConfigSections.h:32
ripple::NodeStore::DatabaseShardImp::ShardInfo
Definition: DatabaseShardImp.h:173
std::exception::what
T what(T... args)
ripple::NodeStore::DatabaseShardImp::finalizeShard
void finalizeShard(ShardInfo &shardInfo, bool writeSQLite, std::lock_guard< std::mutex > &)
Definition: DatabaseShardImp.cpp:1206
ripple::NodeStore::DatabaseShardImp::onStop
void onStop() override
Override called when the stop notification is issued.
Definition: DatabaseShardImp.cpp:606
ripple::NodeStore::DatabaseShardImp::ctx_
std::unique_ptr< nudb::context > ctx_
Definition: DatabaseShardImp.h:200
ripple::BasicConfig::section
Section & section(std::string const &name)
Returns the section with the given name.
Definition: BasicConfig.cpp:140
ripple::Serializer::add256
int add256(uint256 const &)
Definition: Serializer.cpp:93
ripple::Stoppable::isStopping
bool isStopping() const
Returns true if the stoppable should stop.
Definition: Stoppable.cpp:56
ripple::NodeStore::DatabaseShardImp::storeLedgerInShard
bool storeLedgerInShard(std::shared_ptr< Shard > &shard, std::shared_ptr< Ledger const > const &ledger)
Definition: DatabaseShardImp.cpp:1388
ripple::NodeStore::DatabaseShardImp::backendName_
std::string backendName_
Definition: DatabaseShardImp.h:221