diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index eb9de59b7..8dcb534e3 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -1399,7 +1399,7 @@ - + @@ -1506,6 +1506,8 @@ + + diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 38658f45d..3e62374dd 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -1436,9 +1436,6 @@ [1] Ripple\ripple_app\main - - [1] Ripple\ripple_app\main - [1] Ripple\ripple_app\main @@ -1673,6 +1670,15 @@ [1] Ripple\ripple_app\peers + + [1] Ripple\ripple_core\functional + + + [1] Ripple\ripple_core\functional + + + [1] Ripple\ripple_app\main + diff --git a/modules/ripple_app/main/ripple_Application.cpp b/modules/ripple_app/main/ripple_Application.cpp index d15dcaaf4..411acb27e 100644 --- a/modules/ripple_app/main/ripple_Application.cpp +++ b/modules/ripple_app/main/ripple_Application.cpp @@ -175,7 +175,7 @@ public: , mValidations (IValidations::New ()) , mUNL (UniqueNodeList::New ()) , mProofOfWorkFactory (IProofOfWorkFactory::New ()) - , m_loadManager (ILoadManager::New ()) + , m_loadManager (LoadManager::New ()) // VFALCO End new stuff // VFALCO TODO replace all NULL with nullptr , mRpcDB (NULL) @@ -267,7 +267,7 @@ public: return mMasterLock; } - ILoadManager& getLoadManager () + LoadManager& getLoadManager () { return *m_loadManager; } @@ -703,7 +703,7 @@ private: ScopedPointer mUNL; ScopedPointer mProofOfWorkFactory; ScopedPointer m_peers; - ScopedPointer m_loadManager; + ScopedPointer m_loadManager; ScopedPointer m_peerDoor; ScopedPointer m_peerProxyDoor; ScopedPointer m_wsPublicDoor; diff --git a/modules/ripple_app/main/ripple_Application.h b/modules/ripple_app/main/ripple_Application.h index 458ee9ea4..64a137f8b 100644 --- a/modules/ripple_app/main/ripple_Application.h +++ b/modules/ripple_app/main/ripple_Application.h @@ -83,7 +83,7 @@ public: virtual IFeeVote& getFeeVote () = 0; virtual IHashRouter& getHashRouter () = 0; virtual ILoadFeeTrack& getFeeTrack () = 0; - virtual ILoadManager& getLoadManager () = 0; + virtual LoadManager& getLoadManager () = 0; virtual Peers& getPeers () = 0; virtual IProofOfWorkFactory& getProofOfWorkFactory () = 0; virtual UniqueNodeList& getUNL () = 0; diff --git a/modules/ripple_app/main/ripple_ILoadManager.h b/modules/ripple_app/main/ripple_ILoadManager.h deleted file mode 100644 index ee1bbdaa8..000000000 --- a/modules/ripple_app/main/ripple_ILoadManager.h +++ /dev/null @@ -1,276 +0,0 @@ -//------------------------------------------------------------------------------ -/* - Copyright (c) 2011-2013, OpenCoin, Inc. -*/ -//============================================================================== - -#ifndef RIPPLE_ILOADMANAGER_H -#define RIPPLE_ILOADMANAGER_H - -// types of load that can be placed on the server -// VFALCO TODO replace LT_ with loadType in constants -enum LoadType -{ - // Bad things - LT_InvalidRequest, // A request that we can immediately tell is invalid - LT_RequestNoReply, // A request that we cannot satisfy - LT_InvalidSignature, // An object whose signature we had to check and it failed - LT_UnwantedData, // Data we have no use for - LT_BadPoW, // Proof of work not valid - LT_BadData, // Data we have to verify before rejecting - - // RPC loads - LT_RPCInvalid, // An RPC request that we can immediately tell is invalid. - LT_RPCReference, // A default "reference" unspecified load - LT_RPCException, // An RPC load that causes an exception - LT_RPCBurden, // A particularly burdensome RPC load - - // Good things - LT_NewTrusted, // A new transaction/validation/proposal we trust - LT_NewTransaction, // A new, valid transaction - LT_NeededData, // Data we requested - - // Requests - LT_RequestData, // A request that is hard to satisfy, disk access - LT_CheapQuery, // A query that is trivial, cached data - - LT_MAX // MUST BE LAST -}; - -//------------------------------------------------------------------------------ - -/** Tracks the consumption of resources at an endpoint. - - To prevent monopolization of server resources or attacks on servers, - resource consumption is monitored at each endpoint. When consumption - exceeds certain thresholds, costs are imposed. Costs include charging - additional XRP for transactions, requiring a proof of work to be - performed, or simply disconnecting the endpoint. - - Currently, consumption endpoints include websocket connections used to - service clients, and peer connections used to create the peer to peer - overlay network implementing the Ripple protcool. - - The current "balance" of a LoadSource represents resource consumption - debt or credit. Debt is accrued when bad loads are imposed. Credit is - granted when good loads are imposed. When the balance crosses heuristic - thresholds, costs are increased on the endpoint. - - The balance is represented as a unitless relative quantity. - - @note Although RPC connections consume resources, they are transient and - cannot be rate limited. It is advised not to expose RPC interfaces - to the general public. -*/ -class LoadSource -{ -public: - // VFALCO TODO Use these dispositions - /* - enum Disposition - { - none, - shouldWarn, - shouldDrop, - }; - */ - - /** Construct a load source. - - Sources with admin privileges have relaxed or no restrictions - on resource consumption. - - @param admin `true` if the source should have admin privileges. - */ - // VFALCO TODO See who is constructing this with a parameter - explicit LoadSource (bool admin) - : mBalance (0) - , mFlags (admin ? lsfPrivileged : 0) - , mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ()) - , mLastWarning (0) - , mLogged (false) - { - } - - /** Construct a load source with a given name. - - The endpoint is considered non-privileged. - */ - explicit LoadSource (std::string const& name) - : mName (name) - , mBalance (0) - , mFlags (0) - , mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ()) - , mLastWarning (0) - , mLogged (false) - { - } - - /** Change the name of the source. - - An endpoint can be created before it's name is known. For example, - on an incoming connection before the IP and port have been determined. - */ - // VFALCO TODO Figure out a way to construct the LoadSource object with - // the proper name instead of renaming it later. - // - void rename (std::string const& name) - { - mName = name; - } - - /** Retrieve the name of this endpoint. - */ - std::string const& getName () const - { - return mName; - } - - /** Determine if this endpoint is privileged. - */ - bool isPrivileged () const - { - return (mFlags & lsfPrivileged) != 0; - } - - /** Grant the privileged attribute on this endpoint. - */ - void setPrivileged () - { - mFlags |= lsfPrivileged; - } - - /** Retrieve the load debit or credit associated with the endpoint. - - The balance is represented in a unitless relative quantity - indicating the heuristically weighted amount of resource consumption. - */ - int getBalance () const - { - return mBalance; - } - - /** Returns true if the endpoint received a log warning. - */ - bool isLogged () const - { - return mLogged; - } - - /** Reset the flag indicating the endpoint received a log warning. - */ - void clearLogged () - { - mLogged = false; - } - - /** Indicate that this endpoint is an outgoing connection. - */ - void setOutbound () - { - mFlags |= lsfOutbound; - } - - /** Returns true if this endpoint is an outgoing connection. - */ - bool isOutbound () const - { - return (mFlags & lsfOutbound) != 0; - } - -private: - // VFALCO Make this not a friend - friend class LoadManager; - - static const int lsfPrivileged = 1; - static const int lsfOutbound = 2; - -private: - std::string mName; - int mBalance; - int mFlags; - int mLastUpdate; - int mLastWarning; - bool mLogged; -}; - -//------------------------------------------------------------------------------ - -/** Manages load sources. - - This object creates an associated thread to maintain a clock. - - When the server is overloaded by a particular peer it issues a warning - first. This allows friendly peers to reduce their consumption of resources, - or disconnect from the server. - - The warning system is used instead of merely dropping, because hostile - peers can just reconnect anyway. - - @see LoadSource, LoadType -*/ -class ILoadManager -{ -public: - /** Create a new manager. - - The manager thread begins running immediately. - - @note The thresholds for warnings and punishments are in - the ctor-initializer - */ - static ILoadManager* New (); - - /** Destroy the manager. - - The destructor returns only after the thread has stopped. - */ - virtual ~ILoadManager () { } - - /** 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 startThread () = 0; - - /** Turn on deadlock detection. - - The deadlock detector begins in a disabled state. After this function - is called, it will report deadlocks using a separate thread whenever - the reset function is not called at least once per 10 seconds. - - @see resetDeadlockDetector - */ - // VFALCO NOTE it seems that the deadlock detector has an "armed" state to prevent it - // from going off during program startup if there's a lengthy initialization - // operation taking place? - // - virtual void activateDeadlockDetector () = 0; - - /** Reset the deadlock detection timer. - - A dedicated thread monitors the deadlock timer, and if too much - time passes it will produce log warnings. - */ - virtual void resetDeadlockDetector () = 0; - - /** Update an endpoint to reflect an imposed load. - - The balance of the endpoint is adjusted based on the heuristic cost - of the indicated load. - - @return `true` if the endpoint should be warned or punished. - */ - virtual bool applyLoadCharge (LoadSource& sourceToAdjust, LoadType loadToImpose) const = 0; - - // VFALCO TODO Eliminate these two functions and just make applyLoadCharge() - // return a LoadSource::Disposition - // - virtual bool shouldWarn (LoadSource&) const = 0; - virtual bool shouldCutoff (LoadSource&) const = 0; -}; - -#endif diff --git a/modules/ripple_app/main/ripple_LoadManager.cpp b/modules/ripple_app/main/ripple_LoadManager.cpp index 46189eff2..56ed18181 100644 --- a/modules/ripple_app/main/ripple_LoadManager.cpp +++ b/modules/ripple_app/main/ripple_LoadManager.cpp @@ -8,8 +8,8 @@ SETUP_LOG (LoadManager) //------------------------------------------------------------------------------ -class LoadManager - : public ILoadManager +class LoadManagerImp + : public LoadManager , public beast::InterruptibleThread::EntryPoint { private: @@ -59,8 +59,8 @@ private: }; public: - LoadManager () - : mLock (this, "LoadManager", __FILE__, __LINE__) + LoadManagerImp () + : mLock (this, "LoadManagerImp", __FILE__, __LINE__) , m_thread ("loadmgr") , m_logThread ("loadmgr_log") , mCreditRate (100) @@ -115,7 +115,7 @@ public: } private: - ~LoadManager () + ~LoadManagerImp () { UptimeTimer::getInstance ().endManualUpdates (); @@ -430,7 +430,8 @@ private: //------------------------------------------------------------------------------ -ILoadManager* ILoadManager::New () +LoadManager* LoadManager::New () { - return new LoadManager; + ScopedPointer object (new LoadManagerImp); + return object.release (); } diff --git a/modules/ripple_app/main/ripple_LoadManager.h b/modules/ripple_app/main/ripple_LoadManager.h new file mode 100644 index 000000000..33b570757 --- /dev/null +++ b/modules/ripple_app/main/ripple_LoadManager.h @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_LOADMANAGER_H_INCLUDEd +#define RIPPLE_LOADMANAGER_H_INCLUDEd + +/** Manages load sources. + + This object creates an associated thread to maintain a clock. + + When the server is overloaded by a particular peer it issues a warning + first. This allows friendly peers to reduce their consumption of resources, + or disconnect from the server. + + The warning system is used instead of merely dropping, because hostile + peers can just reconnect anyway. + + @see LoadSource, LoadType +*/ +class LoadManager +{ +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 (); + + /** Destroy the manager. + + The destructor returns only after the thread has stopped. + */ + 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 startThread () = 0; + + /** Turn on deadlock detection. + + The deadlock detector begins in a disabled state. After this function + is called, it will report deadlocks using a separate thread whenever + the reset function is not called at least once per 10 seconds. + + @see resetDeadlockDetector + */ + // VFALCO NOTE it seems that the deadlock detector has an "armed" state to prevent it + // from going off during program startup if there's a lengthy initialization + // operation taking place? + // + virtual void activateDeadlockDetector () = 0; + + /** Reset the deadlock detection timer. + + A dedicated thread monitors the deadlock timer, and if too much + time passes it will produce log warnings. + */ + virtual void resetDeadlockDetector () = 0; + + /** Update an endpoint to reflect an imposed load. + + The balance of the endpoint is adjusted based on the heuristic cost + of the indicated load. + + @return `true` if the endpoint should be warned or punished. + */ + virtual bool applyLoadCharge (LoadSource& sourceToAdjust, LoadType loadToImpose) const = 0; + + // VFALCO TODO Eliminate these two functions and just make applyLoadCharge() + // return a LoadSource::Disposition + // + virtual bool shouldWarn (LoadSource&) const = 0; + virtual bool shouldCutoff (LoadSource&) const = 0; +}; + +#endif diff --git a/modules/ripple_app/misc/NetworkOPs.cpp b/modules/ripple_app/misc/NetworkOPs.cpp index 88b2b695a..90974a300 100644 --- a/modules/ripple_app/misc/NetworkOPs.cpp +++ b/modules/ripple_app/misc/NetworkOPs.cpp @@ -78,7 +78,7 @@ void NetworkOPs::processHeartbeatTimer () // VFALCO NOTE This is for diagnosing a crash on exit Application& app (getApp ()); - ILoadManager& mgr (app.getLoadManager ()); + LoadManager& mgr (app.getLoadManager ()); mgr.resetDeadlockDetector (); std::size_t const numPeers = getApp().getPeers ().getPeerVector ().size (); diff --git a/modules/ripple_app/ripple_app.cpp b/modules/ripple_app/ripple_app.cpp index 91f585b9a..9786a303b 100644 --- a/modules/ripple_app/ripple_app.cpp +++ b/modules/ripple_app/ripple_app.cpp @@ -126,7 +126,7 @@ namespace ripple #include "misc/ripple_NicknameState.h" #include "ledger/Ledger.h" #include "ledger/SerializedValidation.h" -#include "main/ripple_ILoadManager.h" +#include "main/ripple_LoadManager.h" #include "misc/ripple_ProofOfWork.h" #include "misc/ripple_InfoSub.h" #include "misc/ripple_OrderBook.h" diff --git a/modules/ripple_app/ripple_app.h b/modules/ripple_app/ripple_app.h index 904382cc9..9c832762c 100644 --- a/modules/ripple_app/ripple_app.h +++ b/modules/ripple_app/ripple_app.h @@ -11,9 +11,7 @@ */ /** Core classes. - This module contains the Ripple core instance object and related objects. - @defgroup ripple_app */ diff --git a/modules/ripple_core/functional/LoadSource.h b/modules/ripple_core/functional/LoadSource.h new file mode 100644 index 000000000..f56dbb7e5 --- /dev/null +++ b/modules/ripple_core/functional/LoadSource.h @@ -0,0 +1,165 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_CORE_FUNCTIONAL_LOADSOURCE_H_INCLUDED +#define RIPPLE_CORE_FUNCTIONAL_LOADSOURCE_H_INCLUDED + +/** Tracks the consumption of resources at an endpoint. + + To prevent monopolization of server resources or attacks on servers, + resource consumption is monitored at each endpoint. When consumption + exceeds certain thresholds, costs are imposed. Costs include charging + additional XRP for transactions, requiring a proof of work to be + performed, or simply disconnecting the endpoint. + + Currently, consumption endpoints include websocket connections used to + service clients, and peer connections used to create the peer to peer + overlay network implementing the Ripple protcool. + + The current "balance" of a LoadSource represents resource consumption + debt or credit. Debt is accrued when bad loads are imposed. Credit is + granted when good loads are imposed. When the balance crosses heuristic + thresholds, costs are increased on the endpoint. + + The balance is represented as a unitless relative quantity. + + @note Although RPC connections consume resources, they are transient and + cannot be rate limited. It is advised not to expose RPC interfaces + to the general public. +*/ +class LoadSource +{ +public: + // VFALCO TODO Use these dispositions + /* + enum Disposition + { + none, + shouldWarn, + shouldDrop, + }; + */ + + /** Construct a load source. + + Sources with admin privileges have relaxed or no restrictions + on resource consumption. + + @param admin `true` if the source should have admin privileges. + */ + // VFALCO TODO See who is constructing this with a parameter + explicit LoadSource (bool admin) + : mBalance (0) + , mFlags (admin ? lsfPrivileged : 0) + , mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ()) + , mLastWarning (0) + , mLogged (false) + { + } + + /** Construct a load source with a given name. + The endpoint is considered non-privileged. + */ + explicit LoadSource (std::string const& name) + : mName (name) + , mBalance (0) + , mFlags (0) + , mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ()) + , mLastWarning (0) + , mLogged (false) + { + } + + /** Change the name of the source. + + An endpoint can be created before it's name is known. For example, + on an incoming connection before the IP and port have been determined. + */ + // VFALCO TODO Figure out a way to construct the LoadSource object with + // the proper name instead of renaming it later. + // + void rename (std::string const& name) noexcept + { + mName = name; + } + + /** Retrieve the name of this endpoint. + */ + std::string const& getName () const noexcept + { + return mName; + } + + /** Determine if this endpoint is privileged. + */ + bool isPrivileged () const noexcept + { + return (mFlags & lsfPrivileged) != 0; + } + + /** Grant the privileged attribute on this endpoint. + */ + void setPrivileged () noexcept + { + mFlags |= lsfPrivileged; + } + + /** Retrieve the load debit or credit associated with the endpoint. + + The balance is represented in a unitless relative quantity + indicating the heuristically weighted amount of resource consumption. + */ + int getBalance () const noexcept + { + return mBalance; + } + + /** Returns true if the endpoint received a log warning. + */ + bool isLogged () const noexcept + { + return mLogged; + } + + /** Reset the flag indicating the endpoint received a log warning. + */ + void clearLogged () noexcept + { + mLogged = false; + } + + /** Indicate that this endpoint is an outgoing connection. + */ + void setOutbound () noexcept + { + mFlags |= lsfOutbound; + } + + /** Returns true if this endpoint is an outgoing connection. + */ + bool isOutbound () const + { + return (mFlags & lsfOutbound) != 0; + } + +private: + // VFALCO Make this not a friend + friend class LoadManagerImp; + + // VFALCO TODO Rename these for clarity + static const int lsfPrivileged = 1; + static const int lsfOutbound = 2; + +private: + std::string mName; + int mBalance; + int mFlags; + int mLastUpdate; + int mLastWarning; + bool mLogged; +}; + +#endif diff --git a/modules/ripple_core/functional/LoadType.h b/modules/ripple_core/functional/LoadType.h new file mode 100644 index 000000000..9fba854d8 --- /dev/null +++ b/modules/ripple_core/functional/LoadType.h @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_CORE_FUNCTIONAL_LOADTYPE_H_INCLUDED +#define RIPPLE_CORE_FUNCTIONAL_LOADTYPE_H_INCLUDED + +// types of load that can be placed on the server +/** The type of load placed on the server. +*/ +/* VFALCO TODO + - Remove LT_ from each enum + - Put LoadType into a struct like this: + (Note this is modeled after boost::system::error_code::err_c) + + struct LoadType + { + enum load_c + { + invalidRequest, + //... + } + }; + + // For parameters + typedef LoadType::load_c LoadTypeParam; + + // Example of passing a LoadType: + peer->applyLoadCharge (LoadType::newTransaction); + + // Example function prototype + void applyLoadCharge (LoadTypeParam loadType); +*/ +enum LoadType +{ + // Bad things + LT_InvalidRequest, // A request that we can immediately tell is invalid + LT_RequestNoReply, // A request that we cannot satisfy + LT_InvalidSignature, // An object whose signature we had to check and it failed + LT_UnwantedData, // Data we have no use for + LT_BadPoW, // Proof of work not valid + LT_BadData, // Data we have to verify before rejecting + + // RPC loads + LT_RPCInvalid, // An RPC request that we can immediately tell is invalid. + LT_RPCReference, // A default "reference" unspecified load + LT_RPCException, // An RPC load that causes an exception + LT_RPCBurden, // A particularly burdensome RPC load + + // Good things + LT_NewTrusted, // A new transaction/validation/proposal we trust + LT_NewTransaction, // A new, valid transaction + LT_NeededData, // Data we requested + + // Requests + LT_RequestData, // A request that is hard to satisfy, disk access + LT_CheapQuery, // A query that is trivial, cached data + + LT_MAX // MUST BE LAST +}; + +#endif diff --git a/modules/ripple_core/ripple_core.h b/modules/ripple_core/ripple_core.h index e3849298c..029ca0b50 100644 --- a/modules/ripple_core/ripple_core.h +++ b/modules/ripple_core/ripple_core.h @@ -28,8 +28,8 @@ namespace ripple { -// VFALCO NOTE Indentation shows dependency hierarchy -// +// Order matters + /***/#include "functional/ripple_ConfigSections.h" /**/#include "functional/ripple_Config.h" /**/#include "functional/ripple_ILoadFeeTrack.h" @@ -37,6 +37,8 @@ namespace ripple /*..*/#include "functional/ripple_LoadMonitor.h" /*.*/#include "functional/ripple_Job.h" /**/#include "functional/ripple_JobQueue.h" +/*.*/#include "functional/LoadType.h" +/**/#include "functional/LoadSource.h" #include "validator/ripple_Validator.h" #include "validator/ripple_ValidatorList.h"