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

View File

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

View File

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

View File

@@ -35,20 +35,18 @@ class PathState : public CountedObject <PathState>
using Ptr = std::shared_ptr<PathState>; using Ptr = std::shared_ptr<PathState>;
using List = std::vector<Ptr>; using List = std::vector<Ptr>;
PathState (STAmount const& saSend, STAmount const& saSendMax) PathState (MetaView& view, STAmount const& saSend, STAmount const& saSendMax)
: mIndex (0) : metaView_ (view)
, mIndex (0)
, uQuality (0) , uQuality (0)
, saInReq (saSendMax) , saInReq (saSendMax)
, saOutReq (saSend) , saOutReq (saSend)
{ {
} }
explicit PathState (const PathState& psSrc) = default;
void reset(STAmount const& in, STAmount const& out); void reset(STAmount const& in, STAmount const& out);
TER expandPath ( TER expandPath (
MetaView const& viewSource,
STPath const& spSourcePath, STPath const& spSourcePath,
AccountID const& uReceiverID, AccountID const& uReceiverID,
AccountID const& uSenderID AccountID const& uSenderID
@@ -105,7 +103,12 @@ class PathState : public CountedObject <PathState>
MetaView& metaView() MetaView& metaView()
{ {
return *metaView_; return metaView_;
}
void resetView (MetaView& view)
{
reconstruct (metaView_, view);
} }
bool isDry() const bool isDry() const
@@ -149,7 +152,7 @@ private:
// Source may only be used there if not mentioned by an account. // Source may only be used there if not mentioned by an account.
AccountIssueToNodeIndex umReverse; AccountIssueToNodeIndex umReverse;
boost::optional<MetaView> metaView_; MetaView metaView_;
int mIndex; // Index/rank amoung siblings. int mIndex; // Index/rank amoung siblings.
std::uint64_t uQuality; // 0 = no quality/liquity left. 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) bool RippleCalc::addPathState(STPath const& path, TER& resultCode)
{ {
auto pathState = std::make_shared<PathState> ( auto pathState = std::make_shared<PathState> (
saDstAmountReq_, saMaxAmountReq_); metaView, saDstAmountReq_, saMaxAmountReq_);
if (!pathState) if (!pathState)
{ {
@@ -103,7 +103,6 @@ bool RippleCalc::addPathState(STPath const& path, TER& resultCode)
} }
pathState->expandPath ( pathState->expandPath (
metaView,
path, path,
uDstAccountID_, uDstAccountID_,
uSrcAccountID_); uSrcAccountID_);
@@ -208,7 +207,6 @@ TER RippleCalc::rippleCalculate ()
while (resultCode == temUNCERTAIN) while (resultCode == temUNCERTAIN)
{ {
int iBest = -1; int iBest = -1;
MetaView lesCheckpoint = metaView;
int iDry = 0; int iDry = 0;
// True, if ever computed multi-quality. // True, if ever computed multi-quality.
@@ -228,7 +226,7 @@ TER RippleCalc::rippleCalculate ()
// Error if done, output met. // Error if done, output met.
PathCursor pc(*this, *pathState, multiQuality); PathCursor pc(*this, *pathState, multiQuality);
pc.nextIncrement (lesCheckpoint); pc.nextIncrement ();
// Compute increment. // Compute increment.
WriteLog (lsDEBUG, RippleCalc) WriteLog (lsDEBUG, RippleCalc)
@@ -287,13 +285,6 @@ TER RippleCalc::rippleCalculate ()
<< " inPass()=" << pathState->inPass() << " inPass()=" << pathState->inPass()
<< " saOutPass=" << pathState->outPass(); << " 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 (); iBest = pathState->index ();
} }
} }
@@ -339,14 +330,9 @@ TER RippleCalc::rippleCalculate ()
pathState->unfundedOffers().begin (), pathState->unfundedOffers().begin (),
pathState->unfundedOffers().end ()); pathState->unfundedOffers().end ());
// Record best pass' MetaView to build off of and potentially // Apply best pass' MetaView
// return.
assert (pathState->metaView().isValid ()); assert (pathState->metaView().isValid ());
metaView.swapWith (pathState->metaView()); pathState->metaView().apply();
// VFALCO Why is this needed? Can it be done
// without the function call?
pathState->metaView().deprecatedInvalidate();
actualAmountIn_ += pathState->inPass(); actualAmountIn_ += pathState->inPass();
actualAmountOut_ += pathState->outPass(); actualAmountOut_ += pathState->outPass();
@@ -421,10 +407,7 @@ TER RippleCalc::rippleCalculate ()
} }
else else
{ {
// We must restore the activeLedger from lesCheckpoint in the case // Don't apply any payment increments
// when iBest is -1 and just before the result is set to tesSUCCESS.
metaView.swapWith (lesCheckpoint);
resultCode = tesSUCCESS; resultCode = tesSUCCESS;
} }
} }

View File

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

View File

@@ -25,13 +25,12 @@
namespace ripple { namespace ripple {
namespace path { namespace path {
TER PathCursor::liquidity (MetaView const& lesCheckpoint) const TER PathCursor::liquidity () const
{ {
TER resultCode = tecPATH_DRY; TER resultCode = tecPATH_DRY;
PathCursor pc = *this; PathCursor pc = *this;
// duplicate pathState_.resetView (rippleCalc_.metaView);
reconstruct(rippleCalc_.metaView, lesCheckpoint);
for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; ) for (pc.nodeIndex_ = pc.nodeSize(); pc.nodeIndex_--; )
{ {
@@ -60,9 +59,7 @@ TER PathCursor::liquidity (MetaView const& lesCheckpoint) const
if (resultCode != tesSUCCESS) if (resultCode != tesSUCCESS)
return resultCode; return resultCode;
// Do forward. pathState_.resetView (rippleCalc_.metaView);
// duplicate
reconstruct(rippleCalc_.metaView, lesCheckpoint);
for (pc.nodeIndex_ = 0; pc.nodeIndex_ < pc.nodeSize(); ++pc.nodeIndex_) 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 // This is the wrapper that restores a checkpointed version of the ledger so we
// can write all over it without consequence. // 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. // The next state is what is available in preference order.
// This is calculated when referenced accounts changed. // This is calculated when referenced accounts changed.
@@ -42,7 +42,7 @@ void PathCursor::nextIncrement (MetaView const& lesCheckpoint) const
// WriteLog (lsTRACE, RippleCalc) // WriteLog (lsTRACE, RippleCalc)
// << "nextIncrement: Path In: " << pathState_.getJson (); // << "nextIncrement: Path In: " << pathState_.getJson ();
auto status = liquidity(lesCheckpoint); auto status = liquidity();
if (status == tesSUCCESS) if (status == tesSUCCESS)
{ {

View File

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

View File

@@ -59,6 +59,10 @@ public:
STAmount const& amount); STAmount const& amount);
void clear (); 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 } // ripple

View File

@@ -147,5 +147,16 @@ void DeferredCredits::clear ()
map_.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 } // ripple