mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Possible fix for a bug Jed reported.
This commit is contained in:
@@ -23,7 +23,7 @@ LedgerHistory::LedgerHistory() : mLedgersByHash(CACHED_LEDGER_NUM, CACHED_LEDGER
|
||||
|
||||
void LedgerHistory::addLedger(Ledger::pointer ledger)
|
||||
{
|
||||
mLedgersByHash.canonicalize(ledger->getHash(), ledger);
|
||||
mLedgersByHash.canonicalize(ledger->getHash(), ledger, true);
|
||||
}
|
||||
|
||||
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
|
||||
@@ -31,7 +31,7 @@ void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
|
||||
assert(ledger && ledger->isAccepted());
|
||||
uint256 h(ledger->getHash());
|
||||
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||
mLedgersByHash.canonicalize(h, ledger);
|
||||
mLedgersByHash.canonicalize(h, ledger, true);
|
||||
assert(ledger);
|
||||
assert(ledger->isAccepted());
|
||||
assert(ledger->isImmutable());
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#ifndef __TAGGEDCACHE__
|
||||
#define __TAGGEDCACHE__
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@@ -21,18 +19,18 @@
|
||||
template <typename c_Key, typename c_Data> class TaggedCache
|
||||
{
|
||||
public:
|
||||
typedef c_Key key_type;
|
||||
typedef c_Data data_type;
|
||||
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;
|
||||
|
||||
typedef std::pair<time_t, data_ptr> cache_entry;
|
||||
typedef boost::weak_ptr<data_type> weak_data_ptr;
|
||||
typedef boost::shared_ptr<data_type> data_ptr;
|
||||
typedef std::pair<time_t, data_ptr> cache_entry;
|
||||
|
||||
protected:
|
||||
mutable boost::recursive_mutex mLock;
|
||||
|
||||
int mTargetSize, mTargetAge;
|
||||
|
||||
boost::unordered_map<key_type, cache_entry> mCache; // Hold strong reference to recent objects
|
||||
time_t mLastSweep;
|
||||
|
||||
@@ -40,6 +38,7 @@ protected:
|
||||
|
||||
public:
|
||||
TaggedCache(int size, int age) : mTargetSize(size), mTargetAge(age), mLastSweep(time(NULL)) { ; }
|
||||
|
||||
int getTargetSize() const;
|
||||
int getTargetAge() const;
|
||||
|
||||
@@ -52,7 +51,7 @@ public:
|
||||
|
||||
bool touch(const key_type& key);
|
||||
bool del(const key_type& key);
|
||||
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data);
|
||||
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);
|
||||
@@ -82,10 +81,12 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
if (mCache.size() < mTargetSize) return;
|
||||
if (mCache.size() < mTargetSize)
|
||||
return;
|
||||
|
||||
time_t now = time(NULL);
|
||||
if ((mLastSweep + 10) < now) return;
|
||||
if ((mLastSweep + 10) < now)
|
||||
return;
|
||||
|
||||
mLastSweep = now;
|
||||
time_t target = now - mTargetAge;
|
||||
@@ -99,7 +100,8 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator tmp = cit++;
|
||||
mCache.erase(tmp);
|
||||
}
|
||||
else ++cit;
|
||||
else
|
||||
++cit;
|
||||
}
|
||||
|
||||
// Pass 2, remove dead objects from map
|
||||
@@ -111,7 +113,8 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator tmp = mit++;
|
||||
mMap.erase(mit);
|
||||
}
|
||||
else ++mit;
|
||||
else
|
||||
++mit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +124,8 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch
|
||||
|
||||
// Is the object in the map?
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) return false;
|
||||
if (mit == mMap.end())
|
||||
return false;
|
||||
if (mit->second.expired())
|
||||
{ // in map, but expired
|
||||
mMap.erase(mit);
|
||||
@@ -146,13 +150,14 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(c
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit == mCache.end()) return false;
|
||||
if (cit == mCache.end())
|
||||
return false;
|
||||
mCache.erase(cit);
|
||||
return true;
|
||||
}
|
||||
|
||||
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 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);
|
||||
@@ -172,13 +177,21 @@ bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||
return false;
|
||||
}
|
||||
|
||||
data = cachedData;
|
||||
|
||||
// in map and cache, canonicalize
|
||||
if (replace)
|
||||
mit->second = data;
|
||||
else
|
||||
data = cachedData;
|
||||
|
||||
// Valid in map, is it in cache?
|
||||
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
|
||||
if (cit != mCache.end())
|
||||
{
|
||||
cit->second.first = time(NULL); // Yes, refesh
|
||||
if (replace)
|
||||
cit->second.second = data;
|
||||
}
|
||||
else // no, add to cache
|
||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||
|
||||
@@ -192,7 +205,8 @@ boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||
|
||||
// Is it in the map?
|
||||
typename boost::unordered_map<key_type, weak_data_ptr>::iterator mit = mMap.find(key);
|
||||
if (mit == mMap.end()) return data_ptr(); // No, we're done
|
||||
if (mit == mMap.end())
|
||||
return data_ptr(); // No, we're done
|
||||
|
||||
boost::shared_ptr<c_Data> cachedData = mit->second.lock();
|
||||
if (!cachedData)
|
||||
|
||||
Reference in New Issue
Block a user