mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 22:45:52 +00:00
Move PathRequests to separate files
This commit is contained in:
@@ -1096,6 +1096,12 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_app\paths\PathRequests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_app\paths\PathState.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@@ -2464,6 +2470,7 @@
|
||||
<ClInclude Include="..\..\src\ripple_app\node\SqliteFactory.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\Pathfinder.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\PathRequest.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\PathRequests.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\PathState.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\RippleCalc.h" />
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\RippleLineCache.h" />
|
||||
|
||||
@@ -1443,6 +1443,9 @@
|
||||
<ClCompile Include="..\..\src\ripple\rpc\impl\ErrorCodes.cpp">
|
||||
<Filter>[1] Ripple\rpc\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_app\paths\PathRequests.cpp">
|
||||
<Filter>[2] Old Ripple\ripple_app\paths</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ripple_basics\containers\KeyCache.h">
|
||||
@@ -2928,6 +2931,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\rpc\api\ErrorCodes.h">
|
||||
<Filter>[1] Ripple\rpc\api</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_app\paths\PathRequests.h">
|
||||
<Filter>[2] Old Ripple\ripple_app\paths</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
|
||||
SETUP_LOG (PathRequest)
|
||||
|
||||
PathRequest::PathRequest (const boost::shared_ptr<InfoSub>& subscriber, int id, PathRequests& owner)
|
||||
: mLock (this, "PathRequest", __FILE__, __LINE__)
|
||||
PathRequest::PathRequest (
|
||||
const boost::shared_ptr<InfoSub>& subscriber, int id, PathRequests& owner,
|
||||
Journal journal)
|
||||
: m_journal (journal)
|
||||
, mLock (this, "PathRequest", __FILE__, __LINE__)
|
||||
, mOwner (owner)
|
||||
, wpSubscriber (subscriber)
|
||||
, jvStatus (Json::objectValue)
|
||||
@@ -30,16 +33,11 @@ PathRequest::PathRequest (const boost::shared_ptr<InfoSub>& subscriber, int id,
|
||||
, bLastSuccess (false)
|
||||
, iIdentifier (id)
|
||||
{
|
||||
if (journal().debug)
|
||||
journal().debug << iIdentifier << " created";
|
||||
if (m_journal.debug)
|
||||
m_journal.debug << iIdentifier << " created";
|
||||
ptCreated = boost::posix_time::microsec_clock::universal_time ();
|
||||
}
|
||||
|
||||
Journal& PathRequest::journal ()
|
||||
{
|
||||
return mOwner.journal ();
|
||||
}
|
||||
|
||||
static std::string const get_milli_diff (boost::posix_time::ptime const& after, boost::posix_time::ptime const& before)
|
||||
{
|
||||
return lexicalCastThrow <std::string> (static_cast <unsigned> ((after - before).total_milliseconds()));
|
||||
@@ -65,8 +63,8 @@ PathRequest::~PathRequest()
|
||||
full += get_milli_diff (ptFullReply, ptCreated);
|
||||
full += "ms";
|
||||
}
|
||||
if (journal().info)
|
||||
journal().info << iIdentifier << " complete:" << fast << full <<
|
||||
if (m_journal.info)
|
||||
m_journal.info << iIdentifier << " complete:" << fast << full <<
|
||||
" total:" << get_milli_diff(ptCreated) << "ms";
|
||||
}
|
||||
|
||||
@@ -171,15 +169,15 @@ Json::Value PathRequest::doCreate (Ledger::ref lrLedger, RippleLineCache::ref& c
|
||||
status = jvStatus;
|
||||
}
|
||||
|
||||
if (journal().debug)
|
||||
if (m_journal.debug)
|
||||
{
|
||||
if (bValid)
|
||||
{
|
||||
journal().debug << iIdentifier << " valid: " << raSrcAccount.humanAccountID () <<
|
||||
journal().debug << iIdentifier << " Deliver: " << saDstAmount.getFullText ();
|
||||
m_journal.debug << iIdentifier << " valid: " << raSrcAccount.humanAccountID () <<
|
||||
m_journal.debug << iIdentifier << " Deliver: " << saDstAmount.getFullText ();
|
||||
}
|
||||
else
|
||||
journal().debug << iIdentifier << " invalid";
|
||||
m_journal.debug << iIdentifier << " invalid";
|
||||
}
|
||||
|
||||
valid = bValid;
|
||||
@@ -280,7 +278,7 @@ int PathRequest::parseJson (const Json::Value& jvParams, bool complete)
|
||||
}
|
||||
Json::Value PathRequest::doClose (const Json::Value&)
|
||||
{
|
||||
journal().debug << iIdentifier << " closed";
|
||||
m_journal.debug << iIdentifier << " closed";
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return jvStatus;
|
||||
}
|
||||
@@ -299,7 +297,7 @@ void PathRequest::resetLevel (int l)
|
||||
|
||||
Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
{
|
||||
journal().debug << iIdentifier << " update " << (fast ? "fast" : "normal");
|
||||
m_journal.debug << iIdentifier << " update " << (fast ? "fast" : "normal");
|
||||
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
@@ -364,7 +362,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
--iLevel;
|
||||
}
|
||||
|
||||
journal().debug << iIdentifier << " processing at level " << iLevel;
|
||||
m_journal.debug << iIdentifier << " processing at level " << iLevel;
|
||||
|
||||
bool found = false;
|
||||
|
||||
@@ -372,8 +370,8 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
{
|
||||
{
|
||||
STAmount test (currIssuer.first, currIssuer.second, 1);
|
||||
if (journal().debug)
|
||||
journal().debug << iIdentifier << " Trying to find paths: " << test.getFullText ();
|
||||
if (m_journal.debug)
|
||||
m_journal.debug << iIdentifier << " Trying to find paths: " << test.getFullText ();
|
||||
}
|
||||
bool valid;
|
||||
STPathSet& spsPaths = mContext[currIssuer];
|
||||
@@ -392,7 +390,7 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
currIssuer.second.isNonZero () ? currIssuer.second :
|
||||
(currIssuer.first.isZero () ? ACCOUNT_XRP : raSrcAccount.getAccountID ()), 1);
|
||||
saMaxAmount.negate ();
|
||||
journal().debug << iIdentifier << " Paths found, calling rippleCalc";
|
||||
m_journal.debug << iIdentifier << " Paths found, calling rippleCalc";
|
||||
TER terResult = RippleCalc::rippleCalc (lesSandbox, saMaxAmountAct, saDstAmountAct,
|
||||
vpsExpanded, saMaxAmount, saDstAmount,
|
||||
raDstAccount.getAccountID (), raSrcAccount.getAccountID (),
|
||||
@@ -401,14 +399,14 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
|
||||
if ((extraPath.size() > 0) && ((terResult == terNO_LINE) || (terResult == tecPATH_PARTIAL)))
|
||||
{
|
||||
journal().debug << iIdentifier << " Trying with an extra path element";
|
||||
m_journal.debug << iIdentifier << " Trying with an extra path element";
|
||||
spsPaths.addPath(extraPath);
|
||||
vpsExpanded.clear ();
|
||||
terResult = RippleCalc::rippleCalc (lesSandbox, saMaxAmountAct, saDstAmountAct,
|
||||
vpsExpanded, saMaxAmount, saDstAmount,
|
||||
raDstAccount.getAccountID (), raSrcAccount.getAccountID (),
|
||||
spsPaths, false, false, false, true);
|
||||
journal().debug << iIdentifier << " Extra path element gives " << transHuman (terResult);
|
||||
m_journal.debug << iIdentifier << " Extra path element gives " << transHuman (terResult);
|
||||
}
|
||||
|
||||
if (terResult == tesSUCCESS)
|
||||
@@ -421,12 +419,12 @@ Json::Value PathRequest::doUpdate (RippleLineCache::ref cache, bool fast)
|
||||
}
|
||||
else
|
||||
{
|
||||
journal().debug << iIdentifier << " rippleCalc returns " << transHuman (terResult);
|
||||
m_journal.debug << iIdentifier << " rippleCalc returns " << transHuman (terResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
journal().debug << iIdentifier << " No paths found";
|
||||
m_journal.debug << iIdentifier << " No paths found";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,177 +451,3 @@ InfoSub::pointer PathRequest::getSubscriber ()
|
||||
return wpSubscriber.lock ();
|
||||
}
|
||||
|
||||
/** Get the current RippleLineCache, updating it if necessary.
|
||||
Get the correct ledger to use.
|
||||
*/
|
||||
RippleLineCache::pointer PathRequests::getLineCache (Ledger::pointer& ledger, bool authoritative)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
uint32 lineSeq = mLineCache ? mLineCache->getLedger()->getLedgerSeq() : 0;
|
||||
uint32 lgrSeq = ledger->getLedgerSeq();
|
||||
|
||||
if ( (lineSeq == 0) || // no ledger
|
||||
(authoritative && (lgrSeq > lineSeq)) || // newer authoritative ledger
|
||||
(authoritative && ((lgrSeq + 8) < lineSeq)) || // we jumped way back for some reason
|
||||
(lgrSeq > (lineSeq + 8))) // we jumped way forward for some reason
|
||||
{
|
||||
ledger = boost::make_shared<Ledger>(*ledger, false); // Take a snapshot of the ledger
|
||||
mLineCache = boost::make_shared<RippleLineCache> (ledger);
|
||||
}
|
||||
else
|
||||
{
|
||||
ledger = mLineCache->getLedger();
|
||||
}
|
||||
return mLineCache;
|
||||
}
|
||||
|
||||
void PathRequests::updateAll (Ledger::ref inLedger, CancelCallback shouldCancel)
|
||||
{
|
||||
std::vector<PathRequest::wptr> requests;
|
||||
|
||||
LoadEvent::autoptr event (getApp().getJobQueue().getLoadEventAP(jtPATH_FIND, "PathRequest::updateAll"));
|
||||
|
||||
// Get the ledger and cache we should be using
|
||||
Ledger::pointer ledger = inLedger;
|
||||
RippleLineCache::pointer cache;
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
requests = mRequests;
|
||||
cache = getLineCache (ledger, true);
|
||||
}
|
||||
|
||||
bool newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
bool mustBreak = false;
|
||||
|
||||
journal().trace << "updateAll seq=" << ledger->getLedgerSeq() << ", " <<
|
||||
requests.size() << " requests";
|
||||
int processed = 0, removed = 0;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
{ // Get the latest requests, cache, and ledger
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
if (mRequests.empty())
|
||||
return;
|
||||
|
||||
// Newest request is last in mRequests, but we want to serve it first
|
||||
requests.empty();
|
||||
requests.reserve (mRequests.size ());
|
||||
BOOST_REVERSE_FOREACH (PathRequest::wptr& req, mRequests)
|
||||
{
|
||||
requests.push_back (req);
|
||||
}
|
||||
|
||||
cache = getLineCache (ledger, false);
|
||||
}
|
||||
|
||||
BOOST_FOREACH (PathRequest::wref wRequest, requests)
|
||||
{
|
||||
if (shouldCancel())
|
||||
break;
|
||||
|
||||
bool remove = true;
|
||||
PathRequest::pointer pRequest = wRequest.lock ();
|
||||
|
||||
if (pRequest)
|
||||
{
|
||||
if (!pRequest->needsUpdate (newRequests, ledger->getLedgerSeq ()))
|
||||
remove = false;
|
||||
else
|
||||
{
|
||||
InfoSub::pointer ipSub = pRequest->getSubscriber ();
|
||||
if (ipSub)
|
||||
{
|
||||
Json::Value update = pRequest->doUpdate (cache, false);
|
||||
update["type"] = "path_find";
|
||||
ipSub->send (update, false);
|
||||
remove = false;
|
||||
++processed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remove)
|
||||
{
|
||||
PathRequest::pointer pRequest = wRequest.lock ();
|
||||
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
// Remove any dangling weak pointers or weak pointers that refer to this path request.
|
||||
std::vector<PathRequest::wptr>::iterator it = mRequests.begin();
|
||||
while (it != mRequests.end())
|
||||
{
|
||||
PathRequest::pointer itRequest = it->lock ();
|
||||
if (!itRequest || (itRequest == pRequest))
|
||||
{
|
||||
++removed;
|
||||
it = mRequests.erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
mustBreak = !newRequests && getApp().getLedgerMaster().isNewPathRequest();
|
||||
if (mustBreak) // We weren't handling new requests and then there was a new request
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (mustBreak)
|
||||
{ // a new request came in while we were working
|
||||
newRequests = true;
|
||||
}
|
||||
else if (newRequests)
|
||||
{ // we only did new requests, so we always need a last pass
|
||||
newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
}
|
||||
else
|
||||
{ // check if there are any new requests, otherwise we are done
|
||||
newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
if (!newRequests) // We did a full pass and there are no new requests
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
while (!shouldCancel ());
|
||||
|
||||
journal().debug << "updateAll complete " << processed << " process and " <<
|
||||
removed << " removed";
|
||||
}
|
||||
|
||||
Json::Value PathRequests::makePathRequest(
|
||||
boost::shared_ptr <InfoSub> const& subscriber,
|
||||
const boost::shared_ptr<Ledger>& inLedger,
|
||||
const Json::Value& requestJson)
|
||||
{
|
||||
PathRequest::pointer req = boost::make_shared<PathRequest> (subscriber, ++mLastIdentifier, *this);
|
||||
|
||||
Ledger::pointer ledger = inLedger;
|
||||
RippleLineCache::pointer cache;
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
cache = getLineCache (ledger, false);
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
Json::Value result = req->doCreate (ledger, cache, requestJson, valid);
|
||||
|
||||
if (valid)
|
||||
{
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mRequests.push_back (req);
|
||||
}
|
||||
subscriber->setPathRequest (req);
|
||||
getApp().getLedgerMaster().newPathRequest();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -31,10 +31,11 @@ class PathRequests;
|
||||
#define PFR_PJ_NOCHANGE 0
|
||||
#define PFR_PJ_CHANGE 1
|
||||
|
||||
class PathRequest : public boost::enable_shared_from_this<PathRequest>, public CountedObject <PathRequest>
|
||||
class PathRequest :
|
||||
public boost::enable_shared_from_this <PathRequest>,
|
||||
public CountedObject <PathRequest>
|
||||
{
|
||||
public:
|
||||
|
||||
static char const* getCountedObjectName () { return "PathRequest"; }
|
||||
|
||||
typedef boost::weak_ptr<PathRequest> wptr;
|
||||
@@ -45,7 +46,9 @@ public:
|
||||
|
||||
public:
|
||||
// VFALCO TODO Break the cyclic dependency on InfoSub
|
||||
explicit PathRequest (boost::shared_ptr <InfoSub> const& subscriber, int id, PathRequests&);
|
||||
PathRequest (boost::shared_ptr <InfoSub> const& subscriber,
|
||||
int id, PathRequests&, Journal journal);
|
||||
|
||||
~PathRequest ();
|
||||
|
||||
bool isValid (const boost::shared_ptr<Ledger>&);
|
||||
@@ -59,13 +62,14 @@ public:
|
||||
Json::Value doStatus (const Json::Value&);
|
||||
Json::Value doUpdate (const boost::shared_ptr<RippleLineCache>&, bool fast); // update jvStatus
|
||||
InfoSub::pointer getSubscriber ();
|
||||
Journal& journal ();
|
||||
|
||||
private:
|
||||
void setValid ();
|
||||
void resetLevel (int level);
|
||||
int parseJson (const Json::Value&, bool complete);
|
||||
|
||||
Journal m_journal;
|
||||
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
@@ -98,64 +102,4 @@ private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
class PathRequests
|
||||
{
|
||||
public:
|
||||
|
||||
PathRequests (Journal journal, std::shared_ptr <insight::Collector> const& collector)
|
||||
: mJournal (journal)
|
||||
, mLastIdentifier (0)
|
||||
, mLock ("PathRequests", __FILE__, __LINE__)
|
||||
{
|
||||
mFast = collector->make_event ("pathfind_fast");
|
||||
mFull = collector->make_event ("pathfind_full");
|
||||
}
|
||||
|
||||
void updateAll (const boost::shared_ptr<Ledger>& ledger, CancelCallback shouldCancel);
|
||||
|
||||
RippleLineCache::pointer getLineCache (Ledger::pointer& ledger, bool authoritative);
|
||||
|
||||
Json::Value makePathRequest (
|
||||
boost::shared_ptr <InfoSub> const& subscriber,
|
||||
const boost::shared_ptr<Ledger>& ledger,
|
||||
const Json::Value& request);
|
||||
|
||||
Journal& journal ()
|
||||
{
|
||||
return mJournal;
|
||||
}
|
||||
|
||||
void reportFast (int milliseconds)
|
||||
{
|
||||
mFast.notify (static_cast < insight::Event::value_type> (milliseconds));
|
||||
}
|
||||
|
||||
void reportFull (int milliseconds)
|
||||
{
|
||||
mFull.notify (static_cast < insight::Event::value_type> (milliseconds));
|
||||
}
|
||||
|
||||
private:
|
||||
Journal mJournal;
|
||||
|
||||
insight::Event mFast;
|
||||
insight::Event mFull;
|
||||
|
||||
// Track all requests
|
||||
std::vector<PathRequest::wptr> mRequests;
|
||||
|
||||
// Use a RippleLineCache
|
||||
RippleLineCache::pointer mLineCache;
|
||||
|
||||
Atomic<int> mLastIdentifier;
|
||||
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
194
src/ripple_app/paths/PathRequests.cpp
Normal file
194
src/ripple_app/paths/PathRequests.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Get the current RippleLineCache, updating it if necessary.
|
||||
Get the correct ledger to use.
|
||||
*/
|
||||
RippleLineCache::pointer PathRequests::getLineCache (Ledger::pointer& ledger, bool authoritative)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
uint32 lineSeq = mLineCache ? mLineCache->getLedger()->getLedgerSeq() : 0;
|
||||
uint32 lgrSeq = ledger->getLedgerSeq();
|
||||
|
||||
if ( (lineSeq == 0) || // no ledger
|
||||
(authoritative && (lgrSeq > lineSeq)) || // newer authoritative ledger
|
||||
(authoritative && ((lgrSeq + 8) < lineSeq)) || // we jumped way back for some reason
|
||||
(lgrSeq > (lineSeq + 8))) // we jumped way forward for some reason
|
||||
{
|
||||
ledger = boost::make_shared<Ledger>(*ledger, false); // Take a snapshot of the ledger
|
||||
mLineCache = boost::make_shared<RippleLineCache> (ledger);
|
||||
}
|
||||
else
|
||||
{
|
||||
ledger = mLineCache->getLedger();
|
||||
}
|
||||
return mLineCache;
|
||||
}
|
||||
|
||||
void PathRequests::updateAll (Ledger::ref inLedger, CancelCallback shouldCancel)
|
||||
{
|
||||
std::vector<PathRequest::wptr> requests;
|
||||
|
||||
LoadEvent::autoptr event (getApp().getJobQueue().getLoadEventAP(jtPATH_FIND, "PathRequest::updateAll"));
|
||||
|
||||
// Get the ledger and cache we should be using
|
||||
Ledger::pointer ledger = inLedger;
|
||||
RippleLineCache::pointer cache;
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
requests = mRequests;
|
||||
cache = getLineCache (ledger, true);
|
||||
}
|
||||
|
||||
bool newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
bool mustBreak = false;
|
||||
|
||||
mJournal.trace << "updateAll seq=" << ledger->getLedgerSeq() << ", " <<
|
||||
requests.size() << " requests";
|
||||
int processed = 0, removed = 0;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
{ // Get the latest requests, cache, and ledger
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
if (mRequests.empty())
|
||||
return;
|
||||
|
||||
// Newest request is last in mRequests, but we want to serve it first
|
||||
requests.empty();
|
||||
requests.reserve (mRequests.size ());
|
||||
BOOST_REVERSE_FOREACH (PathRequest::wptr& req, mRequests)
|
||||
{
|
||||
requests.push_back (req);
|
||||
}
|
||||
|
||||
cache = getLineCache (ledger, false);
|
||||
}
|
||||
|
||||
BOOST_FOREACH (PathRequest::wref wRequest, requests)
|
||||
{
|
||||
if (shouldCancel())
|
||||
break;
|
||||
|
||||
bool remove = true;
|
||||
PathRequest::pointer pRequest = wRequest.lock ();
|
||||
|
||||
if (pRequest)
|
||||
{
|
||||
if (!pRequest->needsUpdate (newRequests, ledger->getLedgerSeq ()))
|
||||
remove = false;
|
||||
else
|
||||
{
|
||||
InfoSub::pointer ipSub = pRequest->getSubscriber ();
|
||||
if (ipSub)
|
||||
{
|
||||
Json::Value update = pRequest->doUpdate (cache, false);
|
||||
update["type"] = "path_find";
|
||||
ipSub->send (update, false);
|
||||
remove = false;
|
||||
++processed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (remove)
|
||||
{
|
||||
PathRequest::pointer pRequest = wRequest.lock ();
|
||||
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
// Remove any dangling weak pointers or weak pointers that refer to this path request.
|
||||
std::vector<PathRequest::wptr>::iterator it = mRequests.begin();
|
||||
while (it != mRequests.end())
|
||||
{
|
||||
PathRequest::pointer itRequest = it->lock ();
|
||||
if (!itRequest || (itRequest == pRequest))
|
||||
{
|
||||
++removed;
|
||||
it = mRequests.erase (it);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
mustBreak = !newRequests && getApp().getLedgerMaster().isNewPathRequest();
|
||||
if (mustBreak) // We weren't handling new requests and then there was a new request
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (mustBreak)
|
||||
{ // a new request came in while we were working
|
||||
newRequests = true;
|
||||
}
|
||||
else if (newRequests)
|
||||
{ // we only did new requests, so we always need a last pass
|
||||
newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
}
|
||||
else
|
||||
{ // check if there are any new requests, otherwise we are done
|
||||
newRequests = getApp().getLedgerMaster().isNewPathRequest();
|
||||
if (!newRequests) // We did a full pass and there are no new requests
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
while (!shouldCancel ());
|
||||
|
||||
mJournal.debug << "updateAll complete " << processed << " process and " <<
|
||||
removed << " removed";
|
||||
}
|
||||
|
||||
Json::Value PathRequests::makePathRequest(
|
||||
boost::shared_ptr <InfoSub> const& subscriber,
|
||||
const boost::shared_ptr<Ledger>& inLedger,
|
||||
const Json::Value& requestJson)
|
||||
{
|
||||
PathRequest::pointer req = boost::make_shared<PathRequest> (
|
||||
subscriber, ++mLastIdentifier, *this, mJournal);
|
||||
|
||||
Ledger::pointer ledger = inLedger;
|
||||
RippleLineCache::pointer cache;
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
cache = getLineCache (ledger, false);
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
Json::Value result = req->doCreate (ledger, cache, requestJson, valid);
|
||||
|
||||
if (valid)
|
||||
{
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mRequests.push_back (req);
|
||||
}
|
||||
subscriber->setPathRequest (req);
|
||||
getApp().getLedgerMaster().newPathRequest();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4
|
||||
74
src/ripple_app/paths/PathRequests.h
Normal file
74
src/ripple_app/paths/PathRequests.h
Normal file
@@ -0,0 +1,74 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PATHREQUESTS_H
|
||||
#define RIPPLE_PATHREQUESTS_H
|
||||
|
||||
class PathRequests
|
||||
{
|
||||
public:
|
||||
PathRequests (Journal journal, insight::Collector::ptr const& collector)
|
||||
: mJournal (journal)
|
||||
, mLastIdentifier (0)
|
||||
, mLock ("PathRequests", __FILE__, __LINE__)
|
||||
{
|
||||
mFast = collector->make_event ("pathfind_fast");
|
||||
mFull = collector->make_event ("pathfind_full");
|
||||
}
|
||||
|
||||
void updateAll (const boost::shared_ptr<Ledger>& ledger, CancelCallback shouldCancel);
|
||||
|
||||
RippleLineCache::pointer getLineCache (Ledger::pointer& ledger, bool authoritative);
|
||||
|
||||
Json::Value makePathRequest (
|
||||
boost::shared_ptr <InfoSub> const& subscriber,
|
||||
const boost::shared_ptr<Ledger>& ledger,
|
||||
const Json::Value& request);
|
||||
|
||||
void reportFast (int milliseconds)
|
||||
{
|
||||
mFast.notify (static_cast < insight::Event::value_type> (milliseconds));
|
||||
}
|
||||
|
||||
void reportFull (int milliseconds)
|
||||
{
|
||||
mFull.notify (static_cast < insight::Event::value_type> (milliseconds));
|
||||
}
|
||||
|
||||
private:
|
||||
Journal mJournal;
|
||||
|
||||
insight::Event mFast;
|
||||
insight::Event mFull;
|
||||
|
||||
// Track all requests
|
||||
std::vector<PathRequest::wptr> mRequests;
|
||||
|
||||
// Use a RippleLineCache
|
||||
RippleLineCache::pointer mLineCache;
|
||||
|
||||
Atomic<int> mLastIdentifier;
|
||||
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -134,6 +134,7 @@ namespace ripple {
|
||||
#include "tx/OfferCreateTransactor.h"
|
||||
#include "paths/RippleLineCache.h"
|
||||
#include "paths/PathRequest.h"
|
||||
#include "paths/PathRequests.h"
|
||||
#include "main/ParameterTable.h"
|
||||
#include "paths/RippleLineCache.h"
|
||||
#include "paths/PathState.h"
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace ripple
|
||||
{
|
||||
|
||||
#include "paths/PathRequest.cpp"
|
||||
#include "paths/PathRequests.cpp"
|
||||
#include "paths/RippleCalc.cpp"
|
||||
#include "paths/PathState.cpp"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user