rippled
Loading...
Searching...
No Matches
LedgerReplayTask.cpp
1#include <xrpld/app/ledger/InboundLedgers.h>
2#include <xrpld/app/ledger/LedgerReplayTask.h>
3#include <xrpld/app/ledger/LedgerReplayer.h>
4#include <xrpld/app/ledger/detail/LedgerDeltaAcquire.h>
5#include <xrpld/app/ledger/detail/SkipListAcquire.h>
6
7namespace xrpl {
8
11 uint256 const& finishLedgerHash,
12 std::uint32_t totalNumLedgers)
13 : reason_(r), finishHash_(finishLedgerHash), totalLedgers_(totalNumLedgers)
14{
15 XRPL_ASSERT(
16 finishLedgerHash.isNonZero() && totalNumLedgers > 0,
17 "xrpl::LedgerReplayTask::TaskParameter::TaskParameter : valid "
18 "inputs");
19}
20
21bool
23 uint256 const& hash,
24 std::uint32_t seq,
25 std::vector<uint256> const& sList)
26{
27 if (finishHash_ != hash || sList.size() + 1 < totalLedgers_ || full_)
28 return false;
29
30 finishSeq_ = seq;
31 skipList_ = sList;
32 skipList_.emplace_back(finishHash_);
33 startHash_ = skipList_[skipList_.size() - totalLedgers_];
34 XRPL_ASSERT(
35 startHash_.isNonZero(),
36 "xrpl::LedgerReplayTask::TaskParameter::update : nonzero start hash");
37 startSeq_ = finishSeq_ - totalLedgers_ + 1;
38 full_ = true;
39 return true;
40}
41
42bool
44{
45 if (reason_ == existingTask.reason_)
46 {
47 if (finishHash_ == existingTask.finishHash_ && totalLedgers_ <= existingTask.totalLedgers_)
48 {
49 return true;
50 }
51
52 if (existingTask.full_)
53 {
54 auto const& exList = existingTask.skipList_;
55 if (auto i = std::find(exList.begin(), exList.end(), finishHash_); i != exList.end())
56 {
57 return existingTask.totalLedgers_ >= totalLedgers_ + (exList.end() - i) - 1;
58 }
59 }
60 }
61
62 return false;
63}
64
66 Application& app,
67 InboundLedgers& inboundLedgers,
68 LedgerReplayer& replayer,
69 std::shared_ptr<SkipListAcquire>& skipListAcquirer,
70 TaskParameter&& parameter)
72 app,
73 parameter.finishHash_,
74 LedgerReplayParameters::TASK_TIMEOUT,
76 app.journal("LedgerReplayTask"))
77 , inboundLedgers_(inboundLedgers)
78 , replayer_(replayer)
79 , parameter_(parameter)
80 , maxTimeouts_(
84 , skipListAcquirer_(skipListAcquirer)
85{
86 JLOG(journal_.trace()) << "Create " << hash_;
87}
88
90{
91 JLOG(journal_.trace()) << "Destroy " << hash_;
92}
93
94void
96{
97 JLOG(journal_.debug()) << "Task start " << hash_;
98
100 skipListAcquirer_->addDataCallback([wptr](bool good, uint256 const& hash) {
101 if (auto sptr = wptr.lock(); sptr)
102 {
103 if (!good)
104 {
105 sptr->cancel();
106 }
107 else
108 {
109 auto const skipListData = sptr->skipListAcquirer_->getData();
110 sptr->updateSkipList(hash, skipListData->ledgerSeq, skipListData->skipList);
111 }
112 }
113 });
114
116 if (!isDone())
117 {
118 trigger(sl);
119 setTimer(sl);
120 }
121}
122
123void
125{
126 JLOG(journal_.trace()) << "trigger " << hash_;
127 if (!parameter_.full_)
128 return;
129
130 if (!parent_)
131 {
133 if (!parent_)
134 {
137 }
138 if (parent_)
139 {
140 JLOG(journal_.trace())
141 << "Got start ledger " << parameter_.startHash_ << " for task " << hash_;
142 }
143 }
144
145 tryAdvance(sl);
146}
147
148void
150{
151 JLOG(journal_.trace()) << "Delta " << deltaHash << " ready for task " << hash_;
153 if (!isDone())
154 tryAdvance(sl);
155}
156
157void
159{
160 JLOG(journal_.trace()) << "tryAdvance task " << hash_
161 << (parameter_.full_ ? ", full parameter"
162 : ", waiting to fill parameter")
163 << ", deltaIndex=" << deltaToBuild_ << ", totalDeltas=" << deltas_.size()
164 << ", parent " << (parent_ ? parent_->header().hash : uint256());
165
166 bool shouldTry = parent_ && parameter_.full_ && parameter_.totalLedgers_ - 1 == deltas_.size();
167 if (!shouldTry)
168 return;
169
170 try
171 {
172 for (; deltaToBuild_ < deltas_.size(); ++deltaToBuild_)
173 {
174 auto& delta = deltas_[deltaToBuild_];
175 XRPL_ASSERT(
176 parent_->seq() + 1 == delta->ledgerSeq_,
177 "xrpl::LedgerReplayTask::tryAdvance : consecutive sequence");
178 if (auto l = delta->tryBuild(parent_); l)
179 {
180 JLOG(journal_.debug())
181 << "Task " << hash_ << " got ledger " << l->header().hash
182 << " deltaIndex=" << deltaToBuild_ << " totalDeltas=" << deltas_.size();
183 parent_ = l;
184 }
185 else
186 return;
187 }
188
189 complete_ = true;
190 JLOG(journal_.info()) << "Completed " << hash_;
191 }
192 catch (std::runtime_error const&)
193 {
194 failed_ = true;
195 }
196}
197
198void
200 uint256 const& hash,
201 std::uint32_t seq,
202 std::vector<uint256> const& sList)
203{
204 {
206 if (isDone())
207 return;
208 if (!parameter_.update(hash, seq, sList))
209 {
210 JLOG(journal_.error()) << "Parameter update failed " << hash_;
211 failed_ = true;
212 return;
213 }
214 }
215
218 if (!isDone())
219 trigger(sl);
220}
221
222void
224{
225 JLOG(journal_.trace()) << "mTimeouts=" << timeouts_ << " for " << hash_;
227 {
228 failed_ = true;
229 JLOG(journal_.debug()) << "LedgerReplayTask Failed, too many timeouts " << hash_;
230 }
231 else
232 {
233 trigger(sl);
234 }
235}
236
242
243void
245{
247 delta->addDataCallback(parameter_.reason_, [wptr](bool good, uint256 const& hash) {
248 if (auto sptr = wptr.lock(); sptr)
249 {
250 if (!good)
251 sptr->cancel();
252 else
253 sptr->deltaReady(hash);
254 }
255 });
256
257 ScopedLockType sl(mtx_);
258 if (!isDone())
259 {
260 JLOG(journal_.trace()) << "addDelta task " << hash_ << " deltaIndex=" << deltaToBuild_
261 << " totalDeltas=" << deltas_.size();
262 XRPL_ASSERT(
263 deltas_.empty() || deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_,
264 "xrpl::LedgerReplayTask::addDelta : no deltas or consecutive "
265 "sequence");
266 deltas_.push_back(delta);
267 }
268}
269
270bool
271LedgerReplayTask::finished() const
272{
273 ScopedLockType sl(mtx_);
274 return isDone();
275}
276
277} // namespace xrpl
Stream error() const
Definition Journal.h:319
Stream debug() const
Definition Journal.h:301
Stream info() const
Definition Journal.h:307
Stream trace() const
Severity stream access functions.
Definition Journal.h:295
Manages the lifetime of inbound ledgers.
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
TaskParameter(InboundLedger::Reason r, uint256 const &finishLedgerHash, std::uint32_t totalNumLedgers)
constructor
bool update(uint256 const &hash, std::uint32_t seq, std::vector< uint256 > const &sList)
fill all the fields that was not filled during construction
bool canMergeInto(TaskParameter const &existingTask) const
check if this task can be merged into an existing task
void trigger(ScopedLockType &sl)
Trigger another round.
void onTimer(bool progress, ScopedLockType &sl) override
Hook called from invokeOnTimer().
LedgerReplayer & replayer_
LedgerReplayTask(Application &app, InboundLedgers &inboundLedgers, LedgerReplayer &replayer, std::shared_ptr< SkipListAcquire > &skipListAcquirer, TaskParameter &&parameter)
Constructor.
InboundLedgers & inboundLedgers_
void updateSkipList(uint256 const &hash, std::uint32_t seq, std::vector< uint256 > const &sList)
Update this task (by a SkipListAcquire subtask) when skip list is ready.
void tryAdvance(ScopedLockType &sl)
Try to build more ledgers.
void deltaReady(uint256 const &deltaHash)
Notify this task (by a LedgerDeltaAcquire subtask) that a delta is ready.
std::weak_ptr< TimeoutCounter > pmDowncast() override
Return a weak pointer to this.
std::vector< std::shared_ptr< LedgerDeltaAcquire > > deltas_
void addDelta(std::shared_ptr< LedgerDeltaAcquire > const &delta)
add a new LedgerDeltaAcquire subtask
std::shared_ptr< Ledger const > parent_
std::shared_ptr< SkipListAcquire > skipListAcquirer_
void init()
Start the task.
Manages the lifetime of ledger replay tasks.
void createDeltas(std::shared_ptr< LedgerReplayTask > task)
Create LedgerDeltaAcquire subtasks for the LedgerReplayTask task.
virtual LedgerMaster & getLedgerMaster()=0
This class is an "active" object.
std::recursive_mutex mtx_
uint256 const hash_
The hash of the object (in practice, always a ledger) we are trying to fetch.
beast::Journal journal_
void setTimer(ScopedLockType &)
Schedule a call to queueJob() after mTimerInterval.
static constexpr std::size_t size()
Definition base_uint.h:497
bool isNonZero() const
Definition base_uint.h:516
T emplace_back(T... args)
T find(T... args)
T lock(T... args)
T max(T... args)
std::uint32_t constexpr TASK_MAX_TIMEOUTS_MINIMUM
std::uint32_t constexpr TASK_MAX_TIMEOUTS_MULTIPLIER
std::uint32_t constexpr MAX_QUEUED_TASKS
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
base_uint< 256 > uint256
Definition base_uint.h:529
@ jtREPLAY_TASK
Definition Job.h:40
T size(T... args)