mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Implement Stoppable for LoadManager
This commit is contained in:
@@ -908,7 +908,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadFeeTrack.cpp">
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadFeeTrackImp.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>
|
||||
@@ -1764,11 +1764,11 @@
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadType.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\Config.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\ConfigSections.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\ILoadFeeTrack.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrack.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\Job.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\JobQueue.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadEvent.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrack.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrackImp.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadMonitor.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Backend.h" />
|
||||
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Database.h" />
|
||||
|
||||
@@ -270,9 +270,6 @@
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadEvent.cpp">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadFeeTrack.cpp">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadMonitor.cpp">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClCompile>
|
||||
@@ -1059,6 +1056,9 @@
|
||||
<ClCompile Include="..\..\src\ripple\validators\impl\Utilities.cpp">
|
||||
<Filter>[1] Ripple\validators\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple_core\functional\LoadFeeTrackImp.cpp">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\ripple_basics\containers\KeyCache.h">
|
||||
@@ -1100,9 +1100,6 @@
|
||||
<ClInclude Include="..\..\src\ripple_basics\utility\UptimeTimer.h">
|
||||
<Filter>[2] Old Ripple\ripple_basics\utility</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\ILoadFeeTrack.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\Job.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
@@ -1112,9 +1109,6 @@
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadEvent.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrack.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadMonitor.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
@@ -2115,6 +2109,12 @@
|
||||
<ClInclude Include="..\..\src\ripple\validators\impl\AgedHistory.h">
|
||||
<Filter>[1] Ripple\validators\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrackImp.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple_core\functional\LoadFeeTrack.h">
|
||||
<Filter>[2] Old Ripple\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">
|
||||
|
||||
@@ -131,10 +131,6 @@ David Features:
|
||||
|
||||
- Rename "fullBelow" to something like haveAllDescendants or haveAllChildren.
|
||||
|
||||
- Remove dependence on JobQueue, LoadFeeTrack, and NetworkOPs from LoadManager
|
||||
by providing an observer (beast::ListenerList or Listeners). This way
|
||||
LoadManager does not need stopThread() function.
|
||||
|
||||
- Rewrite Sustain to use Beast and work on Windows as well
|
||||
* Do not enable watchdog process if a debugger is attached
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
// is being written.
|
||||
//
|
||||
#ifndef RIPPLE_USE_NEW_VALIDATORS
|
||||
#define RIPPLE_USE_NEW_VALIDATORS 1
|
||||
#define RIPPLE_USE_NEW_VALIDATORS 0
|
||||
#endif
|
||||
|
||||
// Turning this on makes the Application object get destroyed,
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
#ifndef RIPPLE_VALIDATORS_LOGIC_H_INCLUDED
|
||||
#define RIPPLE_VALIDATORS_LOGIC_H_INCLUDED
|
||||
|
||||
@@ -36,7 +35,7 @@ enum
|
||||
// We check Source expirations on this time interval
|
||||
,checkEverySeconds = 60 * 60
|
||||
#else
|
||||
secondsBetweenFetches = 5 * 60
|
||||
secondsBetweenFetches = 59
|
||||
,checkEverySeconds = 60
|
||||
#endif
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
, m_store (m_journal)
|
||||
, m_logic (m_store, m_journal)
|
||||
, m_checkTimer (this)
|
||||
, m_checkSources (true)
|
||||
, m_checkSources (false)
|
||||
{
|
||||
#if BEAST_MSVC
|
||||
if (beast_isRunningUnderDebugger())
|
||||
@@ -147,26 +147,35 @@ public:
|
||||
|
||||
void onPrepare (Journal journal)
|
||||
{
|
||||
journal.info << "Preparing Validators";
|
||||
journal.info << "Preparing";
|
||||
|
||||
addRPCHandlers();
|
||||
}
|
||||
|
||||
void onStart (Journal journal)
|
||||
{
|
||||
journal.info << "Starting Validators";
|
||||
journal.info << "Starting";
|
||||
|
||||
// Do this late so the sources have a chance to be added.
|
||||
m_queue.dispatch (bind (&ManagerImp::setCheckSources, this));
|
||||
|
||||
startThread();
|
||||
}
|
||||
|
||||
void onStop (Journal journal)
|
||||
{
|
||||
journal.info << "Stopping Validators";
|
||||
journal.info << "Stopping";
|
||||
|
||||
if (this->Thread::isThreadRunning())
|
||||
{
|
||||
m_journal.debug << "Signaling thread exit";
|
||||
m_queue.dispatch (bind (&Thread::signalThreadShouldExit, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.debug << "Thread was never started";
|
||||
stopped();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -269,12 +278,12 @@ public:
|
||||
|
||||
void init ()
|
||||
{
|
||||
m_journal.trace << "Initializing";
|
||||
m_journal.debug << "Initializing";
|
||||
|
||||
File const file (File::getSpecialLocation (
|
||||
File::userDocumentsDirectory).getChildFile ("validators.sqlite"));
|
||||
|
||||
m_journal.trace << "Opening database at '" << file.getFullPathName() << "'";
|
||||
m_journal.debug << "Opening database at '" << file.getFullPathName() << "'";
|
||||
|
||||
Error error (m_store.open (file));
|
||||
|
||||
@@ -294,13 +303,14 @@ public:
|
||||
{
|
||||
if (timer == m_checkTimer)
|
||||
{
|
||||
m_journal.trace << "Check timer signaled";
|
||||
m_journal.debug << "Check timer expired";
|
||||
m_queue.dispatch (bind (&ManagerImp::setCheckSources, this));
|
||||
}
|
||||
}
|
||||
|
||||
void setCheckSources ()
|
||||
{
|
||||
m_journal.debug << "Checking sources";
|
||||
m_checkSources = true;
|
||||
}
|
||||
|
||||
@@ -308,18 +318,16 @@ public:
|
||||
{
|
||||
if (m_checkSources)
|
||||
{
|
||||
m_journal.trace << "Checking sources";
|
||||
|
||||
if (m_logic.fetch_one () == 0)
|
||||
{
|
||||
m_journal.trace << "Finished checking sources";
|
||||
m_journal.debug << "All sources checked";
|
||||
|
||||
// Made it through the list without interruption!
|
||||
// Clear the flag and set the deadline timer again.
|
||||
//
|
||||
m_checkSources = false;
|
||||
|
||||
m_journal.trace << "Next check timer expires in " <<
|
||||
m_journal.debug << "Next check timer expires in " <<
|
||||
RelativeTime::seconds (checkEverySeconds);
|
||||
|
||||
m_checkTimer.setExpiration (checkEverySeconds);
|
||||
|
||||
@@ -40,6 +40,8 @@ class RPCServiceManagerLog;
|
||||
template <> char const* LogPartition::getPartitionName <RPCServiceManagerLog> () { return "RPCServiceManager"; }
|
||||
class HTTPServerLog;
|
||||
template <> char const* LogPartition::getPartitionName <HTTPServerLog> () { return "RPCServer"; }
|
||||
class LoadManagerLog;
|
||||
template <> char const* LogPartition::getPartitionName <LoadManagerLog> () { return "LoadManager"; }
|
||||
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -124,7 +126,7 @@ public:
|
||||
|
||||
, mFeeVote (IFeeVote::New (10, 50 * SYSTEM_CURRENCY_PARTS, 12.5 * SYSTEM_CURRENCY_PARTS))
|
||||
|
||||
, mFeeTrack (ILoadFeeTrack::New ())
|
||||
, mFeeTrack (LoadFeeTrack::New (LogJournal::get <LoadManagerLog> ()))
|
||||
|
||||
, mHashRouter (IHashRouter::New (IHashRouter::getDefaultHoldTime ()))
|
||||
|
||||
@@ -132,7 +134,7 @@ public:
|
||||
|
||||
, mProofOfWorkFactory (ProofOfWorkFactory::New ())
|
||||
|
||||
, m_loadManager (LoadManager::New ())
|
||||
, m_loadManager (LoadManager::New (*this, LogJournal::get <LoadManagerLog> ()))
|
||||
|
||||
, mPeerFinder (PeerFinder::New (*this))
|
||||
|
||||
@@ -145,8 +147,6 @@ public:
|
||||
|
||||
// VFALCO TODO remove these once the call is thread safe.
|
||||
HashMaps::getInstance ().initializeNonce <size_t> ();
|
||||
|
||||
initValidatorsConfig ();
|
||||
}
|
||||
|
||||
~ApplicationImp ()
|
||||
@@ -163,28 +163,6 @@ public:
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Initialize the Validators object with Config information.
|
||||
void initValidatorsConfig ()
|
||||
{
|
||||
{
|
||||
std::vector <std::string> const& strings (getConfig().validators);
|
||||
if (! strings.empty ())
|
||||
m_validators->addStrings ("rippled.cfg", strings);
|
||||
}
|
||||
|
||||
if (! getConfig().getValidatorsURL().empty())
|
||||
{
|
||||
m_validators->addURL (getConfig().getValidatorsURL());
|
||||
}
|
||||
|
||||
if (getConfig().getValidatorsFile() != File::nonexistent ())
|
||||
{
|
||||
m_validators->addFile (getConfig().getValidatorsFile());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
RPC::Manager& getRPCServiceManager()
|
||||
{
|
||||
return *m_rpcServiceManager;
|
||||
@@ -270,7 +248,7 @@ public:
|
||||
return *mFeatures;
|
||||
}
|
||||
|
||||
ILoadFeeTrack& getFeeTrack ()
|
||||
LoadFeeTrack& getFeeTrack ()
|
||||
{
|
||||
return *mFeeTrack;
|
||||
}
|
||||
@@ -388,10 +366,6 @@ public:
|
||||
// VFALCO NOTE: 0 means use heuristics to determine the thread count.
|
||||
m_jobQueue->setThreadCount (0, getConfig ().RUN_STANDALONE);
|
||||
|
||||
m_sweepTimer.setExpiration (10);
|
||||
|
||||
m_loadManager->start ();
|
||||
|
||||
#if ! BEAST_WIN32
|
||||
#ifdef SIGINT
|
||||
|
||||
@@ -642,16 +616,54 @@ public:
|
||||
m_networkOPs->setStandAlone ();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Initialize the Validators object with Config information.
|
||||
void prepareValidators ()
|
||||
{
|
||||
{
|
||||
std::vector <std::string> const& strings (getConfig().validators);
|
||||
if (! strings.empty ())
|
||||
m_validators->addStrings ("rippled.cfg", strings);
|
||||
}
|
||||
|
||||
if (! getConfig().getValidatorsURL().empty())
|
||||
{
|
||||
m_validators->addURL (getConfig().getValidatorsURL());
|
||||
}
|
||||
|
||||
if (getConfig().getValidatorsFile() != File::nonexistent ())
|
||||
{
|
||||
m_validators->addFile (getConfig().getValidatorsFile());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Stoppable
|
||||
//
|
||||
|
||||
void onPrepare (Journal)
|
||||
{
|
||||
prepareValidators ();
|
||||
}
|
||||
|
||||
void onStart (Journal journal)
|
||||
{
|
||||
journal.debug << "Application starting";
|
||||
|
||||
m_sweepTimer.setExpiration (10);
|
||||
}
|
||||
|
||||
// Called to indicate shutdown.
|
||||
void onStop (Journal)
|
||||
void onStop (Journal journal)
|
||||
{
|
||||
journal.debug << "Application stopping";
|
||||
|
||||
m_sweepTimer.cancel();
|
||||
|
||||
// VFALCO TODO get rid of this flag
|
||||
mShutdown = true;
|
||||
|
||||
mValidations->flush ();
|
||||
@@ -717,7 +729,7 @@ public:
|
||||
// eliminate LoadManager's dependency inversions.
|
||||
//
|
||||
// This deletes the object and therefore, stops the thread.
|
||||
m_loadManager = nullptr;
|
||||
//m_loadManager = nullptr;
|
||||
|
||||
m_journal.info << "Done.";
|
||||
|
||||
@@ -844,7 +856,7 @@ private:
|
||||
ScopedPointer <Validators::Manager> m_validators;
|
||||
ScopedPointer <IFeatures> mFeatures;
|
||||
ScopedPointer <IFeeVote> mFeeVote;
|
||||
ScopedPointer <ILoadFeeTrack> mFeeTrack;
|
||||
ScopedPointer <LoadFeeTrack> mFeeTrack;
|
||||
ScopedPointer <IHashRouter> mHashRouter;
|
||||
ScopedPointer <Validations> mValidations;
|
||||
ScopedPointer <ProofOfWorkFactory> mProofOfWorkFactory;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace RPC { class Manager; }
|
||||
class IFeatures;
|
||||
class IFeeVote;
|
||||
class IHashRouter;
|
||||
class ILoadFeeTrack;
|
||||
class LoadFeeTrack;
|
||||
class Peers;
|
||||
class UniqueNodeList;
|
||||
class JobQueue;
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
virtual IFeatures& getFeatureTable () = 0;
|
||||
virtual IFeeVote& getFeeVote () = 0;
|
||||
virtual IHashRouter& getHashRouter () = 0;
|
||||
virtual ILoadFeeTrack& getFeeTrack () = 0;
|
||||
virtual LoadFeeTrack& getFeeTrack () = 0;
|
||||
virtual LoadManager& getLoadManager () = 0;
|
||||
virtual Peers& getPeers () = 0;
|
||||
virtual ProofOfWorkFactory& getProofOfWorkFactory () = 0;
|
||||
|
||||
@@ -17,16 +17,11 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
SETUP_LOG (LoadManager)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class LoadManagerImp
|
||||
: public LoadManager
|
||||
, public Thread
|
||||
{
|
||||
private:
|
||||
public:
|
||||
/* Entry mapping utilization to cost.
|
||||
|
||||
The cost is expressed as a unitless relative quantity. These
|
||||
@@ -72,11 +67,33 @@ private:
|
||||
int m_resourceFlags;
|
||||
};
|
||||
|
||||
public:
|
||||
LoadManagerImp ()
|
||||
: Thread ("loadmgr")
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Journal m_journal;
|
||||
typedef RippleMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
BlackList<UptimeTimerAdapter> mBlackList;
|
||||
|
||||
int mCreditRate; // credits gained/lost per second
|
||||
int mCreditLimit; // the most credits a source can have
|
||||
int mDebitWarn; // when a source drops below this, we warn
|
||||
int mDebitLimit; // when a source drops below this, we cut it off (should be negative)
|
||||
|
||||
bool mArmed;
|
||||
|
||||
int mDeadLock; // Detect server deadlocks
|
||||
|
||||
std::vector <Cost> mCosts;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
LoadManagerImp (Stoppable& parent, Journal journal)
|
||||
: LoadManager (parent)
|
||||
, Thread ("loadmgr")
|
||||
, m_journal (journal)
|
||||
, mLock (this, "LoadManagerImp", __FILE__, __LINE__)
|
||||
, m_logThread ("loadmgr_log")
|
||||
, mCreditRate (100)
|
||||
, mCreditLimit (500)
|
||||
, mDebitWarn (-500)
|
||||
@@ -85,8 +102,6 @@ public:
|
||||
, mDeadLock (0)
|
||||
, mCosts (LT_MAX)
|
||||
{
|
||||
m_logThread.start ();
|
||||
|
||||
/** Flags indicating the type of load.
|
||||
|
||||
Utilization may include any combination of:
|
||||
@@ -128,7 +143,6 @@ public:
|
||||
UptimeTimer::getInstance ().beginManualUpdates ();
|
||||
}
|
||||
|
||||
private:
|
||||
~LoadManagerImp ()
|
||||
{
|
||||
UptimeTimer::getInstance ().endManualUpdates ();
|
||||
@@ -136,11 +150,36 @@ private:
|
||||
stopThread ();
|
||||
}
|
||||
|
||||
void start ()
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Stoppable
|
||||
//
|
||||
|
||||
void onPrepare (Journal)
|
||||
{
|
||||
startThread();
|
||||
}
|
||||
|
||||
void onStart (Journal journal)
|
||||
{
|
||||
journal.debug << "Starting";
|
||||
startThread ();
|
||||
}
|
||||
|
||||
void onStop (Journal journal)
|
||||
{
|
||||
if (isThreadRunning ())
|
||||
{
|
||||
journal.debug << "Stopping";
|
||||
stopThread (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
stopped ();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void canonicalize (LoadSource& source, int now) const
|
||||
{
|
||||
if (source.mLastUpdate != now)
|
||||
@@ -240,17 +279,17 @@ private:
|
||||
void logWarning (const std::string& source) const
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsDEBUG, LoadManager) << "Load warning from empty source";
|
||||
m_journal.debug << "Load warning from empty source";
|
||||
else
|
||||
WriteLog (lsINFO, LoadManager) << "Load warning: " << source;
|
||||
m_journal.info << "Load warning: " << source;
|
||||
}
|
||||
|
||||
void logDisconnect (const std::string& source) const
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsINFO, LoadManager) << "Disconnect for empty source";
|
||||
m_journal.info << "Disconnect for empty source";
|
||||
else
|
||||
WriteLog (lsWARNING, LoadManager) << "Disconnect for: " << source;
|
||||
m_journal.warning << "Disconnect for: " << source;
|
||||
}
|
||||
|
||||
Json::Value getBlackList (int threshold)
|
||||
@@ -282,9 +321,9 @@ private:
|
||||
mArmed = true;
|
||||
}
|
||||
|
||||
static void logDeadlock (int dlTime)
|
||||
void logDeadlock (int dlTime)
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "Server stalled for " << dlTime << " seconds.";
|
||||
m_journal.warning << "Server stalled for " << dlTime << " seconds.";
|
||||
|
||||
#if RIPPLE_TRACK_MUTEXES
|
||||
StringArray report;
|
||||
@@ -298,59 +337,6 @@ private:
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO These used to be public but are apparently not used. Find out why.
|
||||
/*
|
||||
int getCreditRate () const
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mCreditRate;
|
||||
}
|
||||
|
||||
int getCreditLimit () const
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mCreditLimit;
|
||||
}
|
||||
|
||||
int getDebitWarn () const
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mDebitWarn;
|
||||
}
|
||||
|
||||
int getDebitLimit () const
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mDebitLimit;
|
||||
}
|
||||
|
||||
void setCreditRate (int r)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mCreditRate = r;
|
||||
}
|
||||
|
||||
void setCreditLimit (int r)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mCreditLimit = r;
|
||||
}
|
||||
|
||||
void setDebitWarn (int r)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mDebitWarn = r;
|
||||
}
|
||||
|
||||
void setDebitLimit (int r)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mDebitLimit = r;
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
void addCost (const Cost& c)
|
||||
{
|
||||
mCosts [static_cast <int> (c.getLoadType ())] = c;
|
||||
@@ -393,9 +379,7 @@ private:
|
||||
// Report the deadlocked condition every 10 seconds
|
||||
if ((timeSpentDeadlocked % reportingIntervalSeconds) == 0)
|
||||
{
|
||||
// VFALCO TODO Replace this with a dedicated thread with call queue.
|
||||
//
|
||||
m_logThread.call (&logDeadlock, timeSpentDeadlocked);
|
||||
logDeadlock (timeSpentDeadlocked);
|
||||
}
|
||||
|
||||
// If we go over 500 seconds spent deadlocked, it means that the
|
||||
@@ -413,7 +397,7 @@ private:
|
||||
// Another option is using an observer pattern to invert the dependency.
|
||||
if (getApp().getJobQueue ().isOverloaded ())
|
||||
{
|
||||
WriteLog (lsINFO, LoadManager) << getApp().getJobQueue ().getJson (0);
|
||||
m_journal.info << getApp().getJobQueue ().getJson (0);
|
||||
change = getApp().getFeeTrack ().raiseLocalFee ();
|
||||
}
|
||||
else
|
||||
@@ -432,7 +416,7 @@ private:
|
||||
|
||||
if ((when.is_negative ()) || (when.total_seconds () > 1))
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "time jump";
|
||||
m_journal.warning << "time jump";
|
||||
t = boost::posix_time::microsec_clock::universal_time ();
|
||||
}
|
||||
else
|
||||
@@ -441,32 +425,18 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef RippleMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
beast::ThreadWithCallQueue m_logThread;
|
||||
|
||||
BlackList<UptimeTimerAdapter> mBlackList;
|
||||
|
||||
int mCreditRate; // credits gained/lost per second
|
||||
int mCreditLimit; // the most credits a source can have
|
||||
int mDebitWarn; // when a source drops below this, we warn
|
||||
int mDebitLimit; // when a source drops below this, we cut it off (should be negative)
|
||||
|
||||
bool mArmed;
|
||||
|
||||
int mDeadLock; // Detect server deadlocks
|
||||
|
||||
std::vector <Cost> mCosts;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LoadManager* LoadManager::New ()
|
||||
LoadManager::LoadManager (Stoppable& parent)
|
||||
: Stoppable ("LoadManager", parent)
|
||||
{
|
||||
ScopedPointer <LoadManager> object (new LoadManagerImp);
|
||||
return object.release ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
LoadManager* LoadManager::New (Stoppable& parent, Journal journal)
|
||||
{
|
||||
return new LoadManagerImp (parent, journal);
|
||||
}
|
||||
|
||||
@@ -34,17 +34,18 @@
|
||||
|
||||
@see LoadSource, LoadType
|
||||
*/
|
||||
class LoadManager
|
||||
class LoadManager : public Stoppable
|
||||
{
|
||||
protected:
|
||||
explicit LoadManager (Stoppable& parent);
|
||||
|
||||
public:
|
||||
/** Create a new manager.
|
||||
|
||||
The manager thread begins running immediately.
|
||||
|
||||
@note The thresholds for warnings and punishments are in
|
||||
the ctor-initializer
|
||||
*/
|
||||
static LoadManager* New ();
|
||||
static LoadManager* New (Stoppable& parent, Journal journal);
|
||||
|
||||
/** Destroy the manager.
|
||||
|
||||
@@ -52,15 +53,6 @@ public:
|
||||
*/
|
||||
virtual ~LoadManager () { }
|
||||
|
||||
/** Start the associated thread.
|
||||
|
||||
This is here to prevent the deadlock detector from activating during
|
||||
a lengthy program initialization.
|
||||
*/
|
||||
// VFALCO TODO Simplify the two stage initialization to one stage (construction).
|
||||
// NOTE In stand-alone mode the load manager thread isn't started
|
||||
virtual void start () = 0;
|
||||
|
||||
/** Turn on deadlock detection.
|
||||
|
||||
The deadlock detector begins in a disabled state. After this function
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ILOADFEETRACK_H_INCLUDED
|
||||
#define RIPPLE_ILOADFEETRACK_H_INCLUDED
|
||||
|
||||
/** Manages the current fee schedule.
|
||||
|
||||
The "base" fee is the cost to send a reference transaction under no load,
|
||||
expressed in millionths of one XRP.
|
||||
|
||||
The "load" fee is how much the local server currently charges to send a
|
||||
reference transaction. This fee fluctuates based on the load of the
|
||||
server.
|
||||
*/
|
||||
// VFALCO TODO Rename "load" to "current".
|
||||
class ILoadFeeTrack
|
||||
{
|
||||
public:
|
||||
/** Create a new tracker.
|
||||
*/
|
||||
static ILoadFeeTrack* New ();
|
||||
|
||||
virtual ~ILoadFeeTrack () { }
|
||||
|
||||
// Scale from fee units to millionths of a ripple
|
||||
virtual uint64 scaleFeeBase (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits) = 0;
|
||||
|
||||
// Scale using load as well as base rate
|
||||
virtual uint64 scaleFeeLoad (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin) = 0;
|
||||
|
||||
virtual void setRemoteFee (uint32) = 0;
|
||||
|
||||
virtual uint32 getRemoteFee () = 0;
|
||||
virtual uint32 getLocalFee () = 0;
|
||||
virtual uint32 getClusterFee () = 0;
|
||||
|
||||
virtual uint32 getLoadBase () = 0;
|
||||
virtual uint32 getLoadFactor () = 0;
|
||||
|
||||
virtual Json::Value getJson (uint64 baseFee, uint32 referenceFeeUnits) = 0;
|
||||
|
||||
virtual void setClusterFee (uint32) = 0;
|
||||
virtual bool raiseLocalFee () = 0;
|
||||
virtual bool lowerLocalFee () = 0;
|
||||
virtual bool isLoadedLocal () = 0;
|
||||
virtual bool isLoadedCluster () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -17,217 +17,50 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
#ifndef RIPPLE_LOADFEETRACK_H_INCLUDED
|
||||
#define RIPPLE_LOADFEETRACK_H_INCLUDED
|
||||
|
||||
// PRIVATE HEADER
|
||||
class LoadManager;
|
||||
/** Manages the current fee schedule.
|
||||
|
||||
class LoadFeeTrack : public ILoadFeeTrack
|
||||
The "base" fee is the cost to send a reference transaction under no load,
|
||||
expressed in millionths of one XRP.
|
||||
|
||||
The "load" fee is how much the local server currently charges to send a
|
||||
reference transaction. This fee fluctuates based on the load of the
|
||||
server.
|
||||
*/
|
||||
// VFALCO TODO Rename "load" to "current".
|
||||
class LoadFeeTrack
|
||||
{
|
||||
public:
|
||||
LoadFeeTrack ()
|
||||
: mLock (this, "LoadFeeTrack", __FILE__, __LINE__)
|
||||
, mLocalTxnLoadFee (lftNormalFee)
|
||||
, mRemoteTxnLoadFee (lftNormalFee)
|
||||
, mClusterTxnLoadFee (lftNormalFee)
|
||||
, raiseCount (0)
|
||||
{
|
||||
}
|
||||
/** Create a new tracker.
|
||||
*/
|
||||
static LoadFeeTrack* New (Journal journal);
|
||||
|
||||
// Scale using load as well as base rate
|
||||
uint64 scaleFeeLoad (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin)
|
||||
{
|
||||
static uint64 midrange (0x00000000FFFFFFFF);
|
||||
|
||||
bool big = (fee > midrange);
|
||||
|
||||
if (big) // big fee, divide first to avoid overflow
|
||||
fee /= baseFee;
|
||||
else // normal fee, multiply first for accuracy
|
||||
fee *= referenceFeeUnits;
|
||||
|
||||
uint32 feeFactor = std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee);
|
||||
|
||||
// Let admins pay the normal fee until the local load exceeds four times the remote
|
||||
uint32 uRemFee = std::max(mRemoteTxnLoadFee, mClusterTxnLoadFee);
|
||||
if (bAdmin && (feeFactor > uRemFee) && (feeFactor < (4 * uRemFee)))
|
||||
feeFactor = uRemFee;
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
fee = mulDiv (fee, feeFactor, lftNormalFee);
|
||||
}
|
||||
|
||||
if (big) // Fee was big to start, must now multiply
|
||||
fee *= referenceFeeUnits;
|
||||
else // Fee was small to start, mst now divide
|
||||
fee /= baseFee;
|
||||
|
||||
return fee;
|
||||
}
|
||||
virtual ~LoadFeeTrack () { }
|
||||
|
||||
// Scale from fee units to millionths of a ripple
|
||||
uint64 scaleFeeBase (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
return mulDiv (fee, referenceFeeUnits, baseFee);
|
||||
}
|
||||
virtual uint64 scaleFeeBase (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits) = 0;
|
||||
|
||||
uint32 getRemoteFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mRemoteTxnLoadFee;
|
||||
}
|
||||
// Scale using load as well as base rate
|
||||
virtual uint64 scaleFeeLoad (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin) = 0;
|
||||
|
||||
uint32 getLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mLocalTxnLoadFee;
|
||||
}
|
||||
virtual void setRemoteFee (uint32) = 0;
|
||||
|
||||
uint32 getLoadBase ()
|
||||
{
|
||||
return lftNormalFee;
|
||||
}
|
||||
virtual uint32 getRemoteFee () = 0;
|
||||
virtual uint32 getLocalFee () = 0;
|
||||
virtual uint32 getClusterFee () = 0;
|
||||
|
||||
uint32 getLoadFactor ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return std::max(mClusterTxnLoadFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee));
|
||||
}
|
||||
virtual uint32 getLoadBase () = 0;
|
||||
virtual uint32 getLoadFactor () = 0;
|
||||
|
||||
void setClusterFee (uint32 fee)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mClusterTxnLoadFee = fee;
|
||||
}
|
||||
virtual Json::Value getJson (uint64 baseFee, uint32 referenceFeeUnits) = 0;
|
||||
|
||||
uint32 getClusterFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mClusterTxnLoadFee;
|
||||
}
|
||||
|
||||
bool isLoadedLocal ()
|
||||
{
|
||||
// VFALCO TODO This could be replaced with a SharedData and
|
||||
// using a read/write lock instead of a critical section.
|
||||
//
|
||||
// NOTE This applies to all the locking in this class.
|
||||
//
|
||||
//
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee);
|
||||
}
|
||||
|
||||
bool isLoadedCluster ()
|
||||
{
|
||||
// VFALCO TODO This could be replaced with a SharedData and
|
||||
// using a read/write lock instead of a critical section.
|
||||
//
|
||||
// NOTE This applies to all the locking in this class.
|
||||
//
|
||||
//
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee) || (mClusterTxnLoadFee != lftNormalFee);
|
||||
}
|
||||
|
||||
void setRemoteFee (uint32 f)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mRemoteTxnLoadFee = f;
|
||||
}
|
||||
|
||||
bool raiseLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
if (++raiseCount < 2)
|
||||
return false;
|
||||
|
||||
uint32 origFee = mLocalTxnLoadFee;
|
||||
|
||||
if (mLocalTxnLoadFee < mRemoteTxnLoadFee) // make sure this fee takes effect
|
||||
mLocalTxnLoadFee = mRemoteTxnLoadFee;
|
||||
|
||||
mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); // increment by 1/16th
|
||||
|
||||
if (mLocalTxnLoadFee > lftFeeMax)
|
||||
mLocalTxnLoadFee = lftFeeMax;
|
||||
|
||||
if (origFee == mLocalTxnLoadFee)
|
||||
return false;
|
||||
|
||||
WriteLog (lsDEBUG, LoadManager) << "Local load fee raised from " << origFee << " to " << mLocalTxnLoadFee;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lowerLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
uint32 origFee = mLocalTxnLoadFee;
|
||||
raiseCount = 0;
|
||||
|
||||
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
|
||||
|
||||
if (mLocalTxnLoadFee < lftNormalFee)
|
||||
mLocalTxnLoadFee = lftNormalFee;
|
||||
|
||||
if (origFee == mLocalTxnLoadFee)
|
||||
return false;
|
||||
|
||||
WriteLog (lsDEBUG, LoadManager) << "Local load fee lowered from " << origFee << " to " << mLocalTxnLoadFee;
|
||||
return true;
|
||||
}
|
||||
|
||||
Json::Value getJson (uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
Json::Value j (Json::objectValue);
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
// base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple
|
||||
j["base_fee"] = Json::Value::UInt (baseFee);
|
||||
|
||||
// load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple
|
||||
j["load_fee"] = Json::Value::UInt (
|
||||
mulDiv (baseFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO Move this function to some "math utilities" file
|
||||
// compute (value)*(mul)/(div) - avoid overflow but keep precision
|
||||
uint64 mulDiv (uint64 value, uint32 mul, uint64 div)
|
||||
{
|
||||
// VFALCO TODO replace with beast::literal64bitUnsigned ()
|
||||
//
|
||||
static uint64 boundary = (0x00000000FFFFFFFF);
|
||||
|
||||
if (value > boundary) // Large value, avoid overflow
|
||||
return (value / div) * mul;
|
||||
else // Normal value, preserve accuracy
|
||||
return (value * mul) / div;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
|
||||
static const int lftFeeIncFraction = 4; // increase fee by 1/4
|
||||
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
|
||||
static const int lftFeeMax = lftNormalFee * 1000000;
|
||||
|
||||
typedef RippleMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
uint32 mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
uint32 mClusterTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
int raiseCount;
|
||||
virtual void setClusterFee (uint32) = 0;
|
||||
virtual bool raiseLocalFee () = 0;
|
||||
virtual bool lowerLocalFee () = 0;
|
||||
virtual bool isLoadedLocal () = 0;
|
||||
virtual bool isLoadedCluster () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
|
||||
ILoadFeeTrack* ILoadFeeTrack::New ()
|
||||
LoadFeeTrack* LoadFeeTrack::New (Journal journal)
|
||||
{
|
||||
return new LoadFeeTrack;
|
||||
return new LoadFeeTrackImp (journal);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -35,7 +34,7 @@ public:
|
||||
void runTest ()
|
||||
{
|
||||
Config d; // get a default configuration object
|
||||
LoadFeeTrack l;
|
||||
LoadFeeTrackImp l;
|
||||
|
||||
beginTestCase ("fee scaling");
|
||||
|
||||
231
src/ripple_core/functional/LoadFeeTrackImp.h
Normal file
231
src/ripple_core/functional/LoadFeeTrackImp.h
Normal file
@@ -0,0 +1,231 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_LOADFEETRACKIMP_H_INCLUDED
|
||||
#define RIPPLE_LOADFEETRACKIMP_H_INCLUDED
|
||||
|
||||
class LoadFeeTrackImp : public LoadFeeTrack
|
||||
{
|
||||
public:
|
||||
explicit LoadFeeTrackImp (Journal journal = Journal())
|
||||
: m_journal (journal)
|
||||
, mLock (this, "LoadFeeTrackImp", __FILE__, __LINE__)
|
||||
, mLocalTxnLoadFee (lftNormalFee)
|
||||
, mRemoteTxnLoadFee (lftNormalFee)
|
||||
, mClusterTxnLoadFee (lftNormalFee)
|
||||
, raiseCount (0)
|
||||
{
|
||||
}
|
||||
|
||||
// Scale using load as well as base rate
|
||||
uint64 scaleFeeLoad (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin)
|
||||
{
|
||||
static uint64 midrange (0x00000000FFFFFFFF);
|
||||
|
||||
bool big = (fee > midrange);
|
||||
|
||||
if (big) // big fee, divide first to avoid overflow
|
||||
fee /= baseFee;
|
||||
else // normal fee, multiply first for accuracy
|
||||
fee *= referenceFeeUnits;
|
||||
|
||||
uint32 feeFactor = std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee);
|
||||
|
||||
// Let admins pay the normal fee until the local load exceeds four times the remote
|
||||
uint32 uRemFee = std::max(mRemoteTxnLoadFee, mClusterTxnLoadFee);
|
||||
if (bAdmin && (feeFactor > uRemFee) && (feeFactor < (4 * uRemFee)))
|
||||
feeFactor = uRemFee;
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
fee = mulDiv (fee, feeFactor, lftNormalFee);
|
||||
}
|
||||
|
||||
if (big) // Fee was big to start, must now multiply
|
||||
fee *= referenceFeeUnits;
|
||||
else // Fee was small to start, mst now divide
|
||||
fee /= baseFee;
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
// Scale from fee units to millionths of a ripple
|
||||
uint64 scaleFeeBase (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
return mulDiv (fee, referenceFeeUnits, baseFee);
|
||||
}
|
||||
|
||||
uint32 getRemoteFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mRemoteTxnLoadFee;
|
||||
}
|
||||
|
||||
uint32 getLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mLocalTxnLoadFee;
|
||||
}
|
||||
|
||||
uint32 getLoadBase ()
|
||||
{
|
||||
return lftNormalFee;
|
||||
}
|
||||
|
||||
uint32 getLoadFactor ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return std::max(mClusterTxnLoadFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee));
|
||||
}
|
||||
|
||||
void setClusterFee (uint32 fee)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mClusterTxnLoadFee = fee;
|
||||
}
|
||||
|
||||
uint32 getClusterFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return mClusterTxnLoadFee;
|
||||
}
|
||||
|
||||
bool isLoadedLocal ()
|
||||
{
|
||||
// VFALCO TODO This could be replaced with a SharedData and
|
||||
// using a read/write lock instead of a critical section.
|
||||
//
|
||||
// NOTE This applies to all the locking in this class.
|
||||
//
|
||||
//
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee);
|
||||
}
|
||||
|
||||
bool isLoadedCluster ()
|
||||
{
|
||||
// VFALCO TODO This could be replaced with a SharedData and
|
||||
// using a read/write lock instead of a critical section.
|
||||
//
|
||||
// NOTE This applies to all the locking in this class.
|
||||
//
|
||||
//
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee) || (mClusterTxnLoadFee != lftNormalFee);
|
||||
}
|
||||
|
||||
void setRemoteFee (uint32 f)
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
mRemoteTxnLoadFee = f;
|
||||
}
|
||||
|
||||
bool raiseLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
if (++raiseCount < 2)
|
||||
return false;
|
||||
|
||||
uint32 origFee = mLocalTxnLoadFee;
|
||||
|
||||
if (mLocalTxnLoadFee < mRemoteTxnLoadFee) // make sure this fee takes effect
|
||||
mLocalTxnLoadFee = mRemoteTxnLoadFee;
|
||||
|
||||
mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); // increment by 1/16th
|
||||
|
||||
if (mLocalTxnLoadFee > lftFeeMax)
|
||||
mLocalTxnLoadFee = lftFeeMax;
|
||||
|
||||
if (origFee == mLocalTxnLoadFee)
|
||||
return false;
|
||||
|
||||
m_journal.debug << "Local load fee raised from " << origFee << " to " << mLocalTxnLoadFee;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lowerLocalFee ()
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
uint32 origFee = mLocalTxnLoadFee;
|
||||
raiseCount = 0;
|
||||
|
||||
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
|
||||
|
||||
if (mLocalTxnLoadFee < lftNormalFee)
|
||||
mLocalTxnLoadFee = lftNormalFee;
|
||||
|
||||
if (origFee == mLocalTxnLoadFee)
|
||||
return false;
|
||||
|
||||
m_journal.debug << "Local load fee lowered from " << origFee << " to " << mLocalTxnLoadFee;
|
||||
return true;
|
||||
}
|
||||
|
||||
Json::Value getJson (uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
Json::Value j (Json::objectValue);
|
||||
|
||||
{
|
||||
ScopedLockType sl (mLock, __FILE__, __LINE__);
|
||||
|
||||
// base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple
|
||||
j["base_fee"] = Json::Value::UInt (baseFee);
|
||||
|
||||
// load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple
|
||||
j["load_fee"] = Json::Value::UInt (
|
||||
mulDiv (baseFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO Move this function to some "math utilities" file
|
||||
// compute (value)*(mul)/(div) - avoid overflow but keep precision
|
||||
uint64 mulDiv (uint64 value, uint32 mul, uint64 div)
|
||||
{
|
||||
// VFALCO TODO replace with beast::literal64bitUnsigned ()
|
||||
//
|
||||
static uint64 boundary = (0x00000000FFFFFFFF);
|
||||
|
||||
if (value > boundary) // Large value, avoid overflow
|
||||
return (value / div) * mul;
|
||||
else // Normal value, preserve accuracy
|
||||
return (value * mul) / div;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
|
||||
static const int lftFeeIncFraction = 4; // increase fee by 1/4
|
||||
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
|
||||
static const int lftFeeMax = lftNormalFee * 1000000;
|
||||
|
||||
Journal m_journal;
|
||||
typedef RippleMutex LockType;
|
||||
typedef LockType::ScopedLockType ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
uint32 mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
uint32 mClusterTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
int raiseCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -40,8 +40,8 @@ namespace ripple
|
||||
{
|
||||
|
||||
#include "functional/Config.cpp"
|
||||
# include "functional/LoadFeeTrack.h" // private
|
||||
#include "functional/LoadFeeTrack.cpp"
|
||||
# include "functional/LoadFeeTrackImp.h" // private
|
||||
#include "functional/LoadFeeTrackImp.cpp"
|
||||
#include "functional/Job.cpp"
|
||||
#include "functional/JobQueue.cpp"
|
||||
#include "functional/LoadEvent.cpp"
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ripple
|
||||
|
||||
# include "functional/ConfigSections.h"
|
||||
#include "functional/Config.h"
|
||||
#include "functional/ILoadFeeTrack.h"
|
||||
#include "functional/LoadFeeTrack.h"
|
||||
# include "functional/LoadEvent.h"
|
||||
# include "functional/LoadMonitor.h"
|
||||
# include "functional/Job.h"
|
||||
|
||||
Reference in New Issue
Block a user