rippled
Loading...
Searching...
No Matches
SHAMapStoreImp.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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 <xrpld/app/ledger/TransactionMaster.h>
21#include <xrpld/app/misc/NetworkOPs.h>
22#include <xrpld/app/misc/SHAMapStoreImp.h>
23#include <xrpld/app/rdb/State.h>
24#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
25#include <xrpld/core/ConfigSections.h>
26
27#include <xrpl/beast/core/CurrentThreadName.h>
28#include <xrpl/nodestore/Scheduler.h>
29#include <xrpl/nodestore/detail/DatabaseRotatingImp.h>
30#include <xrpl/shamap/SHAMapMissingNode.h>
31
32#include <boost/algorithm/string/predicate.hpp>
33
34namespace ripple {
35void
37 BasicConfig const& config,
38 std::string const& dbName)
39{
41 initStateDB(sqlDb_, config, dbName);
42}
43
51
54{
56
57 return ripple::setCanDelete(sqlDb_, canDelete);
58}
59
67
68void
74
75void
81
82//------------------------------------------------------------------------------
83
85 Application& app,
86 NodeStore::Scheduler& scheduler,
87 beast::Journal journal)
88 : app_(app)
89 , scheduler_(scheduler)
90 , journal_(journal)
91 , working_(true)
92 , canDelete_(std::numeric_limits<LedgerIndex>::max())
93{
94 Config& config{app.config()};
95
96 Section& section{config.section(ConfigSection::nodeDatabase())};
97 if (section.empty())
98 {
99 Throw<std::runtime_error>(
100 "Missing [" + ConfigSection::nodeDatabase() +
101 "] entry in configuration file");
102 }
103
104 // RocksDB only. Use sensible defaults if no values specified.
105 if (boost::iequals(get(section, "type"), "RocksDB"))
106 {
107 if (!section.exists("cache_mb"))
108 {
109 section.set(
110 "cache_mb",
111 std::to_string(config.getValueFor(SizedItem::hashNodeDBCache)));
112 }
113
114 if (!section.exists("filter_bits") && (config.NODE_SIZE >= 2))
115 section.set("filter_bits", "10");
116 }
117
118 get_if_exists(section, "online_delete", deleteInterval_);
119
120 if (deleteInterval_)
121 {
122 // Configuration that affects the behavior of online delete
123 get_if_exists(section, "delete_batch", deleteBatch_);
124 std::uint32_t temp;
125 if (get_if_exists(section, "back_off_milliseconds", temp) ||
126 // Included for backward compaibility with an undocumented setting
127 get_if_exists(section, "backOff", temp))
128 {
130 }
131 if (get_if_exists(section, "age_threshold_seconds", temp))
133 if (get_if_exists(section, "recovery_wait_seconds", temp))
135
136 get_if_exists(section, "advisory_delete", advisoryDelete_);
137
138 auto const minInterval = config.standalone()
141 if (deleteInterval_ < minInterval)
142 {
143 Throw<std::runtime_error>(
144 "online_delete must be at least " +
145 std::to_string(minInterval));
146 }
147
148 if (config.LEDGER_HISTORY > deleteInterval_)
149 {
150 Throw<std::runtime_error>(
151 "online_delete must not be less than ledger_history "
152 "(currently " +
153 std::to_string(config.LEDGER_HISTORY) + ")");
154 }
155
156 state_db_.init(config, dbName_);
157 dbPaths();
158 }
159}
160
163{
165
166 // Provide default values:
167 if (!nscfg.exists("cache_size"))
168 nscfg.set(
169 "cache_size",
172
173 if (!nscfg.exists("cache_age"))
174 nscfg.set(
175 "cache_age",
178
180
181 if (deleteInterval_)
182 {
183 SavedState state = state_db_.getState();
184 auto writableBackend = makeBackendRotating(state.writableDb);
185 auto archiveBackend = makeBackendRotating(state.archiveDb);
186 if (!state.writableDb.size())
187 {
188 state.writableDb = writableBackend->getName();
189 state.archiveDb = archiveBackend->getName();
190 state_db_.setState(state);
191 }
192
193 // Create NodeStore with two backends to allow online deletion of
194 // data
197 readThreads,
198 std::move(writableBackend),
199 std::move(archiveBackend),
200 nscfg,
202 fdRequired_ += dbr->fdRequired();
203 dbRotating_ = dbr.get();
204 db.reset(dynamic_cast<NodeStore::Database*>(dbr.release()));
205 }
206 else
207 {
209 megabytes(
212 readThreads,
213 nscfg,
215 fdRequired_ += db->fdRequired();
216 }
217 return db;
218}
219
220void
222{
223 {
225 newLedger_ = ledger;
226 working_ = true;
227 }
229}
230
231void
233{
234 if (!working_)
235 return;
236
238 rendezvous_.wait(lock, [&] { return !working_; });
239}
240
241int
243{
244 return fdRequired_;
245}
246
247bool
249{
250 // Copy a single record from node to dbRotating_
252 node.getHash().as_uint256(),
253 0,
255 true);
256 if (!(++nodeCount % checkHealthInterval_))
257 {
258 if (healthWait() == stopping)
259 return false;
260 }
261
262 return true;
263}
264
265void
267{
268 beast::setCurrentThreadName("SHAMapStore");
270 netOPs_ = &app_.getOPs();
274
275 if (advisoryDelete_)
277
278 while (true)
279 {
280 healthy_ = true;
281 std::shared_ptr<Ledger const> validatedLedger;
282
283 {
285 working_ = false;
287 if (stop_)
288 {
289 return;
290 }
291 cond_.wait(lock);
292 if (newLedger_)
293 {
294 validatedLedger = std::move(newLedger_);
295 }
296 else
297 continue;
298 }
299
300 LedgerIndex const validatedSeq = validatedLedger->info().seq;
301 if (!lastRotated)
302 {
303 lastRotated = validatedSeq;
304 state_db_.setLastRotated(lastRotated);
305 }
306
307 bool const readyToRotate =
308 validatedSeq >= lastRotated + deleteInterval_ &&
309 canDelete_ >= lastRotated - 1 && healthWait() == keepGoing;
310
311 // will delete up to (not including) lastRotated
312 if (readyToRotate)
313 {
314 JLOG(journal_.warn())
315 << "rotating validatedSeq " << validatedSeq << " lastRotated "
316 << lastRotated << " deleteInterval " << deleteInterval_
317 << " canDelete_ " << canDelete_ << " state "
318 << app_.getOPs().strOperatingMode(false) << " age "
320
321 clearPrior(lastRotated);
322 if (healthWait() == stopping)
323 return;
324
325 JLOG(journal_.debug()) << "copying ledger " << validatedSeq;
326 std::uint64_t nodeCount = 0;
327
328 try
329 {
330 validatedLedger->stateMap().snapShot(false)->visitNodes(
331 std::bind(
333 this,
334 std::ref(nodeCount),
335 std::placeholders::_1));
336 }
337 catch (SHAMapMissingNode const& e)
338 {
339 JLOG(journal_.error())
340 << "Missing node while copying ledger before rotate: "
341 << e.what();
342 continue;
343 }
344
345 if (healthWait() == stopping)
346 return;
347 // Only log if we completed without a "health" abort
348 JLOG(journal_.debug()) << "copied ledger " << validatedSeq
349 << " nodecount " << nodeCount;
350
351 JLOG(journal_.debug()) << "freshening caches";
353 if (healthWait() == stopping)
354 return;
355 // Only log if we completed without a "health" abort
356 JLOG(journal_.debug()) << validatedSeq << " freshened caches";
357
358 JLOG(journal_.trace()) << "Making a new backend";
359 auto newBackend = makeBackendRotating();
360 JLOG(journal_.debug())
361 << validatedSeq << " new backend " << newBackend->getName();
362
363 clearCaches(validatedSeq);
364 if (healthWait() == stopping)
365 return;
366
367 lastRotated = validatedSeq;
368
370 std::move(newBackend),
371 [&](std::string const& writableName,
372 std::string const& archiveName) {
373 SavedState savedState;
374 savedState.writableDb = writableName;
375 savedState.archiveDb = archiveName;
376 savedState.lastRotated = lastRotated;
377 state_db_.setState(savedState);
378
379 clearCaches(validatedSeq);
380 });
381
382 JLOG(journal_.warn()) << "finished rotation " << validatedSeq;
383 }
384 }
385}
386
387void
389{
391 boost::filesystem::path dbPath = get(section, "path");
392
393 if (boost::filesystem::exists(dbPath))
394 {
395 if (!boost::filesystem::is_directory(dbPath))
396 {
398 << "node db path must be a directory. " << dbPath.string();
399 Throw<std::runtime_error>("node db path must be a directory.");
400 }
401 }
402 else
403 {
404 boost::filesystem::create_directories(dbPath);
405 }
406
407 SavedState state = state_db_.getState();
408
409 {
410 auto update = [&dbPath](std::string& sPath) {
411 if (sPath.empty())
412 return false;
413
414 // Check if configured "path" matches stored directory path
415 using namespace boost::filesystem;
416 auto const stored{path(sPath)};
417 if (stored.parent_path() == dbPath)
418 return false;
419
420 sPath = (dbPath / stored.filename()).string();
421 return true;
422 };
423
424 if (update(state.writableDb))
425 {
426 update(state.archiveDb);
427 state_db_.setState(state);
428 }
429 }
430
431 bool writableDbExists = false;
432 bool archiveDbExists = false;
433
435 for (boost::filesystem::directory_iterator it(dbPath);
436 it != boost::filesystem::directory_iterator();
437 ++it)
438 {
439 if (!state.writableDb.compare(it->path().string()))
440 writableDbExists = true;
441 else if (!state.archiveDb.compare(it->path().string()))
442 archiveDbExists = true;
443 else if (!dbPrefix_.compare(it->path().stem().string()))
444 pathsToDelete.push_back(it->path());
445 }
446
447 if ((!writableDbExists && state.writableDb.size()) ||
448 (!archiveDbExists && state.archiveDb.size()) ||
449 (writableDbExists != archiveDbExists) ||
450 state.writableDb.empty() != state.archiveDb.empty())
451 {
452 boost::filesystem::path stateDbPathName =
453 app_.config().legacy("database_path");
454 stateDbPathName /= dbName_;
455 stateDbPathName += "*";
456
458 << "state db error:\n"
459 << " writableDbExists " << writableDbExists << " archiveDbExists "
460 << archiveDbExists << '\n'
461 << " writableDb '" << state.writableDb << "' archiveDb '"
462 << state.archiveDb << "\n\n"
463 << "The existing data is in a corrupted state.\n"
464 << "To resume operation, remove the files matching "
465 << stateDbPathName.string() << " and contents of the directory "
466 << get(section, "path") << '\n'
467 << "Optionally, you can move those files to another\n"
468 << "location if you wish to analyze or back up the data.\n"
469 << "However, there is no guarantee that the data in its\n"
470 << "existing form is usable.";
471
472 Throw<std::runtime_error>("state db error");
473 }
474
475 // The necessary directories exist. Now, remove any others.
476 for (boost::filesystem::path& p : pathsToDelete)
477 boost::filesystem::remove_all(p);
478}
479
482{
484 boost::filesystem::path newPath;
485
486 if (path.size())
487 {
488 newPath = path;
489 }
490 else
491 {
492 boost::filesystem::path p = get(section, "path");
493 p /= dbPrefix_;
494 p += ".%%%%";
495 newPath = boost::filesystem::unique_path(p);
496 }
497 section.set("path", newPath.string());
498
500 section,
501 megabytes(
505 backend->open();
506 return backend;
507}
508
509void
511 LedgerIndex lastRotated,
512 std::string const& TableName,
513 std::function<std::optional<LedgerIndex>()> const& getMinSeq,
514 std::function<void(LedgerIndex)> const& deleteBeforeSeq)
515{
516 XRPL_ASSERT(
518 "ripple::SHAMapStoreImp::clearSql : nonzero delete interval");
520
521 {
522 JLOG(journal_.trace())
523 << "Begin: Look up lowest value of: " << TableName;
524 auto m = getMinSeq();
525 JLOG(journal_.trace()) << "End: Look up lowest value of: " << TableName;
526 if (!m)
527 return;
528 min = *m;
529 }
530
531 if (min > lastRotated || healthWait() == stopping)
532 return;
533 if (min == lastRotated)
534 {
535 // Micro-optimization mainly to clarify logs
536 JLOG(journal_.trace()) << "Nothing to delete from " << TableName;
537 return;
538 }
539
540 JLOG(journal_.debug()) << "start deleting in: " << TableName << " from "
541 << min << " to " << lastRotated;
542 while (min < lastRotated)
543 {
544 min = std::min(lastRotated, min + deleteBatch_);
545 JLOG(journal_.trace())
546 << "Begin: Delete up to " << deleteBatch_
547 << " rows with LedgerSeq < " << min << " from: " << TableName;
548 deleteBeforeSeq(min);
549 JLOG(journal_.trace())
550 << "End: Delete up to " << deleteBatch_ << " rows with LedgerSeq < "
551 << min << " from: " << TableName;
552 if (healthWait() == stopping)
553 return;
554 if (min < lastRotated)
556 if (healthWait() == stopping)
557 return;
558 }
559 JLOG(journal_.debug()) << "finished deleting from: " << TableName;
560}
561
562void
568
569void
577
578void
580{
581 // Do not allow ledgers to be acquired from the network
582 // that are about to be deleted.
583 minimumOnline_ = lastRotated + 1;
584 JLOG(journal_.trace()) << "Begin: Clear internal ledgers up to "
585 << lastRotated;
586 ledgerMaster_->clearPriorLedgers(lastRotated);
587 JLOG(journal_.trace()) << "End: Clear internal ledgers up to "
588 << lastRotated;
589 if (healthWait() == stopping)
590 return;
591
592 SQLiteDatabase* const db =
593 dynamic_cast<SQLiteDatabase*>(&app_.getRelationalDatabase());
594
595 if (!db)
596 Throw<std::runtime_error>("Failed to get relational database");
597
598 clearSql(
599 lastRotated,
600 "Ledgers",
601 [db]() -> std::optional<LedgerIndex> { return db->getMinLedgerSeq(); },
602 [db](LedgerIndex min) -> void { db->deleteBeforeLedgerSeq(min); });
603 if (healthWait() == stopping)
604 return;
605
606 if (!app_.config().useTxTables())
607 return;
608
609 clearSql(
610 lastRotated,
611 "Transactions",
612 [&db]() -> std::optional<LedgerIndex> {
613 return db->getTransactionsMinLedgerSeq();
614 },
615 [&db](LedgerIndex min) -> void {
617 });
618 if (healthWait() == stopping)
619 return;
620
621 clearSql(
622 lastRotated,
623 "AccountTransactions",
624 [&db]() -> std::optional<LedgerIndex> {
626 },
627 [&db](LedgerIndex min) -> void {
629 });
630 if (healthWait() == stopping)
631 return;
632}
633
636{
640 while (!stop_ && (mode != OperatingMode::FULL || age > ageThreshold_))
641 {
642 lock.unlock();
643 JLOG(journal_.warn()) << "Waiting " << recoveryWaitTime_.count()
644 << "s for node to stabilize. state: "
645 << app_.getOPs().strOperatingMode(mode, false)
646 << ". age " << age.count() << 's';
649 mode = netOPs_->getOperatingMode();
650 lock.lock();
651 }
652
653 return stop_ ? stopping : keepGoing;
654}
655
656void
658{
659 if (thread_.joinable())
660 {
661 {
663 stop_ = true;
665 }
666 thread_.join();
667 }
668}
669
672{
673 // minimumOnline_ with 0 value is equivalent to unknown/not set.
674 // Don't attempt to acquire ledgers if that value is unknown.
676 return minimumOnline_.load();
677 return app_.getLedgerMaster().minSqlSeq();
678}
679
680//------------------------------------------------------------------------------
681
684 Application& app,
685 NodeStore::Scheduler& scheduler,
686 beast::Journal journal)
687{
688 return std::make_unique<SHAMapStoreImp>(app, scheduler, journal);
689}
690
691} // namespace ripple
T bind(T... args)
A generic endpoint for log messages.
Definition Journal.h:60
Stream error() const
Definition Journal.h:346
Stream debug() const
Definition Journal.h:328
Stream trace() const
Severity stream access functions.
Definition Journal.h:322
Stream warn() const
Definition Journal.h:340
virtual Config & config()=0
virtual NetworkOPs & getOPs()=0
virtual Family & getNodeFamily()=0
virtual LedgerMaster & getLedgerMaster()=0
virtual RelationalDatabase & getRelationalDatabase()=0
virtual TransactionMaster & getMasterTransaction()=0
virtual Logs & logs()=0
Holds unparsed configuration information.
Section & section(std::string const &name)
Returns the section with the given name.
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
bool useTxTables() const
Definition Config.h:342
int getValueFor(SizedItem item, std::optional< std::size_t > node=std::nullopt) const
Retrieve the default value for the item at the specified node size.
Definition Config.cpp:1116
virtual std::shared_ptr< FullBelowCache > getFullBelowCache()=0
Return a pointer to the Family Full Below Cache.
virtual std::shared_ptr< TreeNodeCache > getTreeNodeCache()=0
Return a pointer to the Family Tree Node Cache.
void clearLedgerCachePrior(LedgerIndex seq)
void clearPriorLedgers(LedgerIndex seq)
std::optional< LedgerIndex > minSqlSeq()
std::chrono::seconds getValidatedLedgerAge()
beast::Journal journal(std::string const &name)
Definition Log.cpp:160
virtual OperatingMode getOperatingMode() const =0
virtual std::string strOperatingMode(OperatingMode const mode, bool const admin=false) const =0
virtual void rotate(std::unique_ptr< NodeStore::Backend > &&newBackend, std::function< void(std::string const &writableName, std::string const &archiveName)> const &f)=0
Rotates the backends.
Persistency layer for NodeObject.
Definition Database.h:51
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t ledgerSeq=0, FetchType fetchType=FetchType::synchronous, bool duplicate=false)
Fetch a node object.
Definition Database.cpp:240
virtual std::unique_ptr< Backend > make_Backend(Section const &parameters, std::size_t burstSize, Scheduler &scheduler, beast::Journal journal)=0
Create a backend.
virtual std::unique_ptr< Database > make_Database(std::size_t burstSize, Scheduler &scheduler, int readThreads, Section const &backendParameters, beast::Journal journal)=0
Construct a NodeStore database.
static Manager & instance()
Returns the instance of the manager singleton.
Scheduling for asynchronous backend activity.
virtual std::optional< LedgerIndex > getMinLedgerSeq()=0
getMinLedgerSeq Returns the minimum ledger sequence in the Ledgers table.
uint256 const & as_uint256() const
Definition SHAMapHash.h:44
LedgerIndex setCanDelete(LedgerIndex canDelete)
void setState(SavedState const &state)
void init(BasicConfig const &config, std::string const &dbName)
std::condition_variable rendezvous_
std::condition_variable cond_
bool freshenCache(CacheInstance &cache)
void rendezvous() const override
NodeStore::DatabaseRotating * dbRotating_
std::chrono::milliseconds backOff_
void clearSql(LedgerIndex lastRotated, std::string const &TableName, std::function< std::optional< LedgerIndex >()> const &getMinSeq, std::function< void(LedgerIndex)> const &deleteBeforeSeq)
delete from sqlite table in batches to not lock the db excessively.
static constexpr auto nodeStoreName_
void clearPrior(LedgerIndex lastRotated)
std::atomic< LedgerIndex > canDelete_
std::unique_ptr< NodeStore::Backend > makeBackendRotating(std::string path=std::string())
TreeNodeCache * treeNodeCache_
std::uint32_t deleteInterval_
LedgerMaster * ledgerMaster_
void onLedgerClosed(std::shared_ptr< Ledger const > const &ledger) override
Called by LedgerMaster every time a ledger validates.
std::chrono::seconds recoveryWaitTime_
If the node is out of sync during an online_delete healthWait() call, sleep the thread for this time,...
std::string const dbPrefix_
std::chrono::seconds ageThreshold_
std::atomic< LedgerIndex > minimumOnline_
std::uint64_t const checkHealthInterval_
std::unique_ptr< NodeStore::Database > makeNodeStore(int readThreads) override
std::string const dbName_
std::atomic< bool > working_
FullBelowCache * fullBelowCache_
std::optional< LedgerIndex > minimumOnline() const override
The minimum ledger to try and maintain in our database.
HealthResult
This is a health check for online deletion that waits until rippled is stable before returning.
beast::Journal const journal_
NodeStore::Scheduler & scheduler_
static std::uint32_t const minimumDeletionIntervalSA_
int fdRequired() const override
Returns the number of file descriptors that are needed.
bool copyNode(std::uint64_t &nodeCount, SHAMapTreeNode const &node)
std::shared_ptr< Ledger const > newLedger_
static std::uint32_t const minimumDeletionInterval_
void clearCaches(LedgerIndex validatedSeq)
SHAMapStoreImp(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
SHAMapHash const & getHash() const
Return the hash of this node.
virtual std::optional< LedgerIndex > getAccountTransactionsMinLedgerSeq()=0
getAccountTransactionsMinLedgerSeq Returns the minimum ledger sequence stored in the AccountTransacti...
virtual void deleteAccountTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq)=0
deleteAccountTransactionsBeforeLedgerSeq Deletes all account transactions with a sequence number less...
virtual std::optional< LedgerIndex > getTransactionsMinLedgerSeq()=0
getTransactionsMinLedgerSeq Returns the minimum ledger sequence stored in the Transactions table.
virtual void deleteBeforeLedgerSeq(LedgerIndex ledgerSeq)=0
deleteBeforeLedgerSeq Deletes all ledgers with a sequence number less than or equal to the given ledg...
virtual void deleteTransactionsBeforeLedgerSeq(LedgerIndex ledgerSeq)=0
deleteTransactionsBeforeLedgerSeq Deletes all transactions with a sequence number less than or equal ...
Holds a collection of configuration values.
Definition BasicConfig.h:45
void set(std::string const &key, std::string const &value)
Set a key/value pair.
TaggedCache< uint256, Transaction > & getCache()
T compare(T... args)
T count(T... args)
T empty(T... args)
T is_same_v
T join(T... args)
T joinable(T... args)
T max(T... args)
T min(T... args)
void setCurrentThreadName(std::string_view newThreadName)
Changes the name of the caller thread.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
LedgerIndex getCanDelete(soci::session &session)
getCanDelete Returns the ledger sequence which can be deleted.
Definition State.cpp:81
constexpr auto megabytes(T value) noexcept
SavedState getSavedState(soci::session &session)
getSavedState Returns the saved state.
Definition State.cpp:99
void setSavedState(soci::session &session, SavedState const &state)
setSavedState Saves the given state.
Definition State.cpp:111
bool get_if_exists(Section const &section, std::string const &name, T &v)
OperatingMode
Specifies the mode under which the server believes it's operating.
Definition NetworkOPs.h:68
@ FULL
we have the ledger and can even validate
void initStateDB(soci::session &session, BasicConfig const &config, std::string const &dbName)
initStateDB Opens a session with the State database.
Definition State.cpp:25
LedgerIndex setCanDelete(soci::session &session, LedgerIndex canDelete)
setCanDelete Updates the ledger sequence which can be deleted.
Definition State.cpp:91
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
void setLastRotated(soci::session &session, LedgerIndex seq)
setLastRotated Updates the last rotated ledger sequence.
Definition State.cpp:123
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
STL namespace.
T push_back(T... args)
T ref(T... args)
T reset(T... args)
T size(T... args)
T sleep_for(T... args)
static std::string nodeDatabase()
LedgerIndex lastRotated
Definition State.h:37
std::string writableDb
Definition State.h:35
std::string archiveDb
Definition State.h:36
T to_string(T... args)
T what(T... args)