Use new MetaView functionality in RippleCalc (RIPD-954):

RippleCalc is changed to stack views when calculating results
instead of making a copy of the MetaView, improving efficiency.
This commit is contained in:
JoelKatz
2015-06-23 10:31:35 -07:00
committed by Vinnie Falco
parent 2f485672fa
commit f535304e1b
11 changed files with 89 additions and 65 deletions

View File

@@ -94,6 +94,7 @@ private:
using list_type = std::map<uint256, Item>;
BasicView* parent_;
MetaView* mParent_ = NULL;
list_type items_;
boost::optional<DeferredCredits> mDeferredCredits;
TransactionMetaSet mSet;
@@ -115,13 +116,9 @@ public:
MetaView (Ledger::ref ledger,
TransactionEngineParams tep);
/** Construct a copy.
Effects:
The copy is identical except that
the sequence number is one higher.
/** Construct a nested view.
*/
// DEPRECATED
MetaView (MetaView const&);
MetaView (MetaView&);
//--------------------------------------------------------------------------
//

View File

@@ -69,16 +69,18 @@ MetaView::MetaView (Ledger::ref ledger,
{
}
MetaView::MetaView (MetaView const& other)
: parent_(other.parent_)
MetaView::MetaView (MetaView& other)
: parent_(&other)
, mParent_(&other)
, items_(other.items_)
, mDeferredCredits(other.mDeferredCredits)
, mSet(other.mSet)
// VFALCO NOTE This is a change in behavior,
// previous version set tapNONE
, mParams(other.mParams)
, mSeq(other.mSeq + 1)
{
if (other.mDeferredCredits)
mDeferredCredits.emplace();
}
//------------------------------------------------------------------------------
@@ -279,8 +281,23 @@ MetaView::deprecatedBalance(
STAmount const& amount) const
{
if (mDeferredCredits)
{
if (mParent_)
{
assert (mParent_->mDeferredCredits);
return mDeferredCredits->adjustedBalance(
account, issuer, mParent_->deprecatedBalance(account, issuer, amount));
}
return mDeferredCredits->adjustedBalance(
account, issuer, amount);
}
else if (mParent_ && mParent_->mDeferredCredits)
{
return mParent_->mDeferredCredits->adjustedBalance(
account, issuer, amount);
}
return amount;
}
@@ -422,6 +439,7 @@ MetaView::deprecatedCreditHint(
void MetaView::apply()
{
// Write back the account states
for (auto& item : items_)
{
@@ -433,7 +451,7 @@ void MetaView::apply()
{
case taaCACHED:
assert(parent_->exists(
keylet::child(item.first)));
Keylet(sle->getType(), item.first)));
break;
case taaCREATE:
@@ -458,6 +476,20 @@ void MetaView::apply()
break;
}
}
if (mDeferredCredits)
{
assert (mParent_ != NULL);
if (mParent_->areCreditsDeferred())
{
for (auto& credit : *mDeferredCredits)
{
// This will go away soon
mParent_->mDeferredCredits->merge (credit);
}
}
}
// Safety precaution since we moved the
// entries out, apply() cannot be called twice.
items_.clear();

View File

@@ -268,7 +268,7 @@ TER PathState::pushNode (
auto const& backNode = nodes_.back ();
if (backNode.isAccount())
{
auto sleRippleState = metaView_->peek(
auto sleRippleState = metaView_.peek(
keylet::line(backNode.account_, node.account_, backNode.issue_.currency));
// A "RippleState" means a balance betweeen two accounts for a
@@ -291,7 +291,7 @@ TER PathState::pushNode (
<< backNode.account_ << " and " << node.account_
<< " for " << node.issue_.currency << "." ;
auto sleBck = metaView_->peek (
auto sleBck = metaView_.peek (
keylet::account(backNode.account_));
// Is the source account the highest numbered account ID?
bool bHigh = backNode.account_ > node.account_;
@@ -318,13 +318,13 @@ TER PathState::pushNode (
if (resultCode == tesSUCCESS)
{
STAmount saOwed = creditBalance (*metaView_,
STAmount saOwed = creditBalance (metaView_,
node.account_, backNode.account_,
node.issue_.currency);
STAmount saLimit;
if (saOwed <= zero) {
saLimit = creditLimit (*metaView_,
saLimit = creditLimit (metaView_,
node.account_,
backNode.account_,
node.issue_.currency);
@@ -413,7 +413,6 @@ TER PathState::pushNode (
// terStatus = tesSUCCESS, temBAD_PATH, terNO_LINE, terNO_ACCOUNT, terNO_AUTH,
// or temBAD_PATH_LOOP
TER PathState::expandPath (
MetaView const& viewSource,
STPath const& spSourcePath,
AccountID const& uReceiverID,
AccountID const& uSenderID)
@@ -432,8 +431,6 @@ TER PathState::expandPath (
WriteLog (lsTRACE, RippleCalc)
<< "expandPath> " << spSourcePath.getJson (0);
metaView_.emplace(viewSource);
terStatus = tesSUCCESS;
// XRP with issuer is malformed.
@@ -627,7 +624,7 @@ void PathState::checkFreeze()
// Check each order book for a global freeze
if (nodes_[i].uFlags & STPathElement::typeIssuer)
{
sle = metaView_->peek (keylet::account(nodes_[i].issue_.account));
sle = metaView_.peek (keylet::account(nodes_[i].issue_.account));
if (sle && sle->isFlag (lsfGlobalFreeze))
{
@@ -645,7 +642,7 @@ void PathState::checkFreeze()
if (inAccount != outAccount)
{
sle = metaView_->peek (keylet::account(outAccount));
sle = metaView_.peek (keylet::account(outAccount));
if (sle && sle->isFlag (lsfGlobalFreeze))
{
@@ -653,7 +650,7 @@ void PathState::checkFreeze()
return;
}
sle = metaView_->peek (keylet::line(inAccount,
sle = metaView_.peek (keylet::line(inAccount,
outAccount, currencyID));
if (sle && sle->isFlag (
@@ -680,9 +677,9 @@ TER PathState::checkNoRipple (
Currency const& currency)
{
// fetch the ripple lines into and out of this node
SLE::pointer sleIn = metaView_->peek (
SLE::pointer sleIn = metaView_.peek (
keylet::line(firstAccount, secondAccount, currency));
SLE::pointer sleOut = metaView_->peek (
SLE::pointer sleOut = metaView_.peek (
keylet::line(secondAccount, thirdAccount, currency));
if (!sleIn || !sleOut)

View File

@@ -35,20 +35,18 @@ class PathState : public CountedObject <PathState>
using Ptr = std::shared_ptr<PathState>;
using List = std::vector<Ptr>;
PathState (STAmount const& saSend, STAmount const& saSendMax)
: mIndex (0)
PathState (MetaView& view, STAmount const& saSend, STAmount const& saSendMax)
: metaView_ (view)
, mIndex (0)
, uQuality (0)
, saInReq (saSendMax)
, saOutReq (saSend)
{
}
explicit PathState (const PathState& psSrc) = default;
void reset(STAmount const& in, STAmount const& out);
TER expandPath (
MetaView const& viewSource,
STPath const& spSourcePath,
AccountID const& uReceiverID,
AccountID const& uSenderID
@@ -105,7 +103,12 @@ class PathState : public CountedObject <PathState>
MetaView& metaView()
{
return *metaView_;
return metaView_;
}
void resetView (MetaView& view)
{
reconstruct (metaView_, view);
}
bool isDry() const
@@ -149,7 +152,7 @@ private:
// Source may only be used there if not mentioned by an account.
AccountIssueToNodeIndex umReverse;
boost::optional<MetaView> metaView_;
MetaView metaView_;
int mIndex; // Index/rank amoung siblings.
std::uint64_t uQuality; // 0 = no quality/liquity left.

View File

@@ -94,7 +94,7 @@ RippleCalc::Output RippleCalc::rippleCalculate (
bool RippleCalc::addPathState(STPath const& path, TER& resultCode)
{
auto pathState = std::make_shared<PathState> (
saDstAmountReq_, saMaxAmountReq_);
metaView, saDstAmountReq_, saMaxAmountReq_);
if (!pathState)
{
@@ -103,7 +103,6 @@ bool RippleCalc::addPathState(STPath const& path, TER& resultCode)
}
pathState->expandPath (
metaView,
path,
uDstAccountID_,
uSrcAccountID_);
@@ -208,7 +207,6 @@ TER RippleCalc::rippleCalculate ()
while (resultCode == temUNCERTAIN)
{
int iBest = -1;
MetaView lesCheckpoint = metaView;
int iDry = 0;
// True, if ever computed multi-quality.
@@ -228,7 +226,7 @@ TER RippleCalc::rippleCalculate ()
// Error if done, output met.
PathCursor pc(*this, *pathState, multiQuality);
pc.nextIncrement (lesCheckpoint);
pc.nextIncrement ();
// Compute increment.
WriteLog (lsDEBUG, RippleCalc)
@@ -287,13 +285,6 @@ TER RippleCalc::rippleCalculate ()
<< " inPass()=" << pathState->inPass()
<< " saOutPass=" << pathState->outPass();
assert (metaView.isValid ());
metaView.swapWith (pathState->metaView());
// For the path, save ledger state.
// VFALCO Can this be done without the function call?
metaView.deprecatedInvalidate();
iBest = pathState->index ();
}
}
@@ -339,14 +330,9 @@ TER RippleCalc::rippleCalculate ()
pathState->unfundedOffers().begin (),
pathState->unfundedOffers().end ());
// Record best pass' MetaView to build off of and potentially
// return.
// Apply best pass' MetaView
assert (pathState->metaView().isValid ());
metaView.swapWith (pathState->metaView());
// VFALCO Why is this needed? Can it be done
// without the function call?
pathState->metaView().deprecatedInvalidate();
pathState->metaView().apply();
actualAmountIn_ += pathState->inPass();
actualAmountOut_ += pathState->outPass();
@@ -421,10 +407,7 @@ TER RippleCalc::rippleCalculate ()
}
else
{
// We must restore the activeLedger from lesCheckpoint in the case
// when iBest is -1 and just before the result is set to tesSUCCESS.
metaView.swapWith (lesCheckpoint);
// Don't apply any payment increments
resultCode = tesSUCCESS;
}
}

View File

@@ -98,11 +98,10 @@ public:
STPathSet const& spsPaths,
Input const* const pInputs = nullptr);
/** The active ledger. */
// VFALCO TODO Fix this comment its not the ledger
// VFALCO TODO Rename this to view
// The view we are currently working on
MetaView& metaView;
// If the transaction fails to meet some constraint, still need to delete
// unfunded offers.
//

View File

@@ -25,13 +25,12 @@
namespace ripple {
namespace path {
TER PathCursor::liquidity (MetaView const& lesCheckpoint) const
TER PathCursor::liquidity () const
{
TER resultCode = tecPATH_DRY;
PathCursor pc = *this;
// duplicate
reconstruct(rippleCalc_.metaView, lesCheckpoint);
pathState_.resetView (rippleCalc_.metaView);
for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; )
{
@@ -60,9 +59,7 @@ TER PathCursor::liquidity (MetaView const& lesCheckpoint) const
if (resultCode != tesSUCCESS)
return resultCode;
// Do forward.
// duplicate
reconstruct(rippleCalc_.metaView, lesCheckpoint);
pathState_.resetView (rippleCalc_.metaView);
for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_)
{

View File

@@ -34,7 +34,7 @@ namespace path {
// This is the wrapper that restores a checkpointed version of the ledger so we
// can write all over it without consequence.
void PathCursor::nextIncrement (MetaView const& lesCheckpoint) const
void PathCursor::nextIncrement () const
{
// The next state is what is available in preference order.
// This is calculated when referenced accounts changed.
@@ -42,7 +42,7 @@ void PathCursor::nextIncrement (MetaView const& lesCheckpoint) const
// WriteLog (lsTRACE, RippleCalc)
// << "nextIncrement: Path In: " << pathState_.getJson ();
auto status = liquidity(lesCheckpoint);
auto status = liquidity();
if (status == tesSUCCESS)
{

View File

@@ -50,7 +50,7 @@ public:
{
}
void nextIncrement(MetaView const& checkpoint) const;
void nextIncrement() const;
private:
PathCursor(PathCursor const&) = default;
@@ -60,7 +60,7 @@ private:
return {rippleCalc_, pathState_, multiQuality_, nodeIndex_ + delta};
}
TER liquidity(MetaView const& lesCheckpoint) const;
TER liquidity() const;
TER reverseLiquidity () const;
TER forwardLiquidity () const;
@@ -95,7 +95,8 @@ private:
MetaView& ledger() const
{
// VFALCO Rename metaView to view
return rippleCalc_.metaView;
//return rippleCalc_.metaView;
return pathState_.metaView();
}
NodeIndex nodeSize() const

View File

@@ -59,6 +59,10 @@ public:
STAmount const& amount);
void clear ();
std::map<Key, Value>::iterator begin() { return map_.begin(); }
std::map<Key, Value>::iterator end() { return map_.end(); }
void merge (std::pair <Key, Value> const& p);
};
} // ripple

View File

@@ -147,5 +147,16 @@ void DeferredCredits::clear ()
map_.clear ();
}
void DeferredCredits::merge (std::pair <Key, Value> const& p)
{
using std::get;
auto r = map_.emplace(p);
if (!r.second)
{
get<0>(r.first->second) += get<0>(p.second);
get<1>(r.first->second) += get<1>(p.second);
}
}
} // ripple