mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 14:35:52 +00:00
Path finding fixes:
Track path finding and order book creation time and latency. Use a ledger snapshot for path finding. You can't call getCurrentLedger from an unlocked context. Pathfinding called from the transaction sign function held the master lock.
This commit is contained in:
@@ -56,6 +56,8 @@ const char* Job::toString(JobType t)
|
||||
case jtRPC: return "rpc";
|
||||
case jtACCEPTLEDGER: return "acceptLedger";
|
||||
case jtTXN_PROC: return "processTransaction";
|
||||
case jtOB_SETUP: return "orderBookSetup";
|
||||
case jtPATH_FIND: return "pathFind";
|
||||
default: assert(false); return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,13 +37,15 @@ enum JobType
|
||||
jtDEATH = 14, // job of death, used internally
|
||||
|
||||
// special types not dispatched by the job pool
|
||||
jtPEER = 17,
|
||||
jtDISK = 18,
|
||||
jtRPC = 19,
|
||||
jtACCEPTLEDGER = 20,
|
||||
jtTXN_PROC = 21,
|
||||
jtPEER = 24,
|
||||
jtDISK = 25,
|
||||
jtRPC = 26,
|
||||
jtACCEPTLEDGER = 27,
|
||||
jtTXN_PROC = 28,
|
||||
jtOB_SETUP = 29,
|
||||
jtPATH_FIND = 30
|
||||
}; // CAUTION: If you add new types, add them to JobType.cpp too
|
||||
#define NUM_JOB_TYPES 24
|
||||
#define NUM_JOB_TYPES 32
|
||||
|
||||
class Job
|
||||
{
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
|
||||
#ifndef ORDERBOOK_H
|
||||
#define ORDERBOOK_H
|
||||
|
||||
|
||||
#include "SerializedLedger.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -34,4 +39,6 @@ public:
|
||||
STAmount& getTakePrice(STAmount& takeAmount);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
#include "OrderBookDB.h"
|
||||
#include "Log.h"
|
||||
|
||||
@@ -11,8 +12,10 @@ OrderBookDB::OrderBookDB()
|
||||
}
|
||||
|
||||
// TODO: this would be way faster if we could just look under the order dirs
|
||||
void OrderBookDB::setup(Ledger::pointer ledger)
|
||||
void OrderBookDB::setup(Ledger::ref ledger)
|
||||
{
|
||||
LoadEvent::autoptr ev = theApp->getJobQueue().getLoadEventAP(jtOB_SETUP);
|
||||
|
||||
mXRPOrders.clear();
|
||||
mIssuerMap.clear();
|
||||
mKnownMap.clear();
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
|
||||
#ifndef ORDERBOOK_DB_H
|
||||
#define ORDERBOOK_DB_H
|
||||
|
||||
#include "Ledger.h"
|
||||
#include "OrderBook.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -33,7 +37,7 @@ class OrderBookDB
|
||||
|
||||
public:
|
||||
OrderBookDB();
|
||||
void setup(Ledger::pointer ledger);
|
||||
void setup(Ledger::ref ledger);
|
||||
|
||||
// return list of all orderbooks that want XRP
|
||||
std::vector<OrderBook::pointer>& getXRPInBooks(){ return mXRPOrders; }
|
||||
@@ -56,4 +60,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -127,17 +127,21 @@ bool Pathfinder::bDefaultPath(const STPath& spPath)
|
||||
return false;
|
||||
}
|
||||
|
||||
Pathfinder::Pathfinder(const RippleAddress& uSrcAccountID, const RippleAddress& uDstAccountID, const uint160& uSrcCurrencyID, const uint160& uSrcIssuerID, const STAmount& saDstAmount)
|
||||
: mSrcAccountID(uSrcAccountID.getAccountID()),
|
||||
Pathfinder::Pathfinder(Ledger::ref ledger,
|
||||
const RippleAddress& uSrcAccountID, const RippleAddress& uDstAccountID,
|
||||
const uint160& uSrcCurrencyID, const uint160& uSrcIssuerID, const STAmount& saDstAmount)
|
||||
: mLedger(ledger),
|
||||
mSrcAccountID(uSrcAccountID.getAccountID()),
|
||||
mDstAccountID(uDstAccountID.getAccountID()),
|
||||
mDstAmount(saDstAmount),
|
||||
mSrcCurrencyID(uSrcCurrencyID),
|
||||
mSrcIssuerID(uSrcIssuerID)
|
||||
{
|
||||
mLedger = theApp->getLedgerMaster().getCurrentLedger();
|
||||
mSrcAmount = STAmount(uSrcCurrencyID, uSrcIssuerID, 1, 0); // -1/uSrcIssuerID/uSrcIssuerID
|
||||
|
||||
theApp->getOrderBookDB().setup( theApp->getLedgerMaster().getCurrentLedger()); // TODO: have the orderbook update itself rather than rebuild it from scratch each time
|
||||
theApp->getOrderBookDB().setup(mLedger); // TODO: have the orderbook update itself rather than rebuild it from scratch each time
|
||||
|
||||
mLoadMonitor = theApp->getJobQueue().getLoadEvent(jtPATH_FIND);
|
||||
|
||||
// Construct the default path for later comparison.
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class Pathfinder
|
||||
//OrderBookDB mOrderBook;
|
||||
Ledger::pointer mLedger;
|
||||
PathState::pointer mPsDefault;
|
||||
LoadEvent::pointer mLoadMonitor;
|
||||
|
||||
// std::list<PathOption::pointer> mBuildingPaths;
|
||||
// std::list<PathOption::pointer> mCompletePaths;
|
||||
@@ -56,7 +57,9 @@ class Pathfinder
|
||||
// void addPathOption(PathOption::pointer pathOption);
|
||||
|
||||
public:
|
||||
Pathfinder(const RippleAddress& srcAccountID, const RippleAddress& dstAccountID, const uint160& srcCurrencyID, const uint160& srcIssuerID, const STAmount& dstAmount);
|
||||
Pathfinder(Ledger::ref ledger,
|
||||
const RippleAddress& srcAccountID, const RippleAddress& dstAccountID,
|
||||
const uint160& srcCurrencyID, const uint160& srcIssuerID, const STAmount& dstAmount);
|
||||
|
||||
bool findPaths(const unsigned int iMaxSteps, const unsigned int iMaxPaths, STPathSet& spsDst);
|
||||
|
||||
|
||||
@@ -177,22 +177,28 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
|
||||
return rpcError(rpcINVALID_PARAMS);
|
||||
}
|
||||
|
||||
Pathfinder pf(raSrcAddressID, dstAccountID, saSendMax.getCurrency(), saSendMax.getIssuer(), saSend);
|
||||
|
||||
if (!pf.findPaths(theConfig.PATH_SEARCH_SIZE, 3, spsPaths))
|
||||
Ledger::pointer lSnapshot = boost::make_shared<Ledger>(
|
||||
boost::ref(*theApp->getOPs().getCurrentLedger()), false);
|
||||
{
|
||||
cLog(lsDEBUG) << "transactionSign: build_path: No paths found.";
|
||||
ScopedUnlock su(theApp->getMasterLock());
|
||||
Pathfinder pf(lSnapshot, raSrcAddressID, dstAccountID,
|
||||
saSendMax.getCurrency(), saSendMax.getIssuer(), saSend);
|
||||
|
||||
return rpcError(rpcNO_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsDEBUG) << "transactionSign: build_path: " << spsPaths.getJson(0);
|
||||
}
|
||||
if (!pf.findPaths(theConfig.PATH_SEARCH_SIZE, 3, spsPaths))
|
||||
{
|
||||
cLog(lsDEBUG) << "transactionSign: build_path: No paths found.";
|
||||
|
||||
if (!spsPaths.isEmpty())
|
||||
{
|
||||
txJSON["Paths"]=spsPaths.getJson(0);
|
||||
return rpcError(rpcNO_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsDEBUG) << "transactionSign: build_path: " << spsPaths.getJson(0);
|
||||
}
|
||||
|
||||
if (!spsPaths.isEmpty())
|
||||
{
|
||||
txJSON["Paths"]=spsPaths.getJson(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,7 +1121,8 @@ Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest)
|
||||
}
|
||||
}
|
||||
|
||||
LedgerEntrySet lesSnapshot(lpCurrent);
|
||||
Ledger::pointer lSnapShot = boost::make_shared<Ledger>(boost::ref(*lpCurrent), false);
|
||||
LedgerEntrySet lesSnapshot(lSnapShot);
|
||||
|
||||
ScopedUnlock su(theApp->getMasterLock()); // As long as we have a locked copy of the ledger, we can unlock.
|
||||
|
||||
@@ -1148,7 +1155,7 @@ Json::Value RPCHandler::doRipplePathFind(Json::Value jvRequest)
|
||||
}
|
||||
|
||||
STPathSet spsComputed;
|
||||
Pathfinder pf(raSrc, raDst, uSrcCurrencyID, uSrcIssuerID, saDstAmount);
|
||||
Pathfinder pf(lSnapShot, raSrc, raDst, uSrcCurrencyID, uSrcIssuerID, saDstAmount);
|
||||
|
||||
if (!pf.findPaths(theConfig.PATH_SEARCH_SIZE, 3, spsComputed))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user