mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 14:35:52 +00:00
More work on the feature table.
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
#include "FeatureTable.h"
|
#include "FeatureTable.h"
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
SETUP_LOG();
|
||||||
|
|
||||||
FeatureTable::FeatureState* FeatureTable::getCreateFeature(const uint256& feature, bool create)
|
FeatureTable::FeatureState* FeatureTable::getCreateFeature(const uint256& feature, bool create)
|
||||||
{ // call with the mutex held
|
{ // call with the mutex held
|
||||||
featureMap_t::iterator it = mFeatureMap.find(feature);
|
featureMap_t::iterator it = mFeatureMap.find(feature);
|
||||||
@@ -59,3 +65,113 @@ bool FeatureTable::isFeatureEnabled(const uint256& feature)
|
|||||||
return s && s->mEnabled;
|
return s && s->mEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FeatureTable::featureList_t FeatureTable::getVetoedFeatures()
|
||||||
|
{
|
||||||
|
featureList_t ret;
|
||||||
|
boost::mutex::scoped_lock sl(mMutex);
|
||||||
|
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||||
|
{
|
||||||
|
if (it.second.mVetoed)
|
||||||
|
ret.insert(it.first);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureTable::featureList_t FeatureTable::getEnabledFeatures()
|
||||||
|
{
|
||||||
|
featureList_t ret;
|
||||||
|
boost::mutex::scoped_lock sl(mMutex);
|
||||||
|
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||||
|
{
|
||||||
|
if (it.second.mEnabled)
|
||||||
|
ret.insert(it.first);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FeatureTable::shouldEnable(uint32 closeTime, const FeatureState& fs)
|
||||||
|
{
|
||||||
|
if (fs.mVetoed || fs.mEnabled || (fs.mLastMajority != mLastReport))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fs.mFirstMajority == mFirstReport)
|
||||||
|
{ // had a majority when we first started the server, relaxed check
|
||||||
|
// WRITEME
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // didn't have a majority when we first started the server, normal check
|
||||||
|
// WRITEME
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureTable::featureList_t FeatureTable::getFeaturesToEnable(uint32 closeTime)
|
||||||
|
{
|
||||||
|
featureList_t ret;
|
||||||
|
boost::mutex::scoped_lock sl(mMutex);
|
||||||
|
if (mLastReport != 0)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||||
|
{
|
||||||
|
if (shouldEnable(closeTime, it.second))
|
||||||
|
ret.insert(it.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FeatureTable::reportValidations(const FeatureSet& set)
|
||||||
|
{
|
||||||
|
if (set.mTrustedValidations == 0)
|
||||||
|
return;
|
||||||
|
int threshold = (set.mTrustedValidations * mMajorityFraction) / 256;
|
||||||
|
|
||||||
|
typedef std::pair<const uint256, int> u256_int_pair;
|
||||||
|
|
||||||
|
boost::mutex::scoped_lock sl(mMutex);
|
||||||
|
|
||||||
|
if (mFirstReport == 0)
|
||||||
|
mFirstReport = set.mCloseTime;
|
||||||
|
BOOST_FOREACH(const u256_int_pair& it, set.mVotes)
|
||||||
|
{
|
||||||
|
FeatureState& state = mFeatureMap[it.first];
|
||||||
|
cLog(lsDEBUG) << "Feature " << it.first.GetHex() << " has " << it.second << " votes, needs " << threshold;
|
||||||
|
if (it.second >= threshold)
|
||||||
|
{ // we have a majority
|
||||||
|
state.mLastMajority = set.mCloseTime;
|
||||||
|
if (state.mFirstMajority == 0)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "Feature " << it.first << " attains a majority vote";
|
||||||
|
state.mFirstMajority = set.mCloseTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // we have no majority
|
||||||
|
{
|
||||||
|
if (state.mFirstMajority != 0)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "Feature " << it.first << " loses majority vote";
|
||||||
|
state.mFirstMajority = 0;
|
||||||
|
state.mLastMajority = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mLastReport = set.mCloseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value FeatureTable::getJson(int)
|
||||||
|
{
|
||||||
|
Json::Value ret(Json::objectValue);
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock sl(mMutex);
|
||||||
|
BOOST_FOREACH(const featureIt_t& it, mFeatureMap)
|
||||||
|
{
|
||||||
|
Json::Value v(Json::objectValue);
|
||||||
|
// WRITEME
|
||||||
|
ret[it.first.GetHex()] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,15 +5,19 @@
|
|||||||
#include <boost/unordered_set.hpp>
|
#include <boost/unordered_set.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include "../json/value.h"
|
||||||
|
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
struct FeatureSet
|
class FeatureSet
|
||||||
{ // the status of all features requested in a given window
|
{ // the status of all features requested in a given window
|
||||||
uint32 mLedgerSequence;
|
public:
|
||||||
uint32 mCloseTime;
|
uint32 mCloseTime;
|
||||||
int mTrustedValidations; // number of trusted validations
|
int mTrustedValidations; // number of trusted validations
|
||||||
|
|
||||||
boost::unordered_map<uint256, int> mVotes; // yes votes by feature
|
boost::unordered_map<uint256, int> mVotes; // yes votes by feature
|
||||||
|
|
||||||
|
FeatureSet(uint32 ct, int tv) : mCloseTime(ct), mTrustedValidations(tv) { ; }
|
||||||
|
void addVote(const uint256& feature) { ++mVotes[feature]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class FeatureTable
|
class FeatureTable
|
||||||
@@ -26,28 +30,31 @@ protected:
|
|||||||
bool mVetoed; // We don't want this feature enabled
|
bool mVetoed; // We don't want this feature enabled
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
||||||
int mEnableVotes; // Trusted votes to enable this feature
|
uint32 mFirstMajority; // First time we saw a majority (close time)
|
||||||
int mDisableVotes; // Trusted votes to disable this feature
|
uint32 mLastMajority; // Most recent time we saw a majority (close time)
|
||||||
uint32 mFirstMajority; // First time we saw a majority (ledger sequence)
|
|
||||||
uint32 mLastMajority; // Most recent time we saw a majority
|
|
||||||
|
|
||||||
FeatureState() : mVetoed(false), mEnabled(false), mEnableVotes(0), mDisableVotes(0),
|
FeatureState() : mVetoed(false), mEnabled(false), mFirstMajority(0), mLastMajority(0) { ; }
|
||||||
mFirstMajority(0), mLastMajority(0) { ; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::unordered_map<uint256, FeatureState> featureMap_t;
|
typedef boost::unordered_map<uint256, FeatureState> featureMap_t;
|
||||||
|
typedef std::pair<uint256, FeatureState> featureIt_t;
|
||||||
typedef boost::unordered_set<uint256> featureList_t;
|
typedef boost::unordered_set<uint256> featureList_t;
|
||||||
|
|
||||||
boost::mutex mMutex;
|
boost::mutex mMutex;
|
||||||
featureMap_t mFeatureMap;
|
featureMap_t mFeatureMap;
|
||||||
int mMajorityTime; // Seconds a feature must hold a majority
|
int mMajorityTime; // Seconds a feature must hold a majority
|
||||||
int mMajorityFraction; // 256 = 100%
|
int mMajorityFraction; // 256 = 100%
|
||||||
|
uint32 mFirstReport; // close time of first majority report
|
||||||
|
uint32 mLastReport; // close time of most recent majority report
|
||||||
|
|
||||||
FeatureState* getCreateFeature(const uint256& feature, bool create);
|
FeatureState* getCreateFeature(const uint256& feature, bool create);
|
||||||
|
bool shouldEnable (uint32 closeTime, const FeatureState& fs);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FeatureTable(uint32 majorityTime, int mMajorityFraction) : mMajorityTime(majorityTime) { ; }
|
FeatureTable(uint32 majorityTime, int majorityFraction)
|
||||||
|
: mMajorityTime(majorityTime), mMajorityFraction(majorityFraction), mFirstReport(0)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
bool vetoFeature(const uint256& feature);
|
bool vetoFeature(const uint256& feature);
|
||||||
bool unVetoFeature(const uint256& feature);
|
bool unVetoFeature(const uint256& feature);
|
||||||
@@ -59,9 +66,11 @@ public:
|
|||||||
|
|
||||||
featureList_t getVetoedFeatures();
|
featureList_t getVetoedFeatures();
|
||||||
featureList_t getEnabledFeatures();
|
featureList_t getEnabledFeatures();
|
||||||
featureList_t getFeaturesToEnable(uint32 sequence); // gets features we would vote to enable
|
featureList_t getFeaturesToEnable(uint32 closeTime); // gets features we would vote to enable
|
||||||
|
|
||||||
void reportValidations(const FeatureSet&);
|
void reportValidations(const FeatureSet&);
|
||||||
|
|
||||||
|
Json::Value getJson(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user