diff --git a/src/LedgerHistory.cpp b/src/LedgerHistory.cpp index 79ff9ac615..0445b268d5 100644 --- a/src/LedgerHistory.cpp +++ b/src/LedgerHistory.cpp @@ -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()); diff --git a/src/TaggedCache.h b/src/TaggedCache.h index bb5dc36667..92a122d017 100644 --- a/src/TaggedCache.h +++ b/src/TaggedCache.h @@ -1,8 +1,6 @@ #ifndef __TAGGEDCACHE__ #define __TAGGEDCACHE__ -#include - #include #include #include @@ -21,18 +19,18 @@ template 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 weak_data_ptr; - typedef boost::shared_ptr data_ptr; - - typedef std::pair cache_entry; + typedef boost::weak_ptr weak_data_ptr; + typedef boost::shared_ptr data_ptr; + typedef std::pair cache_entry; protected: mutable boost::recursive_mutex mLock; int mTargetSize, mTargetAge; + boost::unordered_map 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& data); + bool canonicalize(const key_type& key, boost::shared_ptr& data, bool replace = false); bool store(const key_type& key, const c_Data& data); boost::shared_ptr fetch(const key_type& key); bool retrieve(const key_type& key, c_Data& data); @@ -82,10 +81,12 @@ template void TaggedCache::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 void TaggedCache::sweep typename boost::unordered_map::iterator tmp = cit++; mCache.erase(tmp); } - else ++cit; + else + ++cit; } // Pass 2, remove dead objects from map @@ -111,7 +113,8 @@ template void TaggedCache::sweep typename boost::unordered_map::iterator tmp = mit++; mMap.erase(mit); } - else ++mit; + else + ++mit; } } @@ -121,7 +124,8 @@ template bool TaggedCache::touch // Is the object in the map? typename boost::unordered_map::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 bool TaggedCache::del(c boost::recursive_mutex::scoped_lock sl(mLock); typename boost::unordered_map::iterator cit = mCache.find(key); - if (cit == mCache.end()) return false; + if (cit == mCache.end()) + return false; mCache.erase(cit); return true; } template -bool TaggedCache::canonicalize(const key_type& key, boost::shared_ptr& data) +bool TaggedCache::canonicalize(const key_type& key, boost::shared_ptr& 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::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::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 TaggedCache::fetch(const key_type& key) // Is it in the map? typename boost::unordered_map::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 cachedData = mit->second.lock(); if (!cachedData)