diff --git a/modules/ripple_basics/ripple_basics.h b/modules/ripple_basics/ripple_basics.h index b51809f24..80f88ac66 100644 --- a/modules/ripple_basics/ripple_basics.h +++ b/modules/ripple_basics/ripple_basics.h @@ -113,6 +113,10 @@ namespace boost { // UInt256 #include +// ripple_PlatformMacros.h +#include +#include + // VFALCO: TODO, remove this dependency!!! #include // for DiffieHellmanUtil #include // For HashUtilities diff --git a/modules/ripple_basics/utility/ripple_PlatformMacros.h b/modules/ripple_basics/utility/ripple_PlatformMacros.h index 60dfe3ad5..eefd5853f 100644 --- a/modules/ripple_basics/utility/ripple_PlatformMacros.h +++ b/modules/ripple_basics/utility/ripple_PlatformMacros.h @@ -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 #define UPTR_T std::unique_ptr @@ -36,8 +38,6 @@ #else -#include -#include #define UPTR_T std::auto_ptr #define MOVE_P(p) (p) #define BIND_TYPE boost::bind diff --git a/modules/ripple_ledger/ripple_ledger.cpp b/modules/ripple_ledger/ripple_ledger.cpp index 770bd7b0c..d6b3edc7b 100644 --- a/modules/ripple_ledger/ripple_ledger.cpp +++ b/modules/ripple_ledger/ripple_ledger.cpp @@ -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) diff --git a/modules/ripple_main/ripple_main.cpp b/modules/ripple_main/ripple_main.cpp index e81ca6d1c..98131f353 100644 --- a/modules/ripple_main/ripple_main.cpp +++ b/modules/ripple_main/ripple_main.cpp @@ -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" diff --git a/modules/ripple_net/ripple_net.cpp b/modules/ripple_net/ripple_net.cpp index 942ad54c0..17781cf69 100644 --- a/modules/ripple_net/ripple_net.cpp +++ b/modules/ripple_net/ripple_net.cpp @@ -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" diff --git a/newcoin.vcxproj b/newcoin.vcxproj index 6688de041..a69a49be2 100644 --- a/newcoin.vcxproj +++ b/newcoin.vcxproj @@ -974,12 +974,24 @@ true true + + true + true + true + true + true true true true + + true + true + true + true + true true @@ -1640,8 +1652,10 @@ + + diff --git a/newcoin.vcxproj.filters b/newcoin.vcxproj.filters index ac7131916..038d66780 100644 --- a/newcoin.vcxproj.filters +++ b/newcoin.vcxproj.filters @@ -612,9 +612,6 @@ 1. Modules\ripple_main\_old - - 1. Modules\ripple_main\_old - 1. Modules\ripple_main\_old @@ -792,6 +789,15 @@ 1. Modules\ripple_ledger\main + + 1. Modules\ripple_ledger\main + + + 1. Modules\ripple_ledger\main + + + 1. Modules\ripple_ledger\main + @@ -1253,9 +1259,6 @@ 1. Modules\ripple_main\_old - - 1. Modules\ripple_main\_old - 1. Modules\ripple_main\_old @@ -1472,6 +1475,15 @@ 1. Modules\ripple_ledger\main + + 1. Modules\ripple_ledger\main + + + 1. Modules\ripple_ledger\main + + + 1. Modules\ripple_ledger\main + diff --git a/src/cpp/ripple/Application.cpp b/src/cpp/ripple/Application.cpp index 8a048f931..4a0221145 100644 --- a/src/cpp/ripple/Application.cpp +++ b/src/cpp/ripple/Application.cpp @@ -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(&mNonceST), sizeof(mNonceST)); + getRand (mNonce256.begin(), mNonce256.size()); + getRand (reinterpret_cast(&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; diff --git a/src/cpp/ripple/Application.h b/src/cpp/ripple/Application.h index efab7a2a7..698dd841f 100644 --- a/src/cpp/ripple/Application.h +++ b/src/cpp/ripple/Application.h @@ -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, 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; } diff --git a/src/cpp/ripple/Config.cpp b/src/cpp/ripple/Config.cpp index c73de571d..2ffd6ee24 100644 --- a/src/cpp/ripple/Config.cpp +++ b/src/cpp/ripple/Config.cpp @@ -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" diff --git a/src/cpp/ripple/Config.h b/src/cpp/ripple/Config.h index fa9dca3da..7f9761b12 100644 --- a/src/cpp/ripple/Config.h +++ b/src/cpp/ripple/Config.h @@ -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: diff --git a/src/cpp/ripple/JobQueue.cpp b/src/cpp/ripple/JobQueue.cpp index 2d9ba8e55..7fd6cbfb6 100644 --- a/src/cpp/ripple/JobQueue.cpp +++ b/src/cpp/ripple/JobQueue.cpp @@ -5,7 +5,6 @@ #include #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) { diff --git a/src/cpp/ripple/LoadManager.cpp b/src/cpp/ripple/LoadManager.cpp index 3df5ddf63..bb2acfc40 100644 --- a/src/cpp/ripple/LoadManager.cpp +++ b/src/cpp/ripple/LoadManager.cpp @@ -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 diff --git a/src/cpp/ripple/LoadManager.h b/src/cpp/ripple/LoadManager.h index 1620b0f89..36963f96a 100644 --- a/src/cpp/ripple/LoadManager.h +++ b/src/cpp/ripple/LoadManager.h @@ -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 diff --git a/src/cpp/ripple/ripple_DatabaseCon.cpp b/src/cpp/ripple/ripple_DatabaseCon.cpp new file mode 100644 index 000000000..262c7d5a1 --- /dev/null +++ b/src/cpp/ripple/ripple_DatabaseCon.cpp @@ -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; +} diff --git a/src/cpp/ripple/ripple_DatabaseCon.h b/src/cpp/ripple/ripple_DatabaseCon.h new file mode 100644 index 000000000..5e2379f8b --- /dev/null +++ b/src/cpp/ripple/ripple_DatabaseCon.h @@ -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 + diff --git a/src/cpp/ripple/ripple_ILoadFeeTrack.h b/src/cpp/ripple/ripple_ILoadFeeTrack.h new file mode 100644 index 000000000..2e864d0da --- /dev/null +++ b/src/cpp/ripple/ripple_ILoadFeeTrack.h @@ -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 diff --git a/src/cpp/ripple/ripple_LoadFeeTrack.cpp b/src/cpp/ripple/ripple_LoadFeeTrack.cpp new file mode 100644 index 000000000..6bbf3f8a8 --- /dev/null +++ b/src/cpp/ripple/ripple_LoadFeeTrack.cpp @@ -0,0 +1,205 @@ +//#include +//#include +//#include +//#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