Refactor LoadFeeTrack into ILoadFeeTrack, split DatabaseCon out from Application.h

Conflicts:
	src/cpp/ripple/Application.cpp
This commit is contained in:
Vinnie Falco
2013-06-01 08:30:46 -07:00
parent f897b17027
commit ec732ed113
18 changed files with 394 additions and 267 deletions

View File

@@ -113,6 +113,10 @@ namespace boost {
// UInt256
#include <boost/functional/hash.hpp>
// ripple_PlatformMacros.h
#include <boost/bind.hpp>
#include <boost/function.hpp>
// VFALCO: TODO, remove this dependency!!!
#include <openssl/dh.h> // for DiffieHellmanUtil
#include <openssl/ripemd.h> // For HashUtilities

View File

@@ -23,6 +23,8 @@
#if (!defined(FORCE_NO_C11X) && (__cplusplus > 201100L)) || defined(FORCE_C11X)
// VFALCO: TODO, replace BIND_TYPE with a namespace lift
#define C11X
#include <functional>
#define UPTR_T std::unique_ptr
@@ -36,8 +38,6 @@
#else
#include <boost/bind.hpp>
#include <boost/function.hpp>
#define UPTR_T std::auto_ptr
#define MOVE_P(p) (p)
#define BIND_TYPE boost::bind

View File

@@ -124,12 +124,15 @@
// New abstract interfaces
#include "src/cpp/ripple/ripple_IFeatures.h"
#include "src/cpp/ripple/ripple_IFeeVote.h"
#include "src/cpp/ripple/ripple_ILoadFeeTrack.h"
#include "src/cpp/ripple/FeatureTable.h"
//------------------------------------------------------------------------------
// main
#include "src/cpp/ripple/ripple_DatabaseCon.cpp"
#include "src/cpp/ripple/Application.cpp"
#include "src/cpp/ripple/LoadManager.cpp"
// contracts
#include "src/cpp/ripple/Contract.cpp" // no log
@@ -192,6 +195,7 @@
// Implementation of interfaces
#include "src/cpp/ripple/ripple_FeeVote.cpp"
#include "src/cpp/ripple/ripple_LoadFeeTrack.cpp"
#ifdef _MSC_VER
//#pragma warning (pop)

View File

@@ -34,9 +34,10 @@
#pragma warning (disable: 4535) // call requires /EHa
#endif
#include "src/cpp/ripple/Application.h" // VFALCO: TODO Remove this dependency
#include "src/cpp/ripple/Config.cpp" // no log
#include "src/cpp/ripple/JobQueue.cpp"
#include "src/cpp/ripple/LoadManager.cpp"
#include "src/cpp/ripple/LoadMonitor.cpp"
#include "src/cpp/ripple/UpdateTables.cpp"
#include "src/cpp/ripple/main.cpp"

View File

@@ -28,6 +28,8 @@
#include "../websocketpp/src/logger/logger.hpp" // for ripple_LogWebSockets.cpp
#include "src/cpp/ripple/ripple_ILoadFeeTrack.h" // for NetworkOPs
// VFALCO: TODO, fix these warnings!
#ifdef _MSC_VER
//#pragma warning (push) // Causes spurious C4503 "decorated name exceeds maximum length"

View File

@@ -974,12 +974,24 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_DatabaseCon.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_FeeVote.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_LoadFeeTrack.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\cpp\ripple\rpc.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1640,8 +1652,10 @@
<ClInclude Include="src\cpp\ripple\RegularKeySetTransactor.h" />
<ClInclude Include="src\cpp\ripple\RippleCalc.h" />
<ClInclude Include="src\cpp\ripple\RippleState.h" />
<ClInclude Include="src\cpp\ripple\ripple_DatabaseCon.h" />
<ClInclude Include="src\cpp\ripple\ripple_IFeatures.h" />
<ClInclude Include="src\cpp\ripple\ripple_IFeeVote.h" />
<ClInclude Include="src\cpp\ripple\ripple_ILoadFeeTrack.h" />
<ClInclude Include="src\cpp\ripple\RPC.h" />
<ClInclude Include="src\cpp\ripple\RPCDoor.h" />
<ClInclude Include="src\cpp\ripple\RPCErr.h" />

View File

@@ -612,9 +612,6 @@
<ClCompile Include="src\cpp\ripple\JobQueue.cpp">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\LoadManager.cpp">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\LoadMonitor.cpp">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClCompile>
@@ -792,6 +789,15 @@
<ClCompile Include="src\cpp\ripple\Application.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_LoadFeeTrack.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\LoadManager.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
<ClCompile Include="src\cpp\ripple\ripple_DatabaseCon.cpp">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="database\sqlite3ext.h">
@@ -1253,9 +1259,6 @@
<ClInclude Include="src\cpp\ripple\JobQueue.h">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\LoadManager.h">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\LoadMonitor.h">
<Filter>1. Modules\ripple_main\_old</Filter>
</ClInclude>
@@ -1472,6 +1475,15 @@
<ClInclude Include="src\cpp\ripple\Application.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\ripple_ILoadFeeTrack.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\LoadManager.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
<ClInclude Include="src\cpp\ripple\ripple_DatabaseCon.h">
<Filter>1. Modules\ripple_ledger\main</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="SConstruct" />

View File

@@ -23,43 +23,42 @@ SETUP_LOG (Application)
LogPartition AutoSocketPartition("AutoSocket");
Application* theApp = NULL;
int DatabaseCon::sCount = 0;
DatabaseCon::DatabaseCon(const std::string& strName, const char *initStrings[], int initCount)
Application::Application()
: mIOService ((theConfig.NODE_SIZE >= 2) ? 2 : 1)
, mIOWork (mIOService)
, mAuxWork (mAuxService)
, mUNL (mIOService)
, mNetOps (mIOService, &mLedgerMaster)
, mTempNodeCache ("NodeCache", 16384, 90)
, mHashedObjectStore (16384, 300)
, mSLECache ("LedgerEntryCache", 4096, 120)
, mSNTPClient (mAuxService)
, mJobQueue (mIOService)
, mFeeVote (IFeeVote::New (10, 50 * SYSTEM_CURRENCY_PARTS, 12.5 * SYSTEM_CURRENCY_PARTS))
, mFeeTrack (ILoadFeeTrack::New ())
, mFeatureTable (2 * 7 * 24 * 60 * 60, 200) // two weeks, 200/256
// VFALCO: TODO replace all NULL with nullptr
, mRpcDB (NULL)
, mTxnDB (NULL)
, mLedgerDB (NULL)
, mWalletDB (NULL) // VFALCO: NOTE, are all these 'NULL' ctor params necessary?
, mNetNodeDB (NULL)
, mPathFindDB (NULL)
, mHashNodeDB (NULL)
// VFALCO: TODO eliminate USE_LEVELDB macro
#ifdef USE_LEVELDB
, mHashNodeLDB (NULL)
#endif
, mConnectionPool (mIOService)
, mPeerDoor (NULL)
, mRPCDoor (NULL)
, mWSPublicDoor (NULL)
, mWSPrivateDoor (NULL)
, mSweepTimer (mAuxService)
, mShutdown (false)
{
++sCount;
boost::filesystem::path pPath = (theConfig.RUN_STANDALONE && (theConfig.START_UP != Config::LOAD))
? "" // Use temporary files.
: (theConfig.DATA_DIR / strName); // Use regular db files.
mDatabase = new SqliteDatabase(pPath.string().c_str());
mDatabase->connect();
for(int i = 0; i < initCount; ++i)
mDatabase->executeSQL(initStrings[i], true);
}
DatabaseCon::~DatabaseCon()
{
mDatabase->disconnect();
delete mDatabase;
}
Application::Application() :
mIOService((theConfig.NODE_SIZE >= 2) ? 2 : 1),
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), mSLECache("LedgerEntryCache", 4096, 120),
mSNTPClient(mAuxService), mJobQueue(mIOService), mFeeTrack(),
mFeeVote (IFeeVote::New (10, 50 * SYSTEM_CURRENCY_PARTS, 12.5 * SYSTEM_CURRENCY_PARTS)),
mFeatureTable(2 * 7 * 24 * 60 * 60, 200), // two weeks, 200/256
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL),
mNetNodeDB(NULL), mPathFindDB(NULL), mHashNodeDB(NULL), mHashNodeLDB(NULL), mEphemeralLDB(NULL),
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
mSweepTimer(mAuxService), mShutdown(false)
{
getRand(mNonce256.begin(), mNonce256.size());
getRand(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
getRand (mNonce256.begin(), mNonce256.size());
getRand (reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
}
extern const char *RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[],
@@ -414,6 +413,7 @@ void Application::sweep()
Application::~Application()
{
delete mFeeTrack;
delete mFeeVote;
delete mTxnDB;
delete mLedgerDB;

View File

@@ -27,30 +27,18 @@
#include "TransactionQueue.h"
#include "OrderBookDB.h"
#include "ripple_DatabaseCon.h"
// VFALCO: TODO, Fix forward declares required for header dependency loops
class IFeatureTable;
class IFeeVote;
class ILoadFeeTrack;
class RPCDoor;
class PeerDoor;
typedef TaggedCache< uint256, std::vector<unsigned char>, UptimeTimerAdapter> NodeCache;
typedef TaggedCache< uint256, SLE, UptimeTimerAdapter> SLECache;
class DatabaseCon
{
protected:
Database* mDatabase;
boost::recursive_mutex mLock;
static int sCount;
public:
DatabaseCon(const std::string& name, const char *initString[], int countInit);
~DatabaseCon();
Database* getDB() { return mDatabase; }
boost::recursive_mutex& getDBLock() { return mLock; }
static int getCount() { return sCount; }
};
class Application
{
boost::asio::io_service mIOService, mAuxService;
@@ -73,10 +61,10 @@ class Application
JobQueue mJobQueue;
ProofOfWorkGenerator mPOWGen;
LoadManager mLoadMgr;
LoadFeeTrack mFeeTrack;
TXQueue mTxnQueue;
OrderBookDB mOrderBookDB;
IFeeVote* mFeeVote;
ILoadFeeTrack* mFeeTrack;
FeatureTable mFeatureTable;
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mNetNodeDB, *mPathFindDB, *mHashNodeDB;
@@ -129,7 +117,7 @@ public:
boost::recursive_mutex& getMasterLock() { return mMasterLock; }
ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
LoadManager& getLoadManager() { return mLoadMgr; }
LoadFeeTrack& getFeeTrack() { return mFeeTrack; }
ILoadFeeTrack& getFeeTrack() { return *mFeeTrack; }
TXQueue& getTxnQueue() { return mTxnQueue; }
PeerDoor& getPeerDoor() { return *mPeerDoor; }
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }

View File

@@ -12,6 +12,7 @@
#include "HashPrefixes.h"
// VFALCO: TODO Rename and replace these macros with variables.
#define SECTION_ACCOUNT_PROBE_MAX "account_probe_max"
#define SECTION_CLUSTER_NODES "cluster_nodes"
#define SECTION_DATABASE_PATH "database_path"

View File

@@ -72,6 +72,8 @@ struct SizedItem
int sizes[5];
};
// VFALCO: TODO, rename all fields to not look like macros, and be more verbose
// VFALCO: TODO, document every member
class Config
{
public:

View File

@@ -5,7 +5,6 @@
#include <boost/thread.hpp>
#include "Config.h"
#include "Application.h"
SETUP_LOG (JobQueue)
@@ -229,8 +228,9 @@ void JobQueue::shutdown()
mJobCond.wait(sl);
}
// set the number of thread serving the job queue to precisely this number
void JobQueue::setThreadCount(int c)
{ // set the number of thread serving the job queue to precisely this number
{
if (theConfig.RUN_STANDALONE)
c = 1;
else if (c == 0)
@@ -287,8 +287,12 @@ void JobQueue::IOThread(boost::mutex::scoped_lock& sl)
--mIOThreadCount;
}
// do jobs until asked to stop
void JobQueue::threadEntry()
{ // do jobs until asked to stop
{
// VFALCO: TODO, Replace this mutex nonsense
//
boost::mutex::scoped_lock sl(mJobLock);
while (1)
{

View File

@@ -186,137 +186,6 @@ bool LoadManager::adjust(LoadSource& source, int credits) const
return true;
}
uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint64 div)
{ // compute (value)*(mul)/(div) - avoid overflow but keep precision
static uint64 boundary = (0x00000000FFFFFFFF);
if (value > boundary) // Large value, avoid overflow
return (value / div) * mul;
else // Normal value, preserve accuracy
return (value * mul) / div;
}
uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin)
{
static uint64 midrange(0x00000000FFFFFFFF);
bool big = (fee > midrange);
if (big) // big fee, divide first to avoid overflow
fee /= baseFee;
else // normal fee, multiply first for accuracy
fee *= referenceFeeUnits;
uint32 feeFactor = std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee);
// Let admins pay the normal fee until the local load exceeds four times the remote
if (bAdmin && (feeFactor > mRemoteTxnLoadFee) && (feeFactor < (4 * mRemoteTxnLoadFee)))
feeFactor = mRemoteTxnLoadFee;
{
boost::mutex::scoped_lock sl(mLock);
fee = mulDiv(fee, feeFactor, lftNormalFee);
}
if (big) // Fee was big to start, must now multiply
fee *= referenceFeeUnits;
else // Fee was small to start, mst now divide
fee /= baseFee;
return fee;
}
uint64 LoadFeeTrack::scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
{
return mulDiv(fee, referenceFeeUnits, baseFee);
}
uint32 LoadFeeTrack::getRemoteFee()
{
boost::mutex::scoped_lock sl(mLock);
return mRemoteTxnLoadFee;
}
uint32 LoadFeeTrack::getLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
return mLocalTxnLoadFee;
}
uint32 LoadFeeTrack::getLoadFactor()
{
boost::mutex::scoped_lock sl(mLock);
return std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee);
}
void LoadFeeTrack::setRemoteFee(uint32 f)
{
boost::mutex::scoped_lock sl(mLock);
mRemoteTxnLoadFee = f;
}
bool LoadFeeTrack::raiseLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
if (++raiseCount < 2)
return false;
uint32 origFee = mLocalTxnLoadFee;
if (mLocalTxnLoadFee < mRemoteTxnLoadFee) // make sure this fee takes effect
mLocalTxnLoadFee = mRemoteTxnLoadFee;
mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); // increment by 1/16th
if (mLocalTxnLoadFee > lftFeeMax)
mLocalTxnLoadFee = lftFeeMax;
if (origFee == mLocalTxnLoadFee)
return false;
WriteLog (lsDEBUG, LoadManager) << "Local load fee raised from " << origFee << " to " << mLocalTxnLoadFee;
return true;
}
bool LoadFeeTrack::isLoaded()
{
boost::mutex::scoped_lock sl(mLock);
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee);
}
bool LoadFeeTrack::lowerLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
uint32 origFee = mLocalTxnLoadFee;
raiseCount = 0;
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
if (mLocalTxnLoadFee < lftNormalFee)
mLocalTxnLoadFee = lftNormalFee;
if (origFee == mLocalTxnLoadFee)
return false;
WriteLog (lsDEBUG, LoadManager) << "Local load fee lowered from " << origFee << " to " << mLocalTxnLoadFee;
return true;
}
Json::Value LoadFeeTrack::getJson(uint64 baseFee, uint32 referenceFeeUnits)
{
Json::Value j(Json::objectValue);
{
boost::mutex::scoped_lock sl(mLock);
// base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple
j["base_fee"] = Json::Value::UInt(baseFee);
// load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple
j["load_fee"] = Json::Value::UInt(
mulDiv(baseFee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
}
return j;
}
static void LogDeadLock(int dlTime)
{
WriteLog (lsWARNING, LoadManager) << "Server stalled for " << dlTime << " seconds.";
@@ -324,7 +193,9 @@ static void LogDeadLock(int dlTime)
void LoadManager::threadEntry()
{
setCallingThreadName("loadmgr");
setCallingThreadName ("loadmgr");
// VFALCO: TODO replace this with a beast Time object
boost::posix_time::ptime t = boost::posix_time::microsec_clock::universal_time();
while (1)
{
@@ -351,6 +222,8 @@ void LoadManager::threadEntry()
}
// VFALCO: TODO Eliminate the dependence on the Application object by
// constructing with the job queue and the fee tracker.
bool change;
if (theApp->getJobQueue().isOverloaded())
{
@@ -358,9 +231,15 @@ void LoadManager::threadEntry()
change = theApp->getFeeTrack().raiseLocalFee();
}
else
{
change = theApp->getFeeTrack().lowerLocalFee();
if (change)
}
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();
@@ -391,30 +270,4 @@ void LoadManager::logDisconnect(const std::string& source) const
WriteLog (lsWARNING, LoadManager) << "Disconnect for: " << source;
}
BOOST_AUTO_TEST_SUITE(LoadManager_test)
BOOST_AUTO_TEST_CASE(LoadFeeTrack_test)
{
WriteLog (lsDEBUG, LoadManager) << "Running load fee track test";
Config d; // get a default configuration object
LoadFeeTrack l;
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000);
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 10000);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 1);
// Check new default fee values give same fees as old defaults
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_DEFAULT, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_ACCOUNT_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 200 * SYSTEM_CURRENCY_PARTS);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OWNER_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 50 * SYSTEM_CURRENCY_PARTS);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_NICKNAME_CREATE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1000);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OFFER, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_CONTRACT_OPERATION, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
}
BOOST_AUTO_TEST_SUITE_END()
// vim:ts=4

