mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-01 08:25:51 +00:00
Move TaggedCache to ripple_basics and remove dependency on upTime
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
TaggedCache<uint256, AcceptedLedger> AcceptedLedger::ALCache("AcceptedLedger", 4, 60);
|
||||
TaggedCache<uint256, AcceptedLedger, UptimeTimerAdapter> AcceptedLedger::ALCache("AcceptedLedger", 4, 60);
|
||||
|
||||
ALTransaction::ALTransaction(uint32 seq, SerializerIterator& sit)
|
||||
{
|
||||
|
||||
@@ -72,7 +72,7 @@ protected:
|
||||
|
||||
void insert(ALTransaction::ref);
|
||||
|
||||
static TaggedCache<uint256, AcceptedLedger> ALCache;
|
||||
static TaggedCache<uint256, AcceptedLedger, UptimeTimerAdapter> ALCache;
|
||||
AcceptedLedger(Ledger::ref ledger);
|
||||
|
||||
public:
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "BitcoinUtil.h"
|
||||
#include "key.h"
|
||||
#include "utils.h"
|
||||
#include "TaggedCache.h"
|
||||
|
||||
#include "../database/SqliteDatabase.h"
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Peer.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include "WSDoor.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "ValidationCollection.h"
|
||||
#include "Suppression.h"
|
||||
#include "SNTPClient.h"
|
||||
@@ -33,8 +32,8 @@
|
||||
|
||||
class RPCDoor;
|
||||
class PeerDoor;
|
||||
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
|
||||
typedef TaggedCache< uint256, SLE > SLECache;
|
||||
typedef TaggedCache< uint256, std::vector<unsigned char>, UptimeTimerAdapter> NodeCache;
|
||||
typedef TaggedCache< uint256, SLE, UptimeTimerAdapter> SLECache;
|
||||
|
||||
class DatabaseCon
|
||||
{
|
||||
|
||||
@@ -8,13 +8,12 @@
|
||||
|
||||
#include "uint256.h"
|
||||
#include "ScopedLock.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "InstanceCounter.h"
|
||||
|
||||
|
||||
// VFALCO: TODO, Move this to someplace sensible!!
|
||||
// Adapter to furnish uptime information to KeyCache via UptimeTimer singleton
|
||||
struct KeyCacheUptimeTimer
|
||||
struct UptimeTimerAdapter
|
||||
{
|
||||
inline static int getElapsedSeconds ()
|
||||
{
|
||||
@@ -62,8 +61,8 @@ public:
|
||||
class HashedObjectStore
|
||||
{
|
||||
protected:
|
||||
TaggedCache<uint256, HashedObject> mCache;
|
||||
KeyCache <uint256, KeyCacheUptimeTimer> mNegativeCache;
|
||||
TaggedCache<uint256, HashedObject, UptimeTimerAdapter> mCache;
|
||||
KeyCache <uint256, UptimeTimerAdapter> mNegativeCache;
|
||||
|
||||
boost::mutex mWriteMutex;
|
||||
boost::condition_variable mWriteCondition;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "Ledger.h"
|
||||
#include "Peer.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "InstanceCounter.h"
|
||||
#include "ripple.pb.h"
|
||||
|
||||
@@ -146,7 +145,7 @@ class LedgerAcquireMaster
|
||||
protected:
|
||||
boost::mutex mLock;
|
||||
std::map<uint256, LedgerAcquire::pointer> mLedgers;
|
||||
KeyCache<uint256, KeyCacheUptimeTimer> mRecentFailures;
|
||||
KeyCache<uint256, UptimeTimerAdapter> mRecentFailures;
|
||||
|
||||
public:
|
||||
LedgerAcquireMaster() : mRecentFailures("LedgerAcquireRecentFailures", 0, LEDGER_REACQUIRE_INTERVAL) { ; }
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#ifndef __LEDGERHISTORY__
|
||||
#define __LEDGERHISTORY__
|
||||
|
||||
#include "TaggedCache.h"
|
||||
#include "Ledger.h"
|
||||
|
||||
class LedgerHistory
|
||||
{
|
||||
TaggedCache<uint256, Ledger> mLedgersByHash;
|
||||
TaggedCache<uint256, Ledger, UptimeTimerAdapter> mLedgersByHash;
|
||||
std::map<uint32, uint256> mLedgersByIndex; // accepted ledgers
|
||||
|
||||
public:
|
||||
|
||||
@@ -148,7 +148,7 @@ protected:
|
||||
subMapType mSubTransactions; // all accepted transactions
|
||||
subMapType mSubRTTransactions; // all proposed and accepted transactions
|
||||
|
||||
TaggedCache< uint256, std::vector<unsigned char> > mFetchPack;
|
||||
TaggedCache< uint256, std::vector<unsigned char>, UptimeTimerAdapter > mFetchPack;
|
||||
uint32 mLastFetchPack;
|
||||
uint32 mFetchSeq;
|
||||
|
||||
|
||||
@@ -356,7 +356,7 @@ protected:
|
||||
|
||||
SHAMapType mType;
|
||||
|
||||
static KeyCache <uint256, KeyCacheUptimeTimer> fullBelowCache;
|
||||
static KeyCache <uint256, UptimeTimerAdapter> fullBelowCache;
|
||||
|
||||
void dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256& target, uint256 prevHash);
|
||||
std::stack<SHAMapTreeNode::pointer> getStack(const uint256& id, bool include_nonmatching_leaf, bool partialOk);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
static const uint256 uZero;
|
||||
|
||||
KeyCache <uint256, KeyCacheUptimeTimer> SHAMap::fullBelowCache("fullBelowCache", 65536, 240);
|
||||
KeyCache <uint256, UptimeTimerAdapter> SHAMap::fullBelowCache("fullBelowCache", 65536, 240);
|
||||
|
||||
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
|
||||
SHAMapSyncFilter* filter)
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
#ifndef __TAGGEDCACHE__
|
||||
#define __TAGGEDCACHE__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
extern int upTime();
|
||||
|
||||
// This class implements a cache and a map. The cache keeps objects alive
|
||||
// in the map. The map allows multiple code paths that reference objects
|
||||
// with the same tag to get the same actual object.
|
||||
|
||||
// So long as data is in the cache, it will stay in memory.
|
||||
// If it stays in memory even after it is ejected from the cache,
|
||||
// the map will track it.
|
||||
|
||||
// CAUTION: Callers must not modify data objects that are stored in the cache
|
||||
// unless they hold their own lock over all cache operations.
|
||||
|
||||
struct TaggedCacheLog { };
|
||||
|
||||
SETUP_LOG (TaggedCacheLog)
|
||||
|
||||
template <typename c_Key, typename c_Data> class TaggedCache
|
||||
{
|
||||
public:
|
||||
typedef c_Key key_type;
|
||||
typedef c_Data data_type;
|
||||
typedef boost::weak_ptr<data_type> weak_data_ptr;
|
||||
typedef boost::shared_ptr<data_type> data_ptr;
|
||||
|
||||
protected:
|
||||
|
||||
class cache_entry
|
||||
{
|
||||
public:
|
||||
int last_use;
|
||||
data_ptr ptr;
|
||||
weak_data_ptr weak_ptr;
|
||||
|
||||
cache_entry(int l, const data_ptr& d) : last_use(l), ptr(d), weak_ptr(d) { ; }
|
||||
bool isWeak() { return !ptr; }
|
||||
bool isCached() { return !!ptr; }
|
||||
bool isExpired() { return weak_ptr.expired(); }
|
||||
data_ptr lock() { return weak_ptr.lock(); }
|
||||
void touch() { last_use = upTime(); }
|
||||
};
|
||||
|
||||
typedef std::pair<key_type, cache_entry> cache_pair;
|
||||
typedef boost::unordered_map<key_type, cache_entry> cache_type;
|
||||
typedef typename cache_type::iterator cache_iterator;
|
||||
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
std::string mName; // Used for logging
|
||||
int mTargetSize; // Desired number of cache entries (0 = ignore)
|
||||
int mTargetAge; // Desired maximum cache age
|
||||
int mCacheCount; // Number of items cached
|
||||
|
||||
cache_type mCache; // Hold strong reference to recent objects
|
||||
int mLastSweep;
|
||||
|
||||
uint64 mHits, mMisses;
|
||||
|
||||
public:
|
||||
TaggedCache(const char *name, int size, int age)
|
||||
: mName(name), mTargetSize(size), mTargetAge(age), mCacheCount(0), mLastSweep(upTime()),
|
||||
mHits(0), mMisses(0)
|
||||
{ ; }
|
||||
|
||||
int getTargetSize() const;
|
||||
int getTargetAge() const;
|
||||
|
||||
int getCacheSize();
|
||||
int getTrackSize();
|
||||
float getHitRate();
|
||||
void clearStats();
|
||||
|
||||
void setTargetSize(int size);
|
||||
void setTargetAge(int age);
|
||||
void sweep();
|
||||
void clear();
|
||||
|
||||
bool touch(const key_type& key);
|
||||
bool del(const key_type& key, bool valid);
|
||||
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data, bool replace = false);
|
||||
bool store(const key_type& key, const c_Data& data);
|
||||
boost::shared_ptr<c_Data> fetch(const key_type& key);
|
||||
bool retrieve(const key_type& key, c_Data& data);
|
||||
|
||||
boost::recursive_mutex& peekMutex() { return mLock; }
|
||||
};
|
||||
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTargetSize() const
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mTargetSize;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::setTargetSize(int s)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mTargetSize = s;
|
||||
if (s > 0)
|
||||
mCache.rehash(static_cast<std::size_t>((s + (s >> 2)) / mCache.max_load_factor() + 1));
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target size set to " << s;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTargetAge() const
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mTargetAge;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::setTargetAge(int s)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mTargetAge = s;
|
||||
WriteLog (lsDEBUG, TaggedCacheLog) << mName << " target age set to " << s;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getCacheSize()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCacheCount;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTrackSize()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return mCache.size();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> float TaggedCache<c_Key, c_Data>::getHitRate()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
return (static_cast<float>(mHits) * 100) / (1.0f + mHits + mMisses);
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::clearStats()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mHits = 0;
|
||||
mMisses = 0;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::clear()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
mCache.clear();
|
||||
mCacheCount = 0;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep()
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
int mLastSweep = upTime();
|
||||
int target = mLastSweep - mTargetAge;
|
||||
int cacheRemovals = 0, mapRemovals = 0, cc = 0;
|
||||
|
||||
if ((mTargetSize != 0) && (static_cast<int>(mCache.size()) > mTargetSize))
|
||||
{
|
||||
target = mLastSweep - (mTargetAge * mTargetSize / mCache.size());
|
||||
if (target > (mLastSweep - 2))
|
||||
target = mLastSweep - 2;
|
||||
WriteLog (lsINFO, TaggedCacheLog) << mName << " is growing fast " <<
|
||||
mCache.size() << " of " << mTargetSize <<
|
||||
" aging at " << (mLastSweep - target) << " of " << mTargetAge;
|
||||
}
|
||||
|
||||
cache_iterator cit = mCache.begin();
|
||||
while (cit != mCache.end())
|
||||
{
|
||||
if (cit->second.isWeak())
|
||||
{ // weak
|
||||
if (cit->second.isExpired())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase(cit);
|
||||
}
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
else if (cit->second.last_use < target)
|
||||
{ // strong, expired
|
||||
--mCacheCount;
|
||||
++cacheRemovals;
|
||||
cit->second.ptr.reset();
|
||||
if (cit->second.isExpired())
|
||||
{
|
||||
++mapRemovals;
|
||||
cit = mCache.erase(cit);
|
||||
}
|
||||
else // remains weakly cached
|
||||
++cit;
|
||||
}
|
||||
else
|
||||
{ // strong, not expired
|
||||
++cc;
|
||||
++cit;
|
||||
}
|
||||
}
|
||||
|
||||
assert(cc == mCacheCount);
|
||||
if (ShouldLog (lsTRACE, TaggedCacheLog) && (mapRemovals || cacheRemovals))
|
||||
WriteLog (lsTRACE, TaggedCacheLog) << mName << ": cache = " << mCache.size() << "-" << cacheRemovals <<
|
||||
", map-=" << mapRemovals;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch(const key_type& key)
|
||||
{ // If present, make current in cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end()) // Don't have the object
|
||||
return false;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{ // We just put the object back in cache
|
||||
++mCacheCount;
|
||||
entry.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Object fell out
|
||||
mCache.erase(cit);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(const key_type& key, bool valid)
|
||||
{ // Remove from cache, if !valid, remove from map too. Returns true if removed from cache
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
return false;
|
||||
cache_entry& entry = cit->second;
|
||||
|
||||
bool ret = false;
|
||||
if (entry.isCached())
|
||||
{
|
||||
--mCacheCount;
|
||||
entry.ptr.reset();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (!valid || entry.isExpired())
|
||||
mCache.erase(cit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data, bool replace)
|
||||
{ // Return canonical value, store if needed, refresh in cache
|
||||
// Return values: true=we had the data already
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
{
|
||||
mCache.insert(cache_pair(key, cache_entry(upTime(), data)));
|
||||
++mCacheCount;
|
||||
return false;
|
||||
}
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
data = entry.ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
data_ptr cachedData = entry.lock();
|
||||
if (cachedData)
|
||||
{
|
||||
if (replace)
|
||||
{
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.ptr = cachedData;
|
||||
data = cachedData;
|
||||
}
|
||||
++mCacheCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
entry.ptr = data;
|
||||
entry.weak_ptr = data;
|
||||
++mCacheCount;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
{ // fetch us a shared pointer to the stored data object
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
cache_iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end())
|
||||
{
|
||||
++mMisses;
|
||||
return data_ptr();
|
||||
}
|
||||
cache_entry& entry = cit->second;
|
||||
entry.touch();
|
||||
|
||||
if (entry.isCached())
|
||||
{
|
||||
++mHits;
|
||||
return entry.ptr;
|
||||
}
|
||||
|
||||
entry.ptr = entry.lock();
|
||||
if (entry.isCached())
|
||||
{ // independent of cache size, so not counted as a hit
|
||||
++mCacheCount;
|
||||
return entry.ptr;
|
||||
}
|
||||
mCache.erase(cit);
|
||||
++mMisses;
|
||||
return data_ptr();
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
bool TaggedCache<c_Key, c_Data>::store(const key_type& key, const c_Data& data)
|
||||
{
|
||||
data_ptr d = boost::make_shared<c_Data>(boost::cref(data));
|
||||
return canonicalize(key, d);
|
||||
}
|
||||
|
||||
template<typename c_Key, typename c_Data>
|
||||
bool TaggedCache<c_Key, c_Data>::retrieve(const key_type& key, c_Data& data)
|
||||
{ // retrieve the value of the stored data
|
||||
data_ptr entry = fetch(key);
|
||||
if (!entry)
|
||||
return false;
|
||||
data = *entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -2,14 +2,13 @@
|
||||
#define __TRANSACTIONMASTER__
|
||||
|
||||
#include "Transaction.h"
|
||||
#include "TaggedCache.h"
|
||||
|
||||
// Tracks all transactions in memory
|
||||
|
||||
class TransactionMaster
|
||||
{
|
||||
protected:
|
||||
TaggedCache<uint256, Transaction> mCache;
|
||||
TaggedCache<uint256, Transaction, UptimeTimerAdapter> mCache;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "uint256.h"
|
||||
#include "SerializedValidation.h"
|
||||
#include "TaggedCache.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
typedef boost::unordered_map<uint160, SerializedValidation::pointer> ValidationSet;
|
||||
@@ -21,7 +20,7 @@ class ValidationCollection
|
||||
protected:
|
||||
|
||||
boost::mutex mValidationLock;
|
||||
TaggedCache<uint256, ValidationSet> mValidations;
|
||||
TaggedCache<uint256, ValidationSet, UptimeTimerAdapter> mValidations;
|
||||
boost::unordered_map<uint160, SerializedValidation::pointer> mCurrentValidations;
|
||||
std::vector<SerializedValidation::pointer> mStaleValidations;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user