diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 19b8557d78..44ae01cd19 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -908,7 +908,7 @@
true
true
-
+
true
true
true
@@ -1764,11 +1764,11 @@
-
+
-
+
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index bf1eaa7442..71a7cab512 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -270,9 +270,6 @@
[2] Old Ripple\ripple_core\functional
-
- [2] Old Ripple\ripple_core\functional
-
[2] Old Ripple\ripple_core\functional
@@ -1059,6 +1056,9 @@
[1] Ripple\validators\impl
+
+ [2] Old Ripple\ripple_core\functional
+
@@ -1100,9 +1100,6 @@
[2] Old Ripple\ripple_basics\utility
-
- [2] Old Ripple\ripple_core\functional
-
[2] Old Ripple\ripple_core\functional
@@ -1112,9 +1109,6 @@
[2] Old Ripple\ripple_core\functional
-
- [2] Old Ripple\ripple_core\functional
-
[2] Old Ripple\ripple_core\functional
@@ -2115,6 +2109,12 @@
[1] Ripple\validators\impl
+
+ [2] Old Ripple\ripple_core\functional
+
+
+ [2] Old Ripple\ripple_core\functional
+
diff --git a/doc/todo/VFALCO_TODO.txt b/doc/todo/VFALCO_TODO.txt
index d6ec4858b0..7a78ff1e2c 100644
--- a/doc/todo/VFALCO_TODO.txt
+++ b/doc/todo/VFALCO_TODO.txt
@@ -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
diff --git a/src/BeastConfig.h b/src/BeastConfig.h
index 50ee90542d..05dc73cdcc 100644
--- a/src/BeastConfig.h
+++ b/src/BeastConfig.h
@@ -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,
diff --git a/src/ripple/validators/impl/Logic.h b/src/ripple/validators/impl/Logic.h
index c29635d937..5674fb0446 100644
--- a/src/ripple/validators/impl/Logic.h
+++ b/src/ripple/validators/impl/Logic.h
@@ -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
diff --git a/src/ripple/validators/impl/Manager.cpp b/src/ripple/validators/impl/Manager.cpp
index 9abd666c5c..dd9cdbf2e2 100644
--- a/src/ripple/validators/impl/Manager.cpp
+++ b/src/ripple/validators/impl/Manager.cpp
@@ -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);
diff --git a/src/ripple_app/main/Application.cpp b/src/ripple_app/main/Application.cpp
index 6bb55d5856..01cf0a1aa5 100644
--- a/src/ripple_app/main/Application.cpp
+++ b/src/ripple_app/main/Application.cpp
@@ -40,6 +40,8 @@ class RPCServiceManagerLog;
template <> char const* LogPartition::getPartitionName () { return "RPCServiceManager"; }
class HTTPServerLog;
template <> char const* LogPartition::getPartitionName () { return "RPCServer"; }
+class LoadManagerLog;
+template <> char const* LogPartition::getPartitionName () { 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 ()))
, mHashRouter (IHashRouter::New (IHashRouter::getDefaultHoldTime ()))
@@ -132,7 +134,7 @@ public:
, mProofOfWorkFactory (ProofOfWorkFactory::New ())
- , m_loadManager (LoadManager::New ())
+ , m_loadManager (LoadManager::New (*this, LogJournal::get ()))
, mPeerFinder (PeerFinder::New (*this))
@@ -145,8 +147,6 @@ public:
// VFALCO TODO remove these once the call is thread safe.
HashMaps::getInstance ().initializeNonce ();
-
- initValidatorsConfig ();
}
~ApplicationImp ()
@@ -163,28 +163,6 @@ public:
//--------------------------------------------------------------------------
- // Initialize the Validators object with Config information.
- void initValidatorsConfig ()
- {
- {
- std::vector 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 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 m_validators;
ScopedPointer mFeatures;
ScopedPointer mFeeVote;
- ScopedPointer mFeeTrack;
+ ScopedPointer mFeeTrack;
ScopedPointer mHashRouter;
ScopedPointer mValidations;
ScopedPointer mProofOfWorkFactory;
diff --git a/src/ripple_app/main/Application.h b/src/ripple_app/main/Application.h
index cbe0923aaf..5e7c08fca4 100644
--- a/src/ripple_app/main/Application.h
+++ b/src/ripple_app/main/Application.h
@@ -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;
diff --git a/src/ripple_app/main/LoadManager.cpp b/src/ripple_app/main/LoadManager.cpp
index 03bc055a5f..b792143adc 100644
--- a/src/ripple_app/main/LoadManager.cpp
+++ b/src/ripple_app/main/LoadManager.cpp
@@ -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 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 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 (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 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 mCosts;
};
//------------------------------------------------------------------------------
-LoadManager* LoadManager::New ()
+LoadManager::LoadManager (Stoppable& parent)
+ : Stoppable ("LoadManager", parent)
{
- ScopedPointer object (new LoadManagerImp);
- return object.release ();
+}
+
+//------------------------------------------------------------------------------
+
+LoadManager* LoadManager::New (Stoppable& parent, Journal journal)
+{
+ return new LoadManagerImp (parent, journal);
}
diff --git a/src/ripple_app/main/LoadManager.h b/src/ripple_app/main/LoadManager.h
index 9df1b3fced..067d07eca9 100644
--- a/src/ripple_app/main/LoadManager.h
+++ b/src/ripple_app/main/LoadManager.h
@@ -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
diff --git a/src/ripple_core/functional/ILoadFeeTrack.h b/src/ripple_core/functional/ILoadFeeTrack.h
deleted file mode 100644
index 362ad994e8..0000000000
--- a/src/ripple_core/functional/ILoadFeeTrack.h
+++ /dev/null
@@ -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
diff --git a/src/ripple_core/functional/LoadFeeTrack.h b/src/ripple_core/functional/LoadFeeTrack.h
index e4f95200b1..5b230acfb8 100644
--- a/src/ripple_core/functional/LoadFeeTrack.h
+++ b/src/ripple_core/functional/LoadFeeTrack.h
@@ -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
diff --git a/src/ripple_core/functional/LoadFeeTrack.cpp b/src/ripple_core/functional/LoadFeeTrackImp.cpp
similarity index 95%
rename from src/ripple_core/functional/LoadFeeTrack.cpp
rename to src/ripple_core/functional/LoadFeeTrackImp.cpp
index b71ca7bba2..8bf37d7aea 100644
--- a/src/ripple_core/functional/LoadFeeTrack.cpp
+++ b/src/ripple_core/functional/LoadFeeTrackImp.cpp
@@ -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");
diff --git a/src/ripple_core/functional/LoadFeeTrackImp.h b/src/ripple_core/functional/LoadFeeTrackImp.h
new file mode 100644
index 0000000000..75dd0d361d
--- /dev/null
+++ b/src/ripple_core/functional/LoadFeeTrackImp.h
@@ -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
diff --git a/src/ripple_core/ripple_core.cpp b/src/ripple_core/ripple_core.cpp
index 081b624d74..1fc02db779 100644
--- a/src/ripple_core/ripple_core.cpp
+++ b/src/ripple_core/ripple_core.cpp
@@ -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"
diff --git a/src/ripple_core/ripple_core.h b/src/ripple_core/ripple_core.h
index b043554c9e..04fa71d3d0 100644
--- a/src/ripple_core/ripple_core.h
+++ b/src/ripple_core/ripple_core.h
@@ -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"