View File

@@ -155,49 +155,6 @@ public:
void arm() { mArmed = true; }
};
class LoadFeeTrack
{ // structure that tracks our current fee/load schedule
protected:
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
static const int lftFeeIncFraction = 16; // increase fee by 1/16
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
static const int lftFeeMax = lftNormalFee * 1000000;
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
uint32 mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee
int raiseCount;
boost::mutex mLock;
static uint64 mulDiv(uint64 value, uint32 mul, uint64 div);
public:
LoadFeeTrack() : mLocalTxnLoadFee(lftNormalFee), mRemoteTxnLoadFee(lftNormalFee), raiseCount(0)
{ ; }
// Scale from fee units to millionths of a ripple
uint64 scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits);
// Scale using load as well as base rate
uint64 scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin);
uint32 getRemoteFee();
uint32 getLocalFee();
uint32 getLoadBase() { return lftNormalFee; }
uint32 getLoadFactor();
Json::Value getJson(uint64 baseFee, uint32 referenceFeeUnits);
void setRemoteFee(uint32);
bool raiseLocalFee();
bool lowerLocalFee();
bool isLoaded();
};
#endif
// vim:ts=4

View File

@@ -0,0 +1,21 @@
int DatabaseCon::sCount = 0;
DatabaseCon::DatabaseCon(const std::string& strName, const char *initStrings[], int initCount)
{
++sCount;
boost::filesystem::path pPath = (theConfig.RUN_STANDALONE && (theConfig.START_UP != Config::LOAD))
? "" // Use temporary files.
: (theConfig.DATA_DIR / strName); // Use regular db files.
mDatabase = new SqliteDatabase(pPath.string().c_str());
mDatabase->connect();
for(int i = 0; i < initCount; ++i)
mDatabase->executeSQL(initStrings[i], true);
}
DatabaseCon::~DatabaseCon()
{
mDatabase->disconnect();
delete mDatabase;
}

