20#include <xrpld/app/ledger/InboundLedgers.h>
21#include <xrpld/app/ledger/LedgerReplayTask.h>
22#include <xrpld/app/ledger/LedgerReplayer.h>
23#include <xrpld/app/ledger/detail/LedgerDeltaAcquire.h>
24#include <xrpld/app/ledger/detail/SkipListAcquire.h>
25#include <xrpld/core/JobQueue.h>
31 uint256 const& finishLedgerHash,
33 : reason_(r), finishHash_(finishLedgerHash), totalLedgers_(totalNumLedgers)
36 finishLedgerHash.
isNonZero() && totalNumLedgers > 0,
37 "ripple::LedgerReplayTask::TaskParameter::TaskParameter : valid "
47 if (finishHash_ != hash || sList.
size() + 1 < totalLedgers_ || full_)
53 startHash_ = skipList_[skipList_.size() - totalLedgers_];
55 startHash_.isNonZero(),
56 "ripple::LedgerReplayTask::TaskParameter::update : nonzero start hash");
57 startSeq_ = finishSeq_ - totalLedgers_ + 1;
66 if (reason_ == existingTask.
reason_)
74 if (existingTask.
full_)
76 auto const& exList = existingTask.
skipList_;
77 if (
auto i =
std::find(exList.begin(), exList.end(), finishHash_);
81 totalLedgers_ + (exList.end() - i) - 1;
97 parameter.finishHash_,
98 LedgerReplayParameters::TASK_TIMEOUT,
102 app.journal(
"LedgerReplayTask"))
103 , inboundLedgers_(inboundLedgers)
104 , replayer_(replayer)
105 , parameter_(parameter)
108 parameter.totalLedgers_ *
110 , skipListAcquirer_(skipListAcquirer)
112 JLOG(journal_.trace()) <<
"Create " << hash_;
127 if (
auto sptr = wptr.
lock(); sptr)
135 auto const skipListData = sptr->skipListAcquirer_->getData();
136 sptr->updateSkipList(
137 hash, skipListData->ledgerSeq, skipListData->skipList);
142 ScopedLockType sl(mtx_);
153 JLOG(journal_.trace()) <<
"trigger " << hash_;
154 if (!parameter_.full_)
159 parent_ = app_.getLedgerMaster().getLedgerByHash(parameter_.startHash_);
162 parent_ = inboundLedgers_.acquire(
163 parameter_.startHash_,
164 parameter_.startSeq_,
165 InboundLedger::Reason::GENERIC);
169 JLOG(journal_.trace())
170 <<
"Got start ledger " << parameter_.startHash_ <<
" for task "
179LedgerReplayTask::deltaReady(
uint256 const& deltaHash)
181 JLOG(journal_.trace()) <<
"Delta " << deltaHash <<
" ready for task "
191 JLOG(journal_.trace()) <<
"tryAdvance task " << hash_
192 << (parameter_.full_ ?
", full parameter"
193 :
", waiting to fill parameter")
194 <<
", deltaIndex=" << deltaToBuild_
195 <<
", totalDeltas=" << deltas_.size() <<
", parent "
196 << (parent_ ? parent_->info().hash :
uint256());
198 bool shouldTry = parent_ && parameter_.full_ &&
199 parameter_.totalLedgers_ - 1 == deltas_.size();
205 for (; deltaToBuild_ < deltas_.size(); ++deltaToBuild_)
207 auto& delta = deltas_[deltaToBuild_];
209 parent_->seq() + 1 == delta->ledgerSeq_,
210 "ripple::LedgerReplayTask::tryAdvance : consecutive sequence");
211 if (
auto l = delta->tryBuild(parent_); l)
213 JLOG(journal_.debug())
214 <<
"Task " << hash_ <<
" got ledger " << l->info().hash
215 <<
" deltaIndex=" << deltaToBuild_
216 <<
" totalDeltas=" << deltas_.size();
224 JLOG(journal_.info()) <<
"Completed " << hash_;
233LedgerReplayTask::updateSkipList(
242 if (!parameter_.update(hash, seq, sList))
244 JLOG(journal_.error()) <<
"Parameter update failed " << hash_;
250 replayer_.createDeltas(shared_from_this());
259 JLOG(journal_.trace()) <<
"mTimeouts=" << timeouts_ <<
" for " << hash_;
260 if (timeouts_ > maxTimeouts_)
263 JLOG(journal_.debug())
264 <<
"LedgerReplayTask Failed, too many timeouts " << hash_;
273LedgerReplayTask::pmDowncast()
275 return shared_from_this();
282 delta->addDataCallback(
283 parameter_.reason_, [wptr](
bool good,
uint256 const& hash) {
284 if (auto sptr = wptr.lock(); sptr)
289 sptr->deltaReady(hash);
293 ScopedLockType sl(mtx_);
296 JLOG(journal_.trace())
297 <<
"addDelta task " << hash_ <<
" deltaIndex=" << deltaToBuild_
298 <<
" totalDeltas=" << deltas_.size();
301 deltas_.back()->ledgerSeq_ + 1 == delta->ledgerSeq_,
302 "ripple::LedgerReplayTask::addDelta : no deltas or consecutive "
304 deltas_.push_back(delta);
309LedgerReplayTask::finished()
const
Stream trace() const
Severity stream access functions.
Manages the lifetime of inbound ledgers.
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
std::vector< uint256 > skipList_
InboundLedger::Reason reason_
std::uint32_t totalLedgers_
void init()
Start the task.
std::shared_ptr< SkipListAcquire > skipListAcquirer_
LedgerReplayTask(Application &app, InboundLedgers &inboundLedgers, LedgerReplayer &replayer, std::shared_ptr< SkipListAcquire > &skipListAcquirer, TaskParameter &¶meter)
Constructor.
Manages the lifetime of ledger replay tasks.
This class is an "active" object.
uint256 const hash_
The hash of the object (in practice, always a ledger) we are trying to fetch.
T emplace_back(T... args)
std::uint32_t constexpr TASK_MAX_TIMEOUTS_MINIMUM
std::uint32_t constexpr MAX_QUEUED_TASKS
std::uint32_t constexpr TASK_MAX_TIMEOUTS_MULTIPLIER
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T shared_from_this(T... args)