diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index 5b80ca797..6ad660c23 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -2061,14 +2061,12 @@ ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) - + True True ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) ..\..\src\soci\src\core;..\..\src\sqlite;%(AdditionalIncludeDirectories) - - True True diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 4036937d5..f9a40cac4 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -2799,12 +2799,9 @@ ripple\core\impl - + ripple\core\impl - - ripple\core\impl - ripple\core\impl diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 556f8355d..7d59daac2 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -414,7 +414,7 @@ public: (weeks(2), MAJORITY_FRACTION, m_logs.journal("AmendmentTable"))) - , mFeeTrack (LoadFeeTrack::New (m_logs.journal("LoadManager"))) + , mFeeTrack (std::make_unique(m_logs.journal("LoadManager"))) , mHashRouter (IHashRouter::New (IHashRouter::getDefaultHoldTime ())) diff --git a/src/ripple/core/LoadFeeTrack.h b/src/ripple/core/LoadFeeTrack.h index b24a8dcc8..d1391e999 100644 --- a/src/ripple/core/LoadFeeTrack.h +++ b/src/ripple/core/LoadFeeTrack.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace ripple { @@ -39,37 +40,99 @@ namespace ripple { class LoadFeeTrack { public: - /** Create a new tracker. - */ - static LoadFeeTrack* New (beast::Journal journal); + explicit LoadFeeTrack (beast::Journal journal = beast::Journal()) + : m_journal (journal) + , mLocalTxnLoadFee (lftNormalFee) + , mRemoteTxnLoadFee (lftNormalFee) + , mClusterTxnLoadFee (lftNormalFee) + , raiseCount (0) + { + } virtual ~LoadFeeTrack () { } // Scale from fee units to millionths of a ripple - virtual std::uint64_t scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee, - std::uint32_t referenceFeeUnits) = 0; + std::uint64_t scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee, + std::uint32_t referenceFeeUnits) const; // Scale using load as well as base rate - virtual std::uint64_t scaleFeeLoad (std::uint64_t fee, std::uint64_t baseFee, - std::uint32_t referenceFeeUnits, - bool bAdmin) = 0; + std::uint64_t scaleFeeLoad (std::uint64_t fee, std::uint64_t baseFee, + std::uint32_t referenceFeeUnits, bool bAdmin) const; - virtual void setRemoteFee (std::uint32_t) = 0; + void setRemoteFee (std::uint32_t f) + { + ScopedLockType sl (mLock); + mRemoteTxnLoadFee = f; + } - virtual std::uint32_t getRemoteFee () = 0; - virtual std::uint32_t getLocalFee () = 0; - virtual std::uint32_t getClusterFee () = 0; + std::uint32_t getRemoteFee () const + { + ScopedLockType sl (mLock); + return mRemoteTxnLoadFee; + } - virtual std::uint32_t getLoadBase () = 0; - virtual std::uint32_t getLoadFactor () = 0; + std::uint32_t getLocalFee () const + { + ScopedLockType sl (mLock); + return mLocalTxnLoadFee; + } - virtual Json::Value getJson (std::uint64_t baseFee, std::uint32_t referenceFeeUnits) = 0; + std::uint32_t getClusterFee () const + { + ScopedLockType sl (mLock); + return mClusterTxnLoadFee; + } - virtual void setClusterFee (std::uint32_t) = 0; - virtual bool raiseLocalFee () = 0; - virtual bool lowerLocalFee () = 0; - virtual bool isLoadedLocal () = 0; - virtual bool isLoadedCluster () = 0; + std::uint32_t getLoadBase () const + { + return lftNormalFee; + } + + std::uint32_t getLoadFactor () const + { + ScopedLockType sl (mLock); + return std::max({ mClusterTxnLoadFee, mLocalTxnLoadFee, mRemoteTxnLoadFee }); + } + + + Json::Value getJson (std::uint64_t baseFee, std::uint32_t referenceFeeUnits) const; + + void setClusterFee (std::uint32_t fee) + { + ScopedLockType sl (mLock); + mClusterTxnLoadFee = fee; + } + + bool raiseLocalFee (); + bool lowerLocalFee (); + + bool isLoadedLocal () const + { + ScopedLockType sl (mLock); + return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee); + } + + bool isLoadedCluster () const + { + ScopedLockType sl (mLock); + return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee) || (mClusterTxnLoadFee != lftNormalFee); + } + +private: + static const int lftNormalFee = 256; // 256 is the minimum/normal load factor + static const int lftFeeIncFraction = 4; // increase fee by 1/4 + static const int lftFeeDecFraction = 4; // decrease fee by 1/4 + static const int lftFeeMax = lftNormalFee * 1000000; + + beast::Journal m_journal; + using LockType = std::mutex; + using ScopedLockType = std::lock_guard ; + LockType mutable mLock; + + std::uint32_t mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee + std::uint32_t mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee + std::uint32_t mClusterTxnLoadFee; // Scale factor, lftNormalFee = normal fee + int raiseCount; }; } // ripple diff --git a/src/ripple/core/impl/LoadFeeTrack.cpp b/src/ripple/core/impl/LoadFeeTrack.cpp new file mode 100644 index 000000000..44f997752 --- /dev/null +++ b/src/ripple/core/impl/LoadFeeTrack.cpp @@ -0,0 +1,154 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include +#include + +namespace ripple { + +// TODO REMOVE! +std::uint64_t mulDiv (std::uint64_t value, + std::uint32_t mul, std::uint64_t div) +{ + static std::uint64_t boundary = (0x00000000FFFFFFFF); + + if (value > boundary) // Large value, avoid overflow + return (value / div) * mul; + else // Normal value, preserve accuracy + return (value * mul) / div; +} + +// Scale from fee units to millionths of a ripple +std::uint64_t +LoadFeeTrack::scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee, + std::uint32_t referenceFeeUnits) const +{ + return mulDiv (fee, baseFee, referenceFeeUnits); +} + +// Scale using load as well as base rate +std::uint64_t +LoadFeeTrack::scaleFeeLoad (std::uint64_t fee, std::uint64_t baseFee, + std::uint32_t referenceFeeUnits, bool bAdmin) const +{ + static std::uint64_t midrange (0x00000000FFFFFFFF); + + bool big = (fee > midrange); + + if (big) // big fee, divide first to avoid overflow + fee /= referenceFeeUnits; + else // normal fee, multiply first for accuracy + fee *= baseFee; + + std::uint32_t feeFactor = std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee); + + // Let admins pay the normal fee until the local load exceeds four times the remote + std::uint32_t uRemFee = std::max(mRemoteTxnLoadFee, mClusterTxnLoadFee); + if (bAdmin && (feeFactor > uRemFee) && (feeFactor < (4 * uRemFee))) + feeFactor = uRemFee; + + { + ScopedLockType sl (mLock); + fee = mulDiv (fee, feeFactor, lftNormalFee); + } + + if (big) // Fee was big to start, must now multiply + fee *= baseFee; + else // Fee was small to start, mst now divide + fee /= referenceFeeUnits; + + return fee; +} + +Json::Value +LoadFeeTrack::getJson (std::uint64_t baseFee, + std::uint32_t referenceFeeUnits) const +{ + Json::Value j (Json::objectValue); + + { + ScopedLockType sl (mLock); + + // base_fee = The cost to send a "reference" transaction under + // no load, in millionths of a Ripple + j[jss::base_fee] = Json::Value::UInt (baseFee); + + // load_fee = The cost to send a "reference" transaction now, + // in millionths of a Ripple + j[jss::load_fee] = Json::Value::UInt ( + mulDiv (baseFee, std::max (mLocalTxnLoadFee, + mRemoteTxnLoadFee), lftNormalFee)); + } + + return j; +} + +bool +LoadFeeTrack::raiseLocalFee () +{ + ScopedLockType sl (mLock); + + if (++raiseCount < 2) + return false; + + std::uint32_t origFee = mLocalTxnLoadFee; + + // make sure this fee takes effect + if (mLocalTxnLoadFee < mRemoteTxnLoadFee) + mLocalTxnLoadFee = mRemoteTxnLoadFee; + + // Increase slowly + mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); + + if (mLocalTxnLoadFee > lftFeeMax) + mLocalTxnLoadFee = lftFeeMax; + + if (origFee == mLocalTxnLoadFee) + return false; + + m_journal.debug << "Local load fee raised from " << + origFee << " to " << mLocalTxnLoadFee; + return true; +} + +bool +LoadFeeTrack::lowerLocalFee () +{ + ScopedLockType sl (mLock); + std::uint32_t origFee = mLocalTxnLoadFee; + raiseCount = 0; + + // Reduce slowly + mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); + + if (mLocalTxnLoadFee < lftNormalFee) + mLocalTxnLoadFee = lftNormalFee; + + if (origFee == mLocalTxnLoadFee) + return false; + + m_journal.debug << "Local load fee lowered from " << + origFee << " to " << mLocalTxnLoadFee; + return true; +} + +} // ripple diff --git a/src/ripple/core/impl/LoadFeeTrackImp.cpp b/src/ripple/core/impl/LoadFeeTrackImp.cpp deleted file mode 100644 index 10849d26a..000000000 --- a/src/ripple/core/impl/LoadFeeTrackImp.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include - -namespace ripple { - -LoadFeeTrack* LoadFeeTrack::New (beast::Journal journal) -{ - return new LoadFeeTrackImp (journal); -} - -} // ripple diff --git a/src/ripple/core/impl/LoadFeeTrackImp.h b/src/ripple/core/impl/LoadFeeTrackImp.h deleted file mode 100644 index e73730e3f..000000000 --- a/src/ripple/core/impl/LoadFeeTrackImp.h +++ /dev/null @@ -1,238 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of rippled: https://github.com/ripple/rippled - Copyright (c) 2012, 2013 Ripple Labs Inc. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef RIPPLE_CORE_LOADFEETRACKIMP_H_INCLUDED -#define RIPPLE_CORE_LOADFEETRACKIMP_H_INCLUDED - -#include -#include -#include - -namespace ripple { - -class LoadFeeTrackImp : public LoadFeeTrack -{ -public: - explicit LoadFeeTrackImp (beast::Journal journal = beast::Journal()) - : m_journal (journal) - , mLocalTxnLoadFee (lftNormalFee) - , mRemoteTxnLoadFee (lftNormalFee) - , mClusterTxnLoadFee (lftNormalFee) - , raiseCount (0) - { - } - - // Scale using load as well as base rate - std::uint64_t scaleFeeLoad (std::uint64_t fee, std::uint64_t baseFee, std::uint32_t referenceFeeUnits, bool bAdmin) - { - static std::uint64_t midrange (0x00000000FFFFFFFF); - - bool big = (fee > midrange); - - if (big) // big fee, divide first to avoid overflow - fee /= referenceFeeUnits; - else // normal fee, multiply first for accuracy - fee *= baseFee; - - std::uint32_t feeFactor = std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee); - - // Let admins pay the normal fee until the local load exceeds four times the remote - std::uint32_t uRemFee = std::max(mRemoteTxnLoadFee, mClusterTxnLoadFee); - if (bAdmin && (feeFactor > uRemFee) && (feeFactor < (4 * uRemFee))) - feeFactor = uRemFee; - - { - ScopedLockType sl (mLock); - fee = mulDiv (fee, feeFactor, lftNormalFee); - } - - if (big) // Fee was big to start, must now multiply - fee *= baseFee; - else // Fee was small to start, mst now divide - fee /= referenceFeeUnits; - - return fee; - } - - // Scale from fee units to millionths of a ripple - std::uint64_t scaleFeeBase (std::uint64_t fee, std::uint64_t baseFee, std::uint32_t referenceFeeUnits) - { - return mulDiv (fee, baseFee, referenceFeeUnits); - } - - std::uint32_t getRemoteFee () - { - ScopedLockType sl (mLock); - return mRemoteTxnLoadFee; - } - - std::uint32_t getLocalFee () - { - ScopedLockType sl (mLock); - return mLocalTxnLoadFee; - } - - std::uint32_t getLoadBase () - { - return lftNormalFee; - } - - std::uint32_t getLoadFactor () - { - ScopedLockType sl (mLock); - return std::max(mClusterTxnLoadFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee)); - } - - void setClusterFee (std::uint32_t fee) - { - ScopedLockType sl (mLock); - mClusterTxnLoadFee = fee; - } - - std::uint32_t getClusterFee () - { - ScopedLockType sl (mLock); - return mClusterTxnLoadFee; - } - - bool isLoadedLocal () - { - // VFALCO TODO This could be replaced with a SharedData and - // using a read/write lock instead of a critical section. - // - // NOTE This applies to all the locking in this class. - // - // - ScopedLockType sl (mLock); - return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee); - } - - bool isLoadedCluster () - { - // VFALCO TODO This could be replaced with a SharedData and - // using a read/write lock instead of a critical section. - // - // NOTE This applies to all the locking in this class. - // - // - ScopedLockType sl (mLock); - return (raiseCount != 0) || (mLocalTxnLoadFee != lftNormalFee) || (mClusterTxnLoadFee != lftNormalFee); - } - - void setRemoteFee (std::uint32_t f) - { - ScopedLockType sl (mLock); - mRemoteTxnLoadFee = f; - } - - bool raiseLocalFee () - { - ScopedLockType sl (mLock); - - if (++raiseCount < 2) - return false; - - std::uint32_t origFee = mLocalTxnLoadFee; - - if (mLocalTxnLoadFee < mRemoteTxnLoadFee) // make sure this fee takes effect - mLocalTxnLoadFee = mRemoteTxnLoadFee; - - mLocalTxnLoadFee += (mLocalTxnLoadFee / lftFeeIncFraction); // increment by 1/16th - - if (mLocalTxnLoadFee > lftFeeMax) - mLocalTxnLoadFee = lftFeeMax; - - if (origFee == mLocalTxnLoadFee) - return false; - - m_journal.debug << "Local load fee raised from " << origFee << " to " << mLocalTxnLoadFee; - return true; - } - - bool lowerLocalFee () - { - ScopedLockType sl (mLock); - std::uint32_t origFee = mLocalTxnLoadFee; - raiseCount = 0; - - mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4 - - if (mLocalTxnLoadFee < lftNormalFee) - mLocalTxnLoadFee = lftNormalFee; - - if (origFee == mLocalTxnLoadFee) - return false; - - m_journal.debug << "Local load fee lowered from " << origFee << " to " << mLocalTxnLoadFee; - return true; - } - - Json::Value getJson (std::uint64_t baseFee, std::uint32_t referenceFeeUnits) - { - Json::Value j (Json::objectValue); - - { - ScopedLockType sl (mLock); - - // base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple - j[jss::base_fee] = Json::Value::UInt (baseFee); - - // load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple - j[jss::load_fee] = Json::Value::UInt ( - mulDiv (baseFee, std::max (mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee)); - } - - return j; - } - -private: - // VFALCO TODO Move this function to some "math utilities" file - // compute (value)*(mul)/(div) - avoid overflow but keep precision - std::uint64_t mulDiv (std::uint64_t value, std::uint32_t mul, std::uint64_t div) - { - // VFALCO TODO replace with beast::literal64bitUnsigned () - // - static std::uint64_t boundary = (0x00000000FFFFFFFF); - - if (value > boundary) // Large value, avoid overflow - return (value / div) * mul; - else // Normal value, preserve accuracy - return (value * mul) / div; - } - -private: - static const int lftNormalFee = 256; // 256 is the minimum/normal load factor - static const int lftFeeIncFraction = 4; // increase fee by 1/4 - static const int lftFeeDecFraction = 4; // decrease fee by 1/4 - static const int lftFeeMax = lftNormalFee * 1000000; - - beast::Journal m_journal; - using LockType = std::mutex; - using ScopedLockType = std::lock_guard ; - LockType mLock; - - std::uint32_t mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee - std::uint32_t mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee - std::uint32_t mClusterTxnLoadFee; // Scale factor, lftNormalFee = normal fee - int raiseCount; -}; - -} // ripple - -#endif diff --git a/src/ripple/core/tests/Config.test.cpp b/src/ripple/core/tests/Config.test.cpp index b3dc0b2ce..cc7cbf907 100644 --- a/src/ripple/core/tests/Config.test.cpp +++ b/src/ripple/core/tests/Config.test.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include #include #include #include diff --git a/src/ripple/core/tests/LoadFeeTrack.test.cpp b/src/ripple/core/tests/LoadFeeTrack.test.cpp index 2d49bcccb..9be3c7bad 100644 --- a/src/ripple/core/tests/LoadFeeTrack.test.cpp +++ b/src/ripple/core/tests/LoadFeeTrack.test.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include #include #include @@ -30,7 +30,7 @@ public: void run () { Config d; // get a default configuration object - LoadFeeTrackImp l; + LoadFeeTrack l; expect (l.scaleFeeBase (10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE) == 10000); expect (l.scaleFeeLoad (10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE, false) == 10000); diff --git a/src/ripple/unity/core.cpp b/src/ripple/unity/core.cpp index fce87d135..3df0ebdbf 100644 --- a/src/ripple/unity/core.cpp +++ b/src/ripple/unity/core.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include