View File

@@ -0,0 +1,24 @@
#ifndef RIPPLE_DATABASECON_H
#define RIPPLE_DATABASECON_H
// VFALCO: NOTE This looks like a pointless class. Figure out
// what purpose it is really trying to serve and do it better.
class DatabaseCon
{
public:
DatabaseCon (const std::string& name, const char *initString[], int countInit);
~DatabaseCon ();
Database* getDB () { return mDatabase; }
boost::recursive_mutex& getDBLock() { return mLock; }
static int getCount() { return sCount; }
// VFALCO: TODO, change "protected" to "private" throughout the code
private:
Database* mDatabase;
// VFALCO: TODO replace these with a single atomic counter.
boost::recursive_mutex mLock;
static int sCount;
};
#endif

View File

@@ -0,0 +1,35 @@
#ifndef RIPPLE_ILOADFEETRACK_H
#define RIPPLE_ILOADFEETRACK_H
/** Tracks the current fee and load schedule.
*/
class ILoadFeeTrack
{
public:
static ILoadFeeTrack* New ();
virtual ~ILoadFeeTrack () { }
// Scale from fee units to millionths of a ripple
virtual uint64 scaleFeeBase (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits) = 0;
// Scale using load as well as base rate
virtual uint64 scaleFeeLoad (uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin) = 0;
virtual uint32 getRemoteFee () = 0;
virtual uint32 getLocalFee () = 0;
virtual uint32 getLoadBase () = 0;
virtual uint32 getLoadFactor () = 0;
virtual Json::Value getJson (uint64 baseFee, uint32 referenceFeeUnits) = 0;
virtual void setRemoteFee (uint32) = 0;
virtual bool raiseLocalFee () = 0;
virtual bool lowerLocalFee () = 0;
virtual bool isLoaded () = 0;
};
#endif
// vim:ts=4

View File

@@ -0,0 +1,205 @@
//#include <boost/test/unit_test.hpp>
//#include <boost/thread.hpp>
//#include <boost/date_time/posix_time/posix_time.hpp>
//#include "Config.h"
//#include "Application.h"
class LoadFeeTrack : public ILoadFeeTrack
{
private:
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
static const int lftFeeIncFraction = 16; // increase fee by 1/16
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
static const int lftFeeMax = lftNormalFee * 1000000;
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
uint32 mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee
int raiseCount;
boost::mutex mLock;
// VFALCO: TODO Move this function to some "math utilities" file
// compute (value)*(mul)/(div) - avoid overflow but keep precision
uint64 mulDiv (uint64 value, uint32 mul, uint64 div)
{
static uint64 boundary = (0x00000000FFFFFFFF);
if (value > boundary) // Large value, avoid overflow
return (value / div) * mul;
else // Normal value, preserve accuracy
return (value * mul) / div;
}
public:
LoadFeeTrack()
: mLocalTxnLoadFee (lftNormalFee)
, mRemoteTxnLoadFee (lftNormalFee)
, raiseCount (0)
{
}
// Scale using load as well as base rate
uint64 scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits, bool bAdmin)
{
static uint64 midrange(0x00000000FFFFFFFF);
bool big = (fee > midrange);
if (big) // big fee, divide first to avoid overflow
fee /= baseFee;
else // normal fee, multiply first for accuracy
fee *= referenceFeeUnits;
uint32 feeFactor = std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee);
// Let admins pay the normal fee until the local load exceeds four times the remote
if (bAdmin && (feeFactor > mRemoteTxnLoadFee) && (feeFactor < (4 * mRemoteTxnLoadFee)))
feeFactor = mRemoteTxnLoadFee;
{
boost::mutex::scoped_lock sl(mLock);
fee = mulDiv(fee, feeFactor, lftNormalFee);
}
if (big) // Fee was big to start, must now multiply
fee *= referenceFeeUnits;
else // Fee was small to start, mst now divide
fee /= baseFee;
return fee;
}
// Scale from fee units to millionths of a ripple
uint64 scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
{
return mulDiv(fee, referenceFeeUnits, baseFee);
}
uint32 getRemoteFee()
{
boost::mutex::scoped_lock sl(mLock);
return mRemoteTxnLoadFee;
}
uint32 getLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
return mLocalTxnLoadFee;
}
uint32 getLoadBase ()
{
return lftNormalFee;
}
uint32 getLoadFactor()
{
boost::mutex::scoped_lock sl(mLock);
return std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee);
}
bool isLoaded()
{
boost::mutex::scoped_lock sl(mLock);
return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee);
}
void setRemoteFee(uint32 f)
{
boost::mutex::scoped_lock sl(mLock);
mRemoteTxnLoadFee = f;
}
bool raiseLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
if (++raiseCount < 2)
return false;
uint32 origFee = mLocalTxnLoadFee;
if (mLocalTxnLoadFee < mRemoteTxnLoadFee) // make sure this fee takes effect
mLocalTxnLoadFee = mRemoteTxnLoadFee;
mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); // increment by 1/16th
if (mLocalTxnLoadFee > lftFeeMax)
mLocalTxnLoadFee = lftFeeMax;
if (origFee == mLocalTxnLoadFee)
return false;
WriteLog (lsDEBUG, LoadManager) << "Local load fee raised from " << origFee << " to " << mLocalTxnLoadFee;
return true;
}
bool lowerLocalFee()
{
boost::mutex::scoped_lock sl(mLock);
uint32 origFee = mLocalTxnLoadFee;
raiseCount = 0;
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
if (mLocalTxnLoadFee < lftNormalFee)
mLocalTxnLoadFee = lftNormalFee;
if (origFee == mLocalTxnLoadFee)
return false;
WriteLog (lsDEBUG, LoadManager) << "Local load fee lowered from " << origFee << " to " << mLocalTxnLoadFee;
return true;
}
Json::Value getJson(uint64 baseFee, uint32 referenceFeeUnits)
{
Json::Value j(Json::objectValue);
{
boost::mutex::scoped_lock sl(mLock);
// base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple
j["base_fee"] = Json::Value::UInt(baseFee);
// load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple
j["load_fee"] = Json::Value::UInt(
mulDiv(baseFee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
}
return j;
}
};
//------------------------------------------------------------------------------
ILoadFeeTrack* ILoadFeeTrack::New ()
{
return new LoadFeeTrack;
}
//------------------------------------------------------------------------------
BOOST_AUTO_TEST_SUITE(LoadManager_test)
BOOST_AUTO_TEST_CASE(LoadFeeTrack_test)
{
WriteLog (lsDEBUG, LoadManager) << "Running load fee track test";
Config d; // get a default configuration object
LoadFeeTrack l;
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000);
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 10000);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false), 1);
// Check new default fee values give same fees as old defaults
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_DEFAULT, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_ACCOUNT_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 200 * SYSTEM_CURRENCY_PARTS);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OWNER_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 50 * SYSTEM_CURRENCY_PARTS);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_NICKNAME_CREATE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1000);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OFFER, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_CONTRACT_OPERATION, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
}
BOOST_AUTO_TEST_SUITE_END()
// vim:ts=4