xrpld
Loading...
Searching...
No Matches
LedgerPersistence.cpp
1#include <xrpld/app/ledger/LedgerPersistence.h>
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/basics/base_uint.h>
5#include <xrpl/beast/utility/instrumentation.h>
6#include <xrpl/core/HashRouter.h>
7#include <xrpl/core/Job.h>
8#include <xrpl/core/JobQueue.h>
9#include <xrpl/core/ServiceRegistry.h>
10#include <xrpl/ledger/PendingSaves.h>
11#include <xrpl/protocol/Indexes.h>
12#include <xrpl/protocol/Rules.h>
13#include <xrpl/protocol/SystemParameters.h>
14#include <xrpl/rdb/RelationalDatabase.h>
15
16#include <cstdint>
17#include <memory>
18#include <optional>
19#include <string>
20#include <tuple>
21
22namespace xrpl {
23
24static bool
26 ServiceRegistry& registry,
28 bool current)
29{
30 auto j = registry.getJournal("Ledger");
31 auto seq = ledger->header().seq;
32 if (!registry.getPendingSaves().startWork(seq))
33 {
34 // The save was completed synchronously
35 JLOG(j.debug()) << "Save aborted";
36 return true;
37 }
38
39 auto& db = registry.getRelationalDatabase();
40
41 auto const res = db.saveValidatedLedger(ledger, current);
42
43 // Clients can now trust the database for
44 // information about this ledger sequence.
45 registry.getPendingSaves().finishWork(seq);
46 return res;
47}
48
49bool
51 ServiceRegistry& registry,
53 bool isSynchronous,
54 bool isCurrent)
55{
56 if (!registry.getHashRouter().setFlags(ledger->header().hash, HashRouterFlags::SAVED))
57 {
58 // We have tried to save this ledger recently
59 auto stream = registry.getJournal("Ledger").debug();
60 JLOG(stream) << "Double pend save for " << ledger->header().seq;
61
62 if (!isSynchronous || !registry.getPendingSaves().pending(ledger->header().seq))
63 {
64 // Either we don't need it to be finished
65 // or it is finished
66 return true;
67 }
68 }
69
70 XRPL_ASSERT(ledger->isImmutable(), "xrpl::pendSaveValidated : immutable ledger");
71
72 if (!registry.getPendingSaves().shouldWork(ledger->header().seq, isSynchronous))
73 {
74 auto stream = registry.getJournal("Ledger").debug();
75 JLOG(stream) << "Pend save with seq in pending saves " << ledger->header().seq;
76
77 return true;
78 }
79
80 // See if we can use the JobQueue.
81 if (!isSynchronous &&
82 registry.getJobQueue().addJob(
84 "Pub" + std::to_string(ledger->seq()),
85 [&registry, ledger, isCurrent]() { saveValidatedLedger(registry, ledger, isCurrent); }))
86 {
87 return true;
88 }
89
90 // The JobQueue won't do the Job. Do the save synchronously.
91 return saveValidatedLedger(registry, ledger, isCurrent);
92}
93
96 LedgerHeader const& info,
97 Rules const& rules,
98 Fees const& fees,
99 ServiceRegistry& registry,
100 bool acquire)
101{
102 bool loaded = false;
103 auto ledger = std::make_shared<Ledger>(
104 info,
105 loaded,
106 acquire,
107 rules,
108 fees,
109 registry.getNodeFamily(),
110 registry.getJournal("Ledger"));
111
112 if (!loaded)
113 ledger.reset();
114
115 return ledger;
116}
117
118static void
120{
121 if (!ledger)
122 return;
123
124 XRPL_ASSERT(
125 ledger->header().seq < kXrpLedgerEarliestFees || ledger->read(keylet::feeSettings()),
126 "xrpl::finishLoadByIndexOrHash : valid ledger fees");
127 ledger->setImmutable();
128
129 JLOG(j.trace()) << "Loaded ledger: " << to_string(ledger->header().hash);
130
131 ledger->setFull();
132}
133
135getLatestLedger(Rules const& rules, Fees const& fees, ServiceRegistry& registry)
136{
138 if (!info)
139 return {std::shared_ptr<Ledger>(), {}, {}};
140 return {loadLedgerHelper(*info, rules, fees, registry, true), info->seq, info->hash};
141}
142
145 std::uint32_t ledgerIndex,
146 Rules const& rules,
147 Fees const& fees,
148 ServiceRegistry& registry,
149 bool acquire)
150{
152 registry.getRelationalDatabase().getLedgerInfoByIndex(ledgerIndex))
153 {
154 std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, rules, fees, registry, acquire);
155 finishLoadByIndexOrHash(ledger, registry.getJournal("Ledger"));
156 return ledger;
157 }
158 return {};
159}
160
163 uint256 const& ledgerHash,
164 Rules const& rules,
165 Fees const& fees,
166 ServiceRegistry& registry,
167 bool acquire)
168{
170 registry.getRelationalDatabase().getLedgerInfoByHash(ledgerHash))
171 {
172 std::shared_ptr<Ledger> ledger = loadLedgerHelper(*info, rules, fees, registry, acquire);
173 finishLoadByIndexOrHash(ledger, registry.getJournal("Ledger"));
174 XRPL_ASSERT(
175 !ledger || ledger->header().hash == ledgerHash,
176 "xrpl::loadByHash : ledger hash match if loaded");
177 return ledger;
178 }
179 return {};
180}
181
182} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:38
Stream debug() const
Definition Journal.h:297
Stream trace() const
Severity stream access functions.
Definition Journal.h:291
bool setFlags(uint256 const &key, HashRouterFlags flags)
Set the flags on a hash.
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition JobQueue.h:150
void finishWork(LedgerIndex seq)
Finish working on a ledger.
bool shouldWork(LedgerIndex seq, bool isSynchronous)
Check if a ledger should be dispatched.
bool startWork(LedgerIndex seq)
Start working on a ledger.
bool pending(LedgerIndex seq)
Return true if a ledger is in the progress of being saved.
virtual bool saveValidatedLedger(std::shared_ptr< Ledger const > const &ledger, bool current)=0
saveValidatedLedger Saves a ledger into the database.
virtual std::optional< LedgerHeader > getNewestLedgerInfo()=0
getNewestLedgerInfo Returns the info of the newest saved ledger.
virtual std::optional< LedgerHeader > getLedgerInfoByHash(uint256 const &ledgerHash)=0
getLedgerInfoByHash Returns the info of the ledger with given hash.
virtual std::optional< LedgerHeader > getLedgerInfoByIndex(LedgerIndex ledgerSeq)=0
getLedgerInfoByIndex Returns a ledger by its sequence.
Rules controlling protocol behavior.
Definition Rules.h:33
Service registry for dependency injection.
virtual PendingSaves & getPendingSaves()=0
virtual JobQueue & getJobQueue()=0
virtual RelationalDatabase & getRelationalDatabase()=0
virtual beast::Journal getJournal(std::string const &name)=0
virtual HashRouter & getHashRouter()=0
virtual Family & getNodeFamily()=0
T make_shared(T... args)
Keylet const & feeSettings() noexcept
The (fixed) index of the object containing the ledger fees.
Definition Indexes.cpp:221
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Rules const &rules, Fees const &fees, ServiceRegistry &registry)
Fetch the ledger with the highest sequence contained in the database.
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
bool pendSaveValidated(ServiceRegistry &registry, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger.
std::shared_ptr< Ledger > loadLedgerHelper(LedgerHeader const &info, Rules const &rules, Fees const &fees, ServiceRegistry &registry, bool acquire)
Make ledger using info loaded from database.
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Rules const &rules, Fees const &fees, ServiceRegistry &registry, bool acquire)
Load a ledger by its sequence number.
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
static constexpr std::uint32_t kXrpLedgerEarliestFees
The XRP Ledger mainnet's earliest ledger with a FeeSettings object.
static bool saveValidatedLedger(ServiceRegistry &registry, std::shared_ptr< Ledger const > const &ledger, bool current)
@ JtPuboldledger
Definition Job.h:25
@ JtPubledger
Definition Job.h:49
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Rules const &rules, Fees const &fees, ServiceRegistry &registry, bool acquire)
Load a ledger by its hash.
BaseUInt< 256 > uint256
Definition base_uint.h:562
static void finishLoadByIndexOrHash(std::shared_ptr< Ledger > const &ledger, beast::Journal j)
Reflects the fee settings for a particular ledger.
Information about the notional ledger backing the view.
T to_string(T... args)