mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
Full Refactor of LoadManager
This commit is contained in:
@@ -1762,7 +1762,7 @@
|
||||
<ClInclude Include="..\..\src\cpp\ripple\LedgerMaster.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\LedgerProposal.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\LedgerTiming.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_LoadManager.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_ILoadManager.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_InboundLedgers.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\NetworkOPs.h" />
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_NicknameState.h" />
|
||||
|
||||
@@ -600,9 +600,6 @@
|
||||
<ClCompile Include="..\..\src\cpp\ripple\ripple_NicknameState.cpp">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\ripple\ripple_LoadManager.cpp">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\ripple\ripple_Application.cpp">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClCompile>
|
||||
@@ -900,6 +897,9 @@
|
||||
<ClCompile Include="..\..\modules\ripple_core\functional\ripple_LoadFeeTrack.cpp">
|
||||
<Filter>1. Modules\ripple_core\functional</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\ripple\ripple_LoadManager.cpp">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\cpp\protobuf\src\google\protobuf\service.h">
|
||||
@@ -1409,9 +1409,6 @@
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_NicknameState.h">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_LoadManager.h">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_IApplication.h">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClInclude>
|
||||
@@ -1725,6 +1722,9 @@
|
||||
<ClInclude Include="..\..\modules\ripple_core\functional\ripple_ILoadFeeTrack.h">
|
||||
<Filter>1. Modules\ripple_core\functional</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\cpp\ripple\ripple_ILoadManager.h">
|
||||
<Filter>1. Modules\ripple_app\refactored</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\cpp\protobuf\src\google\protobuf\descriptor.proto">
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
#include "src/cpp/ripple/Ledger.h"
|
||||
|
||||
#include "src/cpp/ripple/SerializedValidation.h"
|
||||
#include "src/cpp/ripple/ripple_LoadManager.h"
|
||||
#include "src/cpp/ripple/ripple_ILoadManager.h"
|
||||
|
||||
// These have few dependencies
|
||||
#include "src/cpp/ripple/ripple_DatabaseCon.h"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
@ingroup ripple_client
|
||||
*/
|
||||
|
||||
/*
|
||||
#include <set>
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
@@ -22,6 +23,8 @@
|
||||
|
||||
#include "../ripple_data/ripple_data.h"
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
#include "src/cpp/ripple/ripple_InfoSub.h"
|
||||
|
||||
@@ -44,7 +47,7 @@
|
||||
#include "src/cpp/ripple/Ledger.h"
|
||||
#include "src/cpp/ripple/ripple_LedgerEntrySet.h"
|
||||
#include "src/cpp/ripple/TransactionEngine.h"
|
||||
#include "src/cpp/ripple/ripple_LoadManager.h"
|
||||
#include "src/cpp/ripple/ripple_ILoadManager.h"
|
||||
#include "src/cpp/ripple/ripple_Peer.h"
|
||||
#include "src/cpp/ripple/ripple_PeerSet.h"
|
||||
#include "src/cpp/ripple/ripple_InboundLedger.h"
|
||||
|
||||
@@ -616,6 +616,9 @@ void NetworkOPs::checkState (const boost::system::error_code& result)
|
||||
|
||||
if ((result == boost::asio::error::operation_aborted) || theConfig.RUN_STANDALONE)
|
||||
{
|
||||
// VFALCO NOTE Should never get here. This is probably dead code.
|
||||
// If RUN_STANDALONE is set then this function isn't called.
|
||||
//
|
||||
WriteLog (lsFATAL, NetworkOPs) << "Network state timer error: " << result;
|
||||
return;
|
||||
}
|
||||
@@ -623,7 +626,7 @@ void NetworkOPs::checkState (const boost::system::error_code& result)
|
||||
{
|
||||
ScopedLock sl (theApp->getMasterLock ());
|
||||
|
||||
theApp->getLoadManager ().noDeadLock ();
|
||||
theApp->getLoadManager ().resetDeadlockDetector ();
|
||||
|
||||
std::vector<Peer::pointer> peerList = theApp->getPeers ().getPeerVector ();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,13 +15,34 @@
|
||||
class NetworkOPs;
|
||||
class InfoSub;
|
||||
|
||||
// VFALCO TODO Refactor to abstract interface IRPCHandler
|
||||
//
|
||||
class RPCHandler
|
||||
{
|
||||
NetworkOPs* mNetOps;
|
||||
InfoSub::pointer mInfoSub;
|
||||
int mRole;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
GUEST,
|
||||
USER,
|
||||
ADMIN,
|
||||
FORBID
|
||||
};
|
||||
|
||||
typedef Json::Value (RPCHandler::*doFuncPtr) (Json::Value params, int& cost, ScopedLock& MasterLockHolder);
|
||||
explicit RPCHandler (NetworkOPs* netOps);
|
||||
|
||||
RPCHandler (NetworkOPs* netOps, InfoSub::pointer infoSub);
|
||||
|
||||
Json::Value doCommand (const Json::Value& jvRequest, int role, LoadType* loadType);
|
||||
|
||||
Json::Value doRpcCommand (const std::string& strCommand, Json::Value& jvParams, int iRole, LoadType* loadType);
|
||||
|
||||
private:
|
||||
typedef Json::Value (RPCHandler::*doFuncPtr) (
|
||||
Json::Value params,
|
||||
LoadType* loadType,
|
||||
ScopedLock& MasterLockHolder);
|
||||
|
||||
// VFALCO TODO Document these and give the enumeration a label.
|
||||
enum
|
||||
{
|
||||
optNone = 0,
|
||||
@@ -31,102 +52,115 @@ class RPCHandler
|
||||
};
|
||||
|
||||
// Utilities
|
||||
|
||||
void addSubmitPath (Json::Value& txJSON);
|
||||
boost::unordered_set<RippleAddress> parseAccountIds (const Json::Value& jvArray);
|
||||
|
||||
boost::unordered_set <RippleAddress> parseAccountIds (const Json::Value& jvArray);
|
||||
|
||||
Json::Value transactionSign (Json::Value jvRequest, bool bSubmit, bool bFailHard, ScopedLock& mlh);
|
||||
|
||||
Json::Value lookupLedger (Json::Value jvRequest, Ledger::pointer& lpLedger);
|
||||
|
||||
Json::Value getMasterGenerator (Ledger::ref lrLedger, const RippleAddress& naRegularSeed, RippleAddress& naMasterGenerator);
|
||||
Json::Value authorize (Ledger::ref lrLedger, const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID,
|
||||
RippleAddress& naAccountPublic, RippleAddress& naAccountPrivate,
|
||||
STAmount& saSrcBalance, const STAmount& saFee, AccountState::pointer& asSrc,
|
||||
const RippleAddress& naVerifyGenerator);
|
||||
Json::Value accounts (Ledger::ref lrLedger, const RippleAddress& naMasterGenerator);
|
||||
Json::Value getMasterGenerator (
|
||||
Ledger::ref lrLedger,
|
||||
const RippleAddress& naRegularSeed,
|
||||
RippleAddress& naMasterGenerator);
|
||||
|
||||
Json::Value accountFromString (Ledger::ref lrLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex, const bool bStrict);
|
||||
Json::Value authorize (
|
||||
Ledger::ref lrLedger,
|
||||
const RippleAddress& naRegularSeed,
|
||||
const RippleAddress& naSrcAccountID,
|
||||
RippleAddress& naAccountPublic,
|
||||
RippleAddress& naAccountPrivate,
|
||||
STAmount& saSrcBalance,
|
||||
const STAmount& saFee,
|
||||
AccountState::pointer& asSrc,
|
||||
const RippleAddress& naVerifyGenerator);
|
||||
|
||||
Json::Value doAccountInfo (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doAccountLines (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doAccountOffers (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doAccountTransactions (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doBookOffers (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doConnect (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doConsensusInfo (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
#if ENABLE_INSECURE
|
||||
Json::Value doDataDelete (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doDataFetch (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doDataStore (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
#endif
|
||||
Json::Value doFeature (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doGetCounts (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doInternal (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLedger (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLogLevel (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLogRotate (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doNicknameInfo (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doOwnerInfo (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doPeers (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doPathFind (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doPing (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doProfile (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doProofCreate (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doProofSolve (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doProofVerify (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doRandom (Json::Value jvRequest, int& cost, ScopedLock& mlh);
|
||||
Json::Value doRipplePathFind (Json::Value jvRequest, int& cost, ScopedLock& mlh);
|
||||
Json::Value doServerInfo (Json::Value params, int& cost, ScopedLock& mlh); // for humans
|
||||
Json::Value doServerState (Json::Value params, int& cost, ScopedLock& mlh); // for machines
|
||||
Json::Value doSessionClose (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doSessionOpen (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doSMS (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doStop (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doSign (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doSubmit (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doTx (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doTxHistory (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlAdd (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlDelete (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlFetch (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlList (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlLoad (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlNetwork (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlReset (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnlScore (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value accounts (
|
||||
Ledger::ref lrLedger,
|
||||
const RippleAddress& naMasterGenerator);
|
||||
|
||||
Json::Value doValidationCreate (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doValidationSeed (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value accountFromString (
|
||||
Ledger::ref lrLedger,
|
||||
RippleAddress& naAccount,
|
||||
bool& bIndex,
|
||||
const std::string& strIdent,
|
||||
const int iIndex,
|
||||
const bool bStrict);
|
||||
|
||||
Json::Value doWalletAccounts (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doWalletLock (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doWalletPropose (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doWalletSeed (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doWalletUnlock (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doWalletVerify (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doAccountInfo (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doAccountLines (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doAccountOffers (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doAccountTransactions (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doBookOffers (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doConnect (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doConsensusInfo (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doFeature (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doGetCounts (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doInternal (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedger (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedgerAccept (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedgerClosed (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedgerCurrent (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedgerEntry (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLedgerHeader (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLogLevel (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLogRotate (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doNicknameInfo (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doOwnerInfo (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doPathFind (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doPeers (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doPing (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doProfile (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doProofCreate (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doProofSolve (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doProofVerify (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doRandom (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doRipplePathFind (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doSMS (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doServerInfo (Json::Value params, LoadType* loadType, ScopedLock& mlh); // for humans
|
||||
Json::Value doServerState (Json::Value params, LoadType* loadType, ScopedLock& mlh); // for machines
|
||||
Json::Value doSessionClose (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doSessionOpen (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doSign (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doStop (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doSubmit (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doSubscribe (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doTransactionEntry (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doTx (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doTxHistory (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlAdd (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlDelete (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlFetch (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlList (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlLoad (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlNetwork (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlReset (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnlScore (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doUnsubscribe (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doValidationCreate (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doValidationSeed (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletAccounts (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletLock (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletPropose (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletSeed (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletUnlock (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doWalletVerify (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
|
||||
#if ENABLE_INSECURE
|
||||
Json::Value doLogin (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doDataDelete (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doDataFetch (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doDataStore (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
Json::Value doLogin (Json::Value params, LoadType* loadType, ScopedLock& mlh);
|
||||
#endif
|
||||
|
||||
Json::Value doLedgerAccept (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLedgerClosed (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLedgerCurrent (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLedgerEntry (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doLedgerHeader (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doTransactionEntry (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
private:
|
||||
NetworkOPs* mNetOps;
|
||||
InfoSub::pointer mInfoSub;
|
||||
|
||||
Json::Value doSubscribe (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
Json::Value doUnsubscribe (Json::Value params, int& cost, ScopedLock& mlh);
|
||||
|
||||
public:
|
||||
|
||||
enum { GUEST, USER, ADMIN, FORBID };
|
||||
|
||||
RPCHandler (NetworkOPs* netOps);
|
||||
RPCHandler (NetworkOPs* netOps, InfoSub::pointer infoSub);
|
||||
|
||||
Json::Value doCommand (const Json::Value& jvRequest, int role, int& cost);
|
||||
Json::Value doRpcCommand (const std::string& strCommand, Json::Value& jvParams, int iRole, int& cost);
|
||||
// VFALCO TODO Create an enumeration for this.
|
||||
int mRole;
|
||||
};
|
||||
|
||||
class RPCInternalHandler
|
||||
|
||||
@@ -153,8 +153,11 @@ std::string RPCServer::handleRequest (const std::string& requestStr)
|
||||
RPCHandler mRPCHandler (mNetOps);
|
||||
|
||||
WriteLog (lsINFO, RPCServer) << valParams;
|
||||
int cost = 10;
|
||||
Json::Value result = mRPCHandler.doRpcCommand (strMethod, valParams, mRole, cost);
|
||||
LoadType loadType = LT_RPCReference;
|
||||
Json::Value result = mRPCHandler.doRpcCommand (strMethod, valParams, mRole, &loadType);
|
||||
|
||||
// VFALCO NOTE We discard loadType since there is no endpoint to punish
|
||||
|
||||
WriteLog (lsINFO, RPCServer) << result;
|
||||
|
||||
std::string strReply = JSONRPCReply (result, Json::Value (), id);
|
||||
|
||||
@@ -86,6 +86,8 @@ public:
|
||||
{
|
||||
if (theApp->getLoadManager ().shouldCutoff (mLoadSource))
|
||||
{
|
||||
// VFALCO TODO This must be implemented before open sourcing
|
||||
|
||||
#if SHOULD_DISCONNECT
|
||||
// FIXME: Must dispatch to strand
|
||||
connection_ptr ptr = mConnection.lock ();
|
||||
@@ -97,6 +99,8 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
// Requests without "command" are invalid.
|
||||
//
|
||||
if (!jvRequest.isMember ("command"))
|
||||
{
|
||||
Json::Value jvResult (Json::objectValue);
|
||||
@@ -111,11 +115,12 @@ public:
|
||||
jvResult["id"] = jvRequest["id"];
|
||||
}
|
||||
|
||||
theApp->getLoadManager ().adjust (mLoadSource, -5);
|
||||
theApp->getLoadManager ().applyLoadCharge (mLoadSource, LT_RPCInvalid);
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
int cost = 10;
|
||||
LoadType loadType = LT_RPCReference;
|
||||
RPCHandler mRPCHandler (&mNetwork, boost::dynamic_pointer_cast<InfoSub> (this->shared_from_this ()));
|
||||
Json::Value jvResult (Json::objectValue);
|
||||
|
||||
@@ -129,11 +134,16 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["result"] = mRPCHandler.doCommand (jvRequest, iRole, cost);
|
||||
jvResult["result"] = mRPCHandler.doCommand (jvRequest, iRole, &loadType);
|
||||
}
|
||||
|
||||
if (theApp->getLoadManager ().adjust (mLoadSource, -cost) && theApp->getLoadManager ().shouldWarn (mLoadSource))
|
||||
// Debit/credit the load and see if we should include a warning.
|
||||
//
|
||||
if (theApp->getLoadManager ().applyLoadCharge (mLoadSource, loadType) &&
|
||||
theApp->getLoadManager ().shouldWarn (mLoadSource))
|
||||
{
|
||||
jvResult["warning"] = "load";
|
||||
}
|
||||
|
||||
// Currently we will simply unwrap errors returned by the RPC
|
||||
// API, in the future maybe we can make the responses
|
||||
|
||||
@@ -35,8 +35,9 @@ void startServer ()
|
||||
|
||||
RPCHandler rhHandler (&theApp->getOPs ());
|
||||
|
||||
int cost = 10;
|
||||
Json::Value jvResult = rhHandler.doCommand (jvCommand, RPCHandler::ADMIN, cost);
|
||||
// VFALCO TODO Clean up this magic number
|
||||
LoadType loadType = LT_RPCReference;
|
||||
Json::Value jvResult = rhHandler.doCommand (jvCommand, RPCHandler::ADMIN, &loadType);
|
||||
|
||||
if (!theConfig.QUIET)
|
||||
std::cerr << "Result: " << jvResult << std::endl;
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// VFALCO TODO Wrap this up in something neater. Replace NULL with nullptr
|
||||
IApplication* theApp = NULL;
|
||||
// VFALCO TODO Clean this global up
|
||||
volatile bool doShutdown = false;
|
||||
|
||||
// VFALCO TODO Wrap this up in something neater.
|
||||
IApplication* theApp = nullptr;
|
||||
|
||||
class Application;
|
||||
|
||||
@@ -73,9 +76,9 @@ public:
|
||||
return mMasterLock;
|
||||
}
|
||||
|
||||
LoadManager& getLoadManager ()
|
||||
ILoadManager& getLoadManager ()
|
||||
{
|
||||
return mLoadMgr;
|
||||
return *m_loadManager;
|
||||
}
|
||||
|
||||
TXQueue& getTxnQueue ()
|
||||
@@ -218,7 +221,6 @@ private:
|
||||
SLECache mSLECache;
|
||||
SNTPClient mSNTPClient;
|
||||
JobQueue mJobQueue;
|
||||
LoadManager mLoadMgr;
|
||||
TXQueue mTxnQueue;
|
||||
OrderBookDB mOrderBookDB;
|
||||
|
||||
@@ -231,6 +233,7 @@ private:
|
||||
beast::ScopedPointer <IUniqueNodeList> mUNL;
|
||||
beast::ScopedPointer <IProofOfWorkFactory> mProofOfWorkFactory;
|
||||
beast::ScopedPointer <IPeers> mPeers;
|
||||
beast::ScopedPointer <ILoadManager> m_loadManager;
|
||||
// VFALCO End Clean stuff
|
||||
|
||||
DatabaseCon* mRpcDB;
|
||||
@@ -274,6 +277,7 @@ Application::Application ()
|
||||
, mUNL (IUniqueNodeList::New (mIOService))
|
||||
, mProofOfWorkFactory (IProofOfWorkFactory::New ())
|
||||
, mPeers (IPeers::New (mIOService))
|
||||
, m_loadManager (ILoadManager::New ())
|
||||
// VFALCO End new stuff
|
||||
// VFALCO TODO replace all NULL with nullptr
|
||||
, mRpcDB (NULL)
|
||||
@@ -296,7 +300,8 @@ Application::Application ()
|
||||
HashMaps::getInstance ().initializeNonce <size_t> ();
|
||||
}
|
||||
|
||||
|
||||
// VFALCO TODO Tidy these up into some class with accessors.
|
||||
//
|
||||
extern const char* RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[],
|
||||
*NetNodeDBInit[], *PathFindDBInit[];
|
||||
extern int RpcDBCount, TxnDBCount, LedgerDBCount, WalletDBCount, HashNodeDBCount,
|
||||
@@ -327,8 +332,6 @@ static void InitDB (DatabaseCon** dbCon, const char* fileName, const char* dbIni
|
||||
*dbCon = new DatabaseCon (fileName, dbInit, dbCount);
|
||||
}
|
||||
|
||||
volatile bool doShutdown = false;
|
||||
|
||||
#ifdef SIGINT
|
||||
void sigIntHandler (int)
|
||||
{
|
||||
@@ -349,6 +352,10 @@ static void runIO (boost::asio::io_service& io)
|
||||
io.run ();
|
||||
}
|
||||
|
||||
// VFALCO TODO Break this function up into many small initialization segments.
|
||||
// Or better yet refactor these initializations into RAII classes
|
||||
// which are members of the Application object.
|
||||
//
|
||||
void Application::setup ()
|
||||
{
|
||||
// VFALCO NOTE: 0 means use heuristics to determine the thread count.
|
||||
@@ -356,7 +363,8 @@ void Application::setup ()
|
||||
|
||||
mSweepTimer.expires_from_now (boost::posix_time::seconds (10));
|
||||
mSweepTimer.async_wait (boost::bind (&Application::sweep, this));
|
||||
mLoadMgr.init ();
|
||||
|
||||
m_loadManager->startThread ();
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef SIGINT
|
||||
@@ -617,6 +625,8 @@ void Application::setup ()
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO NOTE the state timer resets the deadlock detector.
|
||||
//
|
||||
mNetOps.setStateTimer ();
|
||||
}
|
||||
}
|
||||
@@ -629,7 +639,12 @@ void Application::run ()
|
||||
}
|
||||
|
||||
if (!theConfig.RUN_STANDALONE)
|
||||
theApp->getLoadManager ().arm ();
|
||||
{
|
||||
// VFALCO NOTE This seems unnecessary. If we properly refactor the load
|
||||
// manager then the deadlock detector can just always be "armed"
|
||||
//
|
||||
theApp->getLoadManager ().activateDeadlockDetector ();
|
||||
}
|
||||
|
||||
mIOService.run (); // This blocks
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
virtual IFeeVote& getFeeVote () = 0;
|
||||
virtual IHashRouter& getHashRouter () = 0;
|
||||
virtual ILoadFeeTrack& getFeeTrack () = 0;
|
||||
virtual ILoadManager& getLoadManager () = 0;
|
||||
virtual IPeers& getPeers () = 0;
|
||||
virtual IProofOfWorkFactory& getProofOfWorkFactory () = 0;
|
||||
virtual IUniqueNodeList& getUNL () = 0;
|
||||
@@ -72,22 +73,23 @@ public:
|
||||
|
||||
virtual HashedObjectStore& getHashedObjectStore () = 0;
|
||||
virtual JobQueue& getJobQueue () = 0;
|
||||
virtual InboundLedgers& getInboundLedgers () = 0;
|
||||
virtual InboundLedgers& getInboundLedgers () = 0;
|
||||
virtual LedgerMaster& getLedgerMaster () = 0;
|
||||
virtual LoadManager& getLoadManager () = 0;
|
||||
virtual NetworkOPs& getOPs () = 0;
|
||||
virtual OrderBookDB& getOrderBookDB () = 0;
|
||||
virtual PeerDoor& getPeerDoor () = 0;
|
||||
virtual TransactionMaster& getMasterTransaction () = 0;
|
||||
virtual TXQueue& getTxnQueue () = 0;
|
||||
virtual LocalCredentials& getLocalCredentials () = 0;
|
||||
virtual LocalCredentials& getLocalCredentials () = 0;
|
||||
|
||||
virtual DatabaseCon* getRpcDB () = 0;
|
||||
virtual DatabaseCon* getTxnDB () = 0;
|
||||
virtual DatabaseCon* getLedgerDB () = 0;
|
||||
virtual DatabaseCon* getWalletDB () = 0;
|
||||
virtual DatabaseCon* getNetNodeDB () = 0;
|
||||
virtual DatabaseCon* getPathFindDB () = 0;
|
||||
// VFALCO NOTE It looks like this isn't used...
|
||||
//virtual DatabaseCon* getNetNodeDB () = 0;
|
||||
// VFALCO NOTE It looks like this isn't used...
|
||||
//virtual DatabaseCon* getPathFindDB () = 0;
|
||||
virtual DatabaseCon* getHashNodeDB () = 0;
|
||||
|
||||
virtual leveldb::DB* getHashNodeLDB () = 0;
|
||||
|
||||
265
src/cpp/ripple/ripple_ILoadManager.h
Normal file
265
src/cpp/ripple/ripple_ILoadManager.h
Normal file
@@ -0,0 +1,265 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 Why even bother with a warning? Why can't we just drop?
|
||||
// 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.
|
||||
|
||||
@see LoadSource, LoadType
|
||||
*/
|
||||
class ILoadManager
|
||||
{
|
||||
public:
|
||||
/** Create a new manager.
|
||||
|
||||
@note The thresholds for warnings and punishments are in
|
||||
the ctor-initializer
|
||||
*/
|
||||
static ILoadManager* New ();
|
||||
|
||||
virtual ~ILoadManager () { }
|
||||
|
||||
/** Start the associated thread.
|
||||
|
||||
This is here to prevent the deadlock detector from activating during
|
||||
a lengthy program initialization.
|
||||
|
||||
@note In stand-alone mode, this might not get called.
|
||||
*/
|
||||
// VFALCO TODO Simplify the two stage initialization to one stage (construction).
|
||||
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
|
||||
@@ -90,7 +90,7 @@ void InboundLedgers::gotLedgerData (Job&, uint256 hash,
|
||||
WriteLog (lsTRACE, InboundLedger) << "Got data for ledger we're not acquiring";
|
||||
|
||||
if (peer)
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -105,14 +105,14 @@ void InboundLedgers::gotLedgerData (Job&, uint256 hash,
|
||||
if (packet.nodes_size () < 1)
|
||||
{
|
||||
WriteLog (lsWARNING, InboundLedger) << "Got empty base data";
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ledger->takeBase (packet.nodes (0).nodedata ()))
|
||||
{
|
||||
WriteLog (lsWARNING, InboundLedger) << "Got invalid base data";
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ void InboundLedgers::gotLedgerData (Job&, uint256 hash,
|
||||
if (packet.nodes ().size () <= 0)
|
||||
{
|
||||
WriteLog (lsINFO, InboundLedger) << "Got response with no nodes";
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ void InboundLedgers::gotLedgerData (Job&, uint256 hash,
|
||||
if (!node.has_nodeid () || !node.has_nodedata ())
|
||||
{
|
||||
WriteLog (lsWARNING, InboundLedger) << "Got bad node";
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ void InboundLedgers::gotLedgerData (Job&, uint256 hash,
|
||||
}
|
||||
|
||||
WriteLog (lsWARNING, InboundLedger) << "Not sure what ledger data we got";
|
||||
peer->punishPeer (LT_InvalidRequest);
|
||||
peer->applyLoadCharge (LT_InvalidRequest);
|
||||
}
|
||||
|
||||
void InboundLedgers::sweep ()
|
||||
|
||||
@@ -6,302 +6,426 @@
|
||||
|
||||
SETUP_LOG (LoadManager)
|
||||
|
||||
LoadManager::LoadManager (int creditRate, int creditLimit, int debitWarn, int debitLimit)
|
||||
: mCreditRate (creditRate)
|
||||
, mCreditLimit (creditLimit)
|
||||
, mDebitWarn (debitWarn)
|
||||
, mDebitLimit (debitLimit)
|
||||
, mShutdown (false)
|
||||
, mArmed (false)
|
||||
, mDeadLock (0)
|
||||
, mCosts (LT_MAX)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class LoadManager : public ILoadManager
|
||||
{
|
||||
addCost (Cost (LT_InvalidRequest, -10, LC_CPU | LC_Network));
|
||||
addCost (Cost (LT_RequestNoReply, -1, LC_CPU | LC_Disk));
|
||||
addCost (Cost (LT_InvalidSignature, -100, LC_CPU));
|
||||
addCost (Cost (LT_UnwantedData, -5, LC_CPU | LC_Network));
|
||||
addCost (Cost (LT_BadData, -20, LC_CPU));
|
||||
private:
|
||||
/* Entry mapping utilization to cost.
|
||||
|
||||
addCost (Cost (LT_NewTrusted, -10, 0));
|
||||
addCost (Cost (LT_NewTransaction, -2, 0));
|
||||
addCost (Cost (LT_NeededData, -10, 0));
|
||||
|
||||
addCost (Cost (LT_RequestData, -5, LC_Disk | LC_Network));
|
||||
addCost (Cost (LT_CheapQuery, -1, LC_CPU));
|
||||
}
|
||||
|
||||
void LoadManager::init ()
|
||||
{
|
||||
UptimeTimer::getInstance ().beginManualUpdates ();
|
||||
|
||||
boost::thread (boost::bind (&LoadManager::threadEntry, this)).detach ();
|
||||
}
|
||||
|
||||
LoadManager::~LoadManager ()
|
||||
{
|
||||
UptimeTimer::getInstance ().endManualUpdates ();
|
||||
|
||||
// VFALCO What is this loop? it doesn't seem to do anything useful.
|
||||
do
|
||||
The cost is expressed as a unitless relative quantity. These
|
||||
mappings are statically loaded at startup with heuristic values.
|
||||
*/
|
||||
class Cost
|
||||
{
|
||||
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
|
||||
public:
|
||||
// VFALCO TODO Eliminate this default ctor somehow
|
||||
Cost ()
|
||||
: m_loadType ()
|
||||
, m_cost (0)
|
||||
, m_resourceFlags (0)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
|
||||
if (!mShutdown)
|
||||
return;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
void LoadManager::noDeadLock ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
//mDeadLock = mUptime;
|
||||
mDeadLock = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
}
|
||||
|
||||
int LoadManager::getCreditRate () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mCreditRate;
|
||||
}
|
||||
|
||||
int LoadManager::getCreditLimit () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mCreditLimit;
|
||||
}
|
||||
|
||||
int LoadManager::getDebitWarn () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mDebitWarn;
|
||||
}
|
||||
|
||||
int LoadManager::getDebitLimit () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mDebitLimit;
|
||||
}
|
||||
|
||||
void LoadManager::setCreditRate (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mCreditRate = r;
|
||||
}
|
||||
|
||||
void LoadManager::setCreditLimit (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mCreditLimit = r;
|
||||
}
|
||||
|
||||
void LoadManager::setDebitWarn (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mDebitWarn = r;
|
||||
}
|
||||
|
||||
void LoadManager::setDebitLimit (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mDebitLimit = r;
|
||||
}
|
||||
|
||||
void LoadManager::canonicalize (LoadSource& source, int now) const
|
||||
{
|
||||
if (source.mLastUpdate != now)
|
||||
{
|
||||
if (source.mLastUpdate < now)
|
||||
|
||||
Cost (LoadType loadType, int cost, int resourceFlags)
|
||||
: m_loadType (loadType)
|
||||
, m_cost (cost)
|
||||
, m_resourceFlags (resourceFlags)
|
||||
{
|
||||
source.mBalance += mCreditRate * (now - source.mLastUpdate);
|
||||
|
||||
if (source.mBalance > mCreditLimit)
|
||||
{
|
||||
source.mBalance = mCreditLimit;
|
||||
source.mLogged = false;
|
||||
}
|
||||
}
|
||||
|
||||
source.mLastUpdate = now;
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadManager::shouldWarn (LoadSource& source) const
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
|
||||
if (source.isPrivileged () || (source.mBalance > mDebitWarn) || (source.mLastWarning == now))
|
||||
return false;
|
||||
|
||||
source.mLastWarning = now;
|
||||
}
|
||||
logWarning (source.getName ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadManager::shouldCutoff (LoadSource& source) const
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
|
||||
if (source.isPrivileged () || (source.mBalance > mDebitLimit))
|
||||
return false;
|
||||
|
||||
if (source.mLogged)
|
||||
return true;
|
||||
|
||||
source.mLogged = true;
|
||||
}
|
||||
logDisconnect (source.getName ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadManager::adjust (LoadSource& source, LoadType t) const
|
||||
{
|
||||
// FIXME: Scale by category
|
||||
Cost cost = mCosts[static_cast<int> (t)];
|
||||
return adjust (source, cost.mCost);
|
||||
}
|
||||
|
||||
bool LoadManager::adjust (LoadSource& source, int credits) const
|
||||
{
|
||||
// return: true = need to warn/cutoff
|
||||
|
||||
// We do it this way in case we want to add exponential decay later
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
source.mBalance += credits;
|
||||
|
||||
if (source.mBalance > mCreditLimit)
|
||||
source.mBalance = mCreditLimit;
|
||||
|
||||
if (source.isPrivileged ()) // privileged sources never warn/cutoff
|
||||
return false;
|
||||
|
||||
if ((source.mBalance >= mDebitLimit) && (source.mLastWarning == now)) // no need to warn
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void LogDeadLock (int dlTime)
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "Server stalled for " << dlTime << " seconds.";
|
||||
}
|
||||
|
||||
void LoadManager::threadEntry ()
|
||||
{
|
||||
setCallingThreadName ("loadmgr");
|
||||
|
||||
// VFALCO TODO replace this with a beast Time object?
|
||||
//
|
||||
// Initialize the clock to the current time.
|
||||
boost::posix_time::ptime t = boost::posix_time::microsec_clock::universal_time ();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
LoadType getLoadType () const
|
||||
{
|
||||
// VFALCO NOTE What is this lock protecting?
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return m_loadType;
|
||||
}
|
||||
|
||||
// Check for the shutdown flag.
|
||||
if (mShutdown)
|
||||
int getCost () const
|
||||
{
|
||||
return m_cost;
|
||||
}
|
||||
|
||||
int getResourceFlags () const
|
||||
{
|
||||
return m_resourceFlags;
|
||||
}
|
||||
|
||||
public:
|
||||
// VFALCO TODO Make these private and const
|
||||
LoadType m_loadType;
|
||||
int m_cost;
|
||||
int m_resourceFlags;
|
||||
};
|
||||
|
||||
public:
|
||||
LoadManager ()
|
||||
: mCreditRate (100)
|
||||
, mCreditLimit (500)
|
||||
, mDebitWarn (-500)
|
||||
, mDebitLimit (-1000)
|
||||
, mShutdown (false)
|
||||
, mArmed (false)
|
||||
, mDeadLock (0)
|
||||
, mCosts (LT_MAX)
|
||||
{
|
||||
/** Flags indicating the type of load.
|
||||
|
||||
Utilization may include any combination of:
|
||||
|
||||
- CPU
|
||||
- Storage space
|
||||
- Network transfer
|
||||
*/
|
||||
// VFALCO NOTE These flags are not used...
|
||||
enum
|
||||
{
|
||||
flagDisk = 1,
|
||||
flagCpu = 2,
|
||||
flagNet = 4
|
||||
};
|
||||
|
||||
// VFALCO TODO Replace this with a function that uses a simple switch statement...
|
||||
//
|
||||
addCost (Cost (LT_InvalidRequest, -10, flagCpu | flagNet));
|
||||
addCost (Cost (LT_RequestNoReply, -1, flagCpu | flagDisk));
|
||||
addCost (Cost (LT_InvalidSignature, -100, flagCpu));
|
||||
addCost (Cost (LT_UnwantedData, -5, flagCpu | flagNet));
|
||||
addCost (Cost (LT_BadData, -20, flagCpu));
|
||||
|
||||
addCost (Cost (LT_RPCInvalid, -10, flagCpu | flagNet));
|
||||
addCost (Cost (LT_RPCReference, -10, flagCpu | flagNet));
|
||||
addCost (Cost (LT_RPCException, -20, flagCpu | flagNet));
|
||||
addCost (Cost (LT_RPCBurden, -50, flagCpu | flagNet));
|
||||
|
||||
// VFALCO NOTE Why do these supposedly "good" load types still have a negative cost?
|
||||
//
|
||||
addCost (Cost (LT_NewTrusted, -10, 0));
|
||||
addCost (Cost (LT_NewTransaction, -2, 0));
|
||||
addCost (Cost (LT_NeededData, -10, 0));
|
||||
|
||||
addCost (Cost (LT_RequestData, -5, flagDisk | flagNet));
|
||||
addCost (Cost (LT_CheapQuery, -1, flagCpu));
|
||||
}
|
||||
|
||||
private:
|
||||
~LoadManager ()
|
||||
{
|
||||
UptimeTimer::getInstance ().endManualUpdates ();
|
||||
|
||||
// VFALCO TODO What is the purpose of this loop? Figure out
|
||||
// a better way to do it.
|
||||
for (;;)
|
||||
{
|
||||
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
|
||||
{
|
||||
// VFALCO NOTE Why clear the flag now?
|
||||
mShutdown = false;
|
||||
return;
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
|
||||
if (!mShutdown)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VFALCO NOTE I think this is to reduce calls to the operating system
|
||||
// for retrieving the current time.
|
||||
//
|
||||
// TODO Instead of incrementing can't we just retrieve the current
|
||||
// time again?
|
||||
//
|
||||
// Manually update the timer.
|
||||
UptimeTimer::getInstance ().incrementElapsedTime ();
|
||||
void startThread ()
|
||||
{
|
||||
UptimeTimer::getInstance ().beginManualUpdates ();
|
||||
|
||||
// Measure the amount of time we have been deadlocked, in seconds.
|
||||
//
|
||||
// VFALCO NOTE mDeadLock is a canary for detecting the condition.
|
||||
int const timeSpentDeadlocked = UptimeTimer::getInstance ().getElapsedSeconds () - mDeadLock;
|
||||
boost::thread (boost::bind (&LoadManager::threadEntry, this)).detach ();
|
||||
}
|
||||
|
||||
if (mArmed && (timeSpentDeadlocked >= 10))
|
||||
void canonicalize (LoadSource& source, int now) const
|
||||
{
|
||||
if (source.mLastUpdate != now)
|
||||
{
|
||||
if (source.mLastUpdate < now)
|
||||
{
|
||||
// Report the deadlocked condition every 10 seconds
|
||||
if ((timeSpentDeadlocked % 10) == 0)
|
||||
source.mBalance += mCreditRate * (now - source.mLastUpdate);
|
||||
|
||||
if (source.mBalance > mCreditLimit)
|
||||
{
|
||||
// VFALCO TODO Replace this with a dedicated thread with call queue.
|
||||
//
|
||||
boost::thread (BIND_TYPE (&LogDeadLock, timeSpentDeadlocked)).detach ();
|
||||
source.mBalance = mCreditLimit;
|
||||
source.mLogged = false;
|
||||
}
|
||||
}
|
||||
|
||||
source.mLastUpdate = now;
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldWarn (LoadSource& source) const
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
|
||||
if (source.isPrivileged () || (source.mBalance > mDebitWarn) || (source.mLastWarning == now))
|
||||
return false;
|
||||
|
||||
source.mLastWarning = now;
|
||||
}
|
||||
logWarning (source.getName ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool shouldCutoff (LoadSource& source) const
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
|
||||
if (source.isPrivileged () || (source.mBalance > mDebitLimit))
|
||||
return false;
|
||||
|
||||
if (source.mLogged)
|
||||
return true;
|
||||
|
||||
source.mLogged = true;
|
||||
}
|
||||
logDisconnect (source.getName ());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool applyLoadCharge (LoadSource& source, LoadType loadType) const
|
||||
{
|
||||
// FIXME: Scale by category
|
||||
Cost cost = mCosts[static_cast<int> (loadType)];
|
||||
|
||||
return adjust (source, cost.m_cost);
|
||||
}
|
||||
|
||||
bool adjust (LoadSource& source, int credits) const
|
||||
{
|
||||
// return: true = need to warn/cutoff
|
||||
|
||||
// We do it this way in case we want to add exponential decay later
|
||||
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
canonicalize (source, now);
|
||||
source.mBalance += credits;
|
||||
|
||||
if (source.mBalance > mCreditLimit)
|
||||
source.mBalance = mCreditLimit;
|
||||
|
||||
if (source.isPrivileged ()) // privileged sources never warn/cutoff
|
||||
return false;
|
||||
|
||||
if ((source.mBalance >= mDebitLimit) && (source.mLastWarning == now)) // no need to warn
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void logWarning (const std::string& source) const
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsDEBUG, LoadManager) << "Load warning from empty source";
|
||||
else
|
||||
WriteLog (lsINFO, LoadManager) << "Load warning: " << source;
|
||||
}
|
||||
|
||||
void logDisconnect (const std::string& source) const
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsINFO, LoadManager) << "Disconnect for empty source";
|
||||
else
|
||||
WriteLog (lsWARNING, LoadManager) << "Disconnect for: " << source;
|
||||
}
|
||||
|
||||
// VFALCO TODO Implement this and stop accessing the vector directly
|
||||
//Cost const& getCost (LoadType loadType) const;
|
||||
int getCost (LoadType t) const
|
||||
{
|
||||
return mCosts [static_cast <int> (t)].getCost ();
|
||||
}
|
||||
|
||||
void resetDeadlockDetector ()
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mDeadLock = UptimeTimer::getInstance ().getElapsedSeconds ();
|
||||
}
|
||||
|
||||
void activateDeadlockDetector ()
|
||||
{
|
||||
mArmed = true;
|
||||
}
|
||||
|
||||
static void logDeadlock (int dlTime)
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "Server stalled for " << dlTime << " seconds.";
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO These used to be public but are apparently not used. Find out why.
|
||||
/*
|
||||
int getCreditRate () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mCreditRate;
|
||||
}
|
||||
|
||||
int getCreditLimit () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mCreditLimit;
|
||||
}
|
||||
|
||||
int getDebitWarn () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mDebitWarn;
|
||||
}
|
||||
|
||||
int getDebitLimit () const
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
return mDebitLimit;
|
||||
}
|
||||
|
||||
void setCreditRate (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mCreditRate = r;
|
||||
}
|
||||
|
||||
void setCreditLimit (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mCreditLimit = r;
|
||||
}
|
||||
|
||||
void setDebitWarn (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mDebitWarn = r;
|
||||
}
|
||||
|
||||
void setDebitLimit (int r)
|
||||
{
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
mDebitLimit = r;
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
void addCost (const Cost& c)
|
||||
{
|
||||
mCosts [static_cast <int> (c.getLoadType ())] = c;
|
||||
}
|
||||
|
||||
// VFALCO NOTE Where's the thread object? It's not a data member...
|
||||
//
|
||||
void threadEntry ()
|
||||
{
|
||||
setCallingThreadName ("loadmgr");
|
||||
|
||||
// VFALCO TODO replace this with a beast Time object?
|
||||
//
|
||||
// Initialize the clock to the current time.
|
||||
boost::posix_time::ptime t = boost::posix_time::microsec_clock::universal_time ();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
// VFALCO NOTE What is this lock protecting?
|
||||
boost::mutex::scoped_lock sl (mLock);
|
||||
|
||||
// Check for the shutdown flag.
|
||||
if (mShutdown)
|
||||
{
|
||||
// VFALCO NOTE Why clear the flag now?
|
||||
mShutdown = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we go over 500 seconds spent deadlocked, it means that the
|
||||
// deadlock resolution code has failed, which qualifies as undefined
|
||||
// behavior.
|
||||
// VFALCO NOTE I think this is to reduce calls to the operating system
|
||||
// for retrieving the current time.
|
||||
//
|
||||
assert (timeSpentDeadlocked < 500);
|
||||
// TODO Instead of incrementing can't we just retrieve the current
|
||||
// time again?
|
||||
//
|
||||
// Manually update the timer.
|
||||
UptimeTimer::getInstance ().incrementElapsedTime ();
|
||||
|
||||
// Measure the amount of time we have been deadlocked, in seconds.
|
||||
//
|
||||
// VFALCO NOTE mDeadLock is a canary for detecting the condition.
|
||||
int const timeSpentDeadlocked = UptimeTimer::getInstance ().getElapsedSeconds () - mDeadLock;
|
||||
|
||||
// VFALCO NOTE I think that "armed" refers to the deadlock detector
|
||||
//
|
||||
if (mArmed && (timeSpentDeadlocked >= 10))
|
||||
{
|
||||
// Report the deadlocked condition every 10 seconds
|
||||
if ((timeSpentDeadlocked % 10) == 0)
|
||||
{
|
||||
// VFALCO TODO Replace this with a dedicated thread with call queue.
|
||||
//
|
||||
boost::thread (BIND_TYPE (&logDeadlock, timeSpentDeadlocked)).detach ();
|
||||
}
|
||||
|
||||
// If we go over 500 seconds spent deadlocked, it means that the
|
||||
// deadlock resolution code has failed, which qualifies as undefined
|
||||
// behavior.
|
||||
//
|
||||
assert (timeSpentDeadlocked < 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
bool change;
|
||||
|
||||
bool change;
|
||||
// VFALCO TODO Eliminate the dependence on the Application object.
|
||||
// Choices include constructing with the job queue / feetracker.
|
||||
// Another option is using an observer pattern to invert the dependency.
|
||||
if (theApp->getJobQueue ().isOverloaded ())
|
||||
{
|
||||
WriteLog (lsINFO, LoadManager) << theApp->getJobQueue ().getJson (0);
|
||||
change = theApp->getFeeTrack ().raiseLocalFee ();
|
||||
}
|
||||
else
|
||||
{
|
||||
change = theApp->getFeeTrack ().lowerLocalFee ();
|
||||
}
|
||||
|
||||
// VFALCO TODO Eliminate the dependence on the Application object.
|
||||
// Choices include constructing with the job queue / feetracker.
|
||||
// Another option is using an observer pattern to invert the dependency.
|
||||
if (theApp->getJobQueue ().isOverloaded ())
|
||||
{
|
||||
WriteLog (lsINFO, LoadManager) << theApp->getJobQueue ().getJson (0);
|
||||
change = theApp->getFeeTrack ().raiseLocalFee ();
|
||||
}
|
||||
else
|
||||
{
|
||||
change = theApp->getFeeTrack ().lowerLocalFee ();
|
||||
}
|
||||
if (change)
|
||||
{
|
||||
// VFALCO TODO replace this with a Listener / observer and subscribe in NetworkOPs or Application
|
||||
theApp->getOPs ().reportFeeChange ();
|
||||
}
|
||||
|
||||
if (change)
|
||||
{
|
||||
// VFALCO TODO replace this with a Listener / observer and subscribe in NetworkOPs or Application
|
||||
theApp->getOPs ().reportFeeChange ();
|
||||
}
|
||||
t += boost::posix_time::seconds (1);
|
||||
boost::posix_time::time_duration when = t - boost::posix_time::microsec_clock::universal_time ();
|
||||
|
||||
t += boost::posix_time::seconds (1);
|
||||
boost::posix_time::time_duration when = t - boost::posix_time::microsec_clock::universal_time ();
|
||||
|
||||
if ((when.is_negative ()) || (when.total_seconds () > 1))
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "time jump";
|
||||
t = boost::posix_time::microsec_clock::universal_time ();
|
||||
if ((when.is_negative ()) || (when.total_seconds () > 1))
|
||||
{
|
||||
WriteLog (lsWARNING, LoadManager) << "time jump";
|
||||
t = boost::posix_time::microsec_clock::universal_time ();
|
||||
}
|
||||
else
|
||||
boost::this_thread::sleep (when);
|
||||
}
|
||||
else
|
||||
boost::this_thread::sleep (when);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadManager::logWarning (const std::string& source) const
|
||||
private:
|
||||
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 mShutdown;
|
||||
bool mArmed;
|
||||
|
||||
int mDeadLock; // Detect server deadlocks
|
||||
|
||||
mutable boost::mutex mLock; // VFALCO TODO Replace with juce::Mutex and remove the mutable attribute
|
||||
|
||||
std::vector <Cost> mCosts;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ILoadManager* ILoadManager::New ()
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsDEBUG, LoadManager) << "Load warning from empty source";
|
||||
else
|
||||
WriteLog (lsINFO, LoadManager) << "Load warning: " << source;
|
||||
return new LoadManager;
|
||||
}
|
||||
|
||||
void LoadManager::logDisconnect (const std::string& source) const
|
||||
{
|
||||
if (source.empty ())
|
||||
WriteLog (lsINFO, LoadManager) << "Disconnect for empty source";
|
||||
else
|
||||
WriteLog (lsWARNING, LoadManager) << "Disconnect for: " << source;
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_LOADMANAGER_H
|
||||
#define RIPPLE_LOADMANAGER_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
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
// load categories
|
||||
// VFALCO NOTE These look like bit flags, name them accordingly
|
||||
enum
|
||||
{
|
||||
LC_Disk = 1,
|
||||
LC_CPU = 2,
|
||||
LC_Network = 4
|
||||
};
|
||||
|
||||
/** 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
|
||||
- Peer connections
|
||||
|
||||
@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
|
||||
{
|
||||
private:
|
||||
// VFALCO Make this not a friend
|
||||
friend class LoadManager;
|
||||
|
||||
public:
|
||||
// load source flags
|
||||
static const int lsfPrivileged = 1;
|
||||
static const int lsfOutbound = 2; // outbound connection
|
||||
|
||||
public:
|
||||
/** Construct a load source.
|
||||
|
||||
Sources with admin privileges have relaxed or no restrictions
|
||||
on resource consumption.
|
||||
|
||||
@param admin `true` if the source has admin privileges.
|
||||
*/
|
||||
explicit LoadSource (bool admin)
|
||||
: mBalance (0)
|
||||
, mFlags (admin ? lsfPrivileged : 0)
|
||||
, mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ())
|
||||
, mLastWarning (0)
|
||||
, mLogged (false)
|
||||
{
|
||||
}
|
||||
|
||||
explicit LoadSource (std::string const& name)
|
||||
: mName (name)
|
||||
, mBalance (0)
|
||||
, mFlags (0)
|
||||
, mLastUpdate (UptimeTimer::getInstance ().getElapsedSeconds ())
|
||||
, mLastWarning (0)
|
||||
, mLogged (false)
|
||||
{
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
std::string const& getName () const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
bool isPrivileged () const
|
||||
{
|
||||
return (mFlags & lsfPrivileged) != 0;
|
||||
}
|
||||
|
||||
void setPrivileged ()
|
||||
{
|
||||
mFlags |= lsfPrivileged;
|
||||
}
|
||||
|
||||
int getBalance () const
|
||||
{
|
||||
return mBalance;
|
||||
}
|
||||
|
||||
bool isLogged () const
|
||||
{
|
||||
return mLogged;
|
||||
}
|
||||
|
||||
void clearLogged ()
|
||||
{
|
||||
mLogged = false;
|
||||
}
|
||||
|
||||
void setOutbound ()
|
||||
{
|
||||
mFlags |= lsfOutbound;
|
||||
}
|
||||
|
||||
bool isOutbound () const
|
||||
{
|
||||
return (mFlags & lsfOutbound) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
int mBalance;
|
||||
int mFlags;
|
||||
int mLastUpdate;
|
||||
int mLastWarning;
|
||||
bool mLogged;
|
||||
};
|
||||
|
||||
// a collection of load sources
|
||||
class LoadManager
|
||||
{
|
||||
public:
|
||||
LoadManager (int creditRate = 100,
|
||||
int creditLimit = 500,
|
||||
int debitWarn = -500,
|
||||
int debitLimit = -1000);
|
||||
|
||||
~LoadManager ();
|
||||
|
||||
void init ();
|
||||
|
||||
bool shouldWarn (LoadSource&) const;
|
||||
|
||||
bool shouldCutoff (LoadSource&) const;
|
||||
|
||||
bool adjust (LoadSource&, int credits) const; // return value: false=balance okay, true=warn/cutoff
|
||||
|
||||
bool adjust (LoadSource&, LoadType l) const;
|
||||
|
||||
void logWarning (const std::string&) const;
|
||||
|
||||
void logDisconnect (const std::string&) const;
|
||||
|
||||
int getCost (LoadType t) const
|
||||
{
|
||||
return mCosts [static_cast <int> (t)].mCost;
|
||||
}
|
||||
|
||||
void noDeadLock ();
|
||||
|
||||
void arm ()
|
||||
{
|
||||
mArmed = true;
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO These used to be public but are apparently not used. Find out why.
|
||||
int getCreditRate () const;
|
||||
int getCreditLimit () const;
|
||||
int getDebitWarn () const;
|
||||
int getDebitLimit () const;
|
||||
void setCreditRate (int);
|
||||
void setCreditLimit (int);
|
||||
void setDebitWarn (int);
|
||||
void setDebitLimit (int);
|
||||
|
||||
private:
|
||||
class Cost
|
||||
{
|
||||
public:
|
||||
Cost ()
|
||||
: mType ()
|
||||
, mCost (0)
|
||||
, mCategories (0)
|
||||
{
|
||||
}
|
||||
|
||||
Cost (LoadType typeOfLoad, int cost, int category)
|
||||
: mType (typeOfLoad)
|
||||
, mCost (cost)
|
||||
, mCategories (category)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
// VFALCO TODO Make these private and const
|
||||
LoadType mType;
|
||||
int mCost;
|
||||
int mCategories;
|
||||
};
|
||||
|
||||
void canonicalize (LoadSource&, int upTime) const;
|
||||
|
||||
void addCost (const Cost& c)
|
||||
{
|
||||
mCosts [static_cast <int> (c.mType)] = c;
|
||||
}
|
||||
|
||||
// VFALCO NOTE Where's the thread object? It's not a data member...
|
||||
//
|
||||
void threadEntry ();
|
||||
|
||||
private:
|
||||
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 mShutdown;
|
||||
bool mArmed;
|
||||
|
||||
int mDeadLock; // Detect server deadlocks
|
||||
|
||||
mutable boost::mutex mLock; // VFALCO TODO Replace with juce::Mutex and remove the mutable attribute
|
||||
|
||||
std::vector <Cost> mCosts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// vim:ts=4
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
|
||||
void sendGetPeers ();
|
||||
|
||||
void punishPeer (LoadType);
|
||||
void applyLoadCharge (LoadType);
|
||||
|
||||
Json::Value getJson ();
|
||||
bool isConnected () const
|
||||
@@ -1070,7 +1070,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
|
||||
if (tx->getStatus () == INVALID)
|
||||
{
|
||||
theApp->getHashRouter ().setFlag (stx->getTransactionID (), SF_BAD);
|
||||
Peer::punishPeer (peer, LT_InvalidSignature);
|
||||
Peer::applyLoadCharge (peer, LT_InvalidSignature);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1083,7 +1083,7 @@ static void checkTransaction (Job&, int flags, SerializedTransaction::pointer st
|
||||
catch (...)
|
||||
{
|
||||
theApp->getHashRouter ().setFlags (stx->getTransactionID (), SF_BAD);
|
||||
punishPeer (peer, LT_InvalidRequest);
|
||||
applyLoadCharge (peer, LT_InvalidRequest);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1109,7 +1109,7 @@ void PeerImp::recvTransaction (protocol::TMTransaction& packet, ScopedLock& Mast
|
||||
// we have seen this transaction recently
|
||||
if (isSetBit (flags, SF_BAD))
|
||||
{
|
||||
punishPeer (LT_InvalidSignature);
|
||||
applyLoadCharge (LT_InvalidSignature);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1166,7 +1166,7 @@ static void checkPropose (Job& job, boost::shared_ptr<protocol::TMProposeSet> pa
|
||||
Peer::pointer p = peer.lock ();
|
||||
WriteLog (lsWARNING, Peer) << "proposal with previous ledger fails signature check: " <<
|
||||
(p ? p->getIP () : std::string ("???"));
|
||||
Peer::punishPeer (peer, LT_InvalidSignature);
|
||||
Peer::applyLoadCharge (peer, LT_InvalidSignature);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -1210,14 +1210,14 @@ void PeerImp::recvPropose (const boost::shared_ptr<protocol::TMProposeSet>& pack
|
||||
(set.signature ().size () < 56) || (set.nodepubkey ().size () > 128) || (set.signature ().size () > 128))
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Received proposal is malformed";
|
||||
punishPeer (LT_InvalidSignature);
|
||||
applyLoadCharge (LT_InvalidSignature);
|
||||
return;
|
||||
}
|
||||
|
||||
if (set.has_previousledger () && (set.previousledger ().size () != 32))
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Received proposal is malformed";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1278,7 +1278,7 @@ void PeerImp::recvHaveTxSet (protocol::TMHaveTransactionSet& packet)
|
||||
|
||||
if (packet.hash ().size () != (256 / 8))
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1289,7 +1289,7 @@ void PeerImp::recvHaveTxSet (protocol::TMHaveTransactionSet& packet)
|
||||
addTxSet (hash);
|
||||
|
||||
if (!theApp->getOPs ().hasTXSet (shared_from_this (), hash, packet.status ()))
|
||||
punishPeer (LT_UnwantedData);
|
||||
applyLoadCharge (LT_UnwantedData);
|
||||
}
|
||||
|
||||
static void checkValidation (Job&, SerializedValidation::pointer val, uint256 signingHash,
|
||||
@@ -1303,7 +1303,7 @@ static void checkValidation (Job&, SerializedValidation::pointer val, uint256 si
|
||||
if (!isCluster && !val->isValid (signingHash))
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Validation is invalid";
|
||||
Peer::punishPeer (peer, LT_InvalidRequest);
|
||||
Peer::applyLoadCharge (peer, LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1329,7 +1329,7 @@ static void checkValidation (Job&, SerializedValidation::pointer val, uint256 si
|
||||
catch (...)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Exception processing validation";
|
||||
Peer::punishPeer (peer, LT_InvalidRequest);
|
||||
Peer::applyLoadCharge (peer, LT_InvalidRequest);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1342,7 +1342,7 @@ void PeerImp::recvValidation (const boost::shared_ptr<protocol::TMValidation>& p
|
||||
if (packet->validation ().size () < 50)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Too small validation from peer";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1376,7 @@ void PeerImp::recvValidation (const boost::shared_ptr<protocol::TMValidation>& p
|
||||
catch (...)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Exception processing validation";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1591,7 +1591,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
|
||||
// this is an answer to a proof of work we requested
|
||||
if (packet.response ().size () != (256 / 8))
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1609,7 +1609,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
|
||||
// return error message
|
||||
// WRITEME
|
||||
if (r != powTOOEASY)
|
||||
punishPeer (LT_BadPoW);
|
||||
applyLoadCharge (LT_BadPoW);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1629,7 +1629,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
|
||||
|
||||
if ((packet.challenge ().size () != (256 / 8)) || (packet.target ().size () != (256 / 8)))
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1640,7 +1640,7 @@ void PeerImp::recvProofWork (protocol::TMProofWork& packet)
|
||||
|
||||
if (!pow->isValid ())
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1731,7 +1731,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
|
||||
if ((!packet.has_ledgerhash () || packet.ledgerhash ().size () != 32))
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
WriteLog (lsWARNING, Peer) << "invalid request for TX candidate set data";
|
||||
return;
|
||||
}
|
||||
@@ -1766,7 +1766,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
}
|
||||
|
||||
WriteLog (lsERROR, Peer) << "We do not have the map our peer wants " << getIP ();
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1788,7 +1788,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
|
||||
if (packet.ledgerhash ().size () != 32)
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
WriteLog (lsWARNING, Peer) << "Invalid request";
|
||||
return;
|
||||
}
|
||||
@@ -1844,14 +1844,14 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
}
|
||||
else
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
WriteLog (lsWARNING, Peer) << "Can't figure out what ledger they want";
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!ledger) || (packet.has_ledgerseq () && (packet.ledgerseq () != ledger->getLedgerSeq ())))
|
||||
{
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
|
||||
if (ShouldLog (lsWARNING, Peer))
|
||||
{
|
||||
@@ -1931,7 +1931,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
if ((!map) || (packet.nodeids_size () == 0))
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Can't find map or empty request";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1944,7 +1944,7 @@ void PeerImp::recvGetLedger (protocol::TMGetLedger& packet, ScopedLock& MasterLo
|
||||
if (!mn.isValid ())
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Request for invalid node: " << logMe;
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2005,7 +2005,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
if (packet.nodes ().size () <= 0)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Ledger/TXset data with no nodes";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2021,7 +2021,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
else
|
||||
{
|
||||
WriteLog (lsINFO, Peer) << "Unable to route TX/ledger data reply";
|
||||
punishPeer (LT_UnwantedData);
|
||||
applyLoadCharge (LT_UnwantedData);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -2032,7 +2032,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
if (packet.ledgerhash ().size () != 32)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "TX candidate reply with invalid hash size";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2051,7 +2051,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
if (!node.has_nodeid () || !node.has_nodedata () || (node.nodeid ().size () != 33))
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "LedgerData request with invalid node ID";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2062,7 +2062,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
SHAMapAddNode san = theApp->getOPs ().gotTXData (shared_from_this (), hash, nodeIDs, nodeData);
|
||||
|
||||
if (san.isInvalid ())
|
||||
punishPeer (LT_UnwantedData);
|
||||
applyLoadCharge (LT_UnwantedData);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2072,7 +2072,7 @@ void PeerImp::recvLedger (const boost::shared_ptr<protocol::TMLedgerData>& packe
|
||||
BIND_TYPE (&InboundLedgers::gotLedgerData, &theApp->getInboundLedgers (),
|
||||
P_1, hash, packet_ptr, boost::weak_ptr<Peer> (shared_from_this ())));
|
||||
else
|
||||
punishPeer (LT_UnwantedData);
|
||||
applyLoadCharge (LT_UnwantedData);
|
||||
}
|
||||
|
||||
bool PeerImp::hasLedger (uint256 const& hash, uint32 seq) const
|
||||
@@ -2203,11 +2203,13 @@ void PeerImp::sendGetPeers ()
|
||||
sendPacket (packet, true);
|
||||
}
|
||||
|
||||
void PeerImp::punishPeer (LoadType l)
|
||||
void PeerImp::applyLoadCharge (LoadType loadType)
|
||||
{
|
||||
if (theApp->getLoadManager ().adjust (mLoad, l))
|
||||
if (theApp->getLoadManager ().applyLoadCharge (mLoad, loadType))
|
||||
{
|
||||
// WRITEME
|
||||
// UNIMPLEMENTED
|
||||
|
||||
// VFALCO TODO This needs to implemented before open sourcing.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2251,7 +2253,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr<protocol::TMGetObjectByHash>&
|
||||
if (packet->ledgerhash ().size () != 32)
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "FetchPack hash size malformed";
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2263,14 +2265,14 @@ void PeerImp::doFetchPack (const boost::shared_ptr<protocol::TMGetObjectByHash>&
|
||||
if (!haveLedger)
|
||||
{
|
||||
WriteLog (lsINFO, Peer) << "Peer requests fetch pack for ledger we don't have: " << hash;
|
||||
punishPeer (LT_RequestNoReply);
|
||||
applyLoadCharge (LT_RequestNoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!haveLedger->isClosed ())
|
||||
{
|
||||
WriteLog (lsWARNING, Peer) << "Peer requests fetch pack from open ledger: " << hash;
|
||||
punishPeer (LT_InvalidRequest);
|
||||
applyLoadCharge (LT_InvalidRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2279,7 +2281,7 @@ void PeerImp::doFetchPack (const boost::shared_ptr<protocol::TMGetObjectByHash>&
|
||||
if (!wantLedger)
|
||||
{
|
||||
WriteLog (lsINFO, Peer) << "Peer requests fetch pack for ledger whose predecessor we don't have: " << hash;
|
||||
punishPeer (LT_RequestNoReply);
|
||||
applyLoadCharge (LT_RequestNoReply);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2374,12 +2376,12 @@ Peer::pointer Peer::New (boost::asio::io_service& io_service,
|
||||
return Peer::pointer (new PeerImp (io_service, ctx, id, inbound));
|
||||
}
|
||||
|
||||
void Peer::punishPeer (const boost::weak_ptr<Peer>& wp, LoadType l)
|
||||
void Peer::applyLoadCharge (const boost::weak_ptr<Peer>& wp, LoadType l)
|
||||
{
|
||||
Peer::pointer p = wp.lock ();
|
||||
|
||||
if (p)
|
||||
p->punishPeer (l);
|
||||
p->applyLoadCharge (l);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -57,10 +57,10 @@ public:
|
||||
|
||||
virtual void sendGetPeers () = 0;
|
||||
|
||||
virtual void punishPeer (LoadType) = 0;
|
||||
virtual void applyLoadCharge (LoadType) = 0;
|
||||
|
||||
// VFALCO NOTE what's with this odd parameter passing? Why the static member?
|
||||
static void punishPeer (const boost::weak_ptr<Peer>&, LoadType);
|
||||
static void applyLoadCharge (const boost::weak_ptr<Peer>&, LoadType);
|
||||
|
||||
virtual Json::Value getJson () = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user