mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Modify the ledger history code to use the tagged cache.
This commit is contained in:
@@ -7,55 +7,63 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
#ifndef CACHED_LEDGER_NUM
|
||||||
|
#define CACHED_LEDGER_NUM 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CACHED_LEDGER_AGE
|
||||||
|
#define CACHED_LEDGER_AGE 60
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LedgerHistory::LedgerHistory() : mLedgersByHash(CACHED_LEDGER_NUM, CACHED_LEDGER_AGE)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
void LedgerHistory::addLedger(Ledger::pointer ledger)
|
void LedgerHistory::addLedger(Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
uint256 h(ledger->getHash());
|
mLedgersByHash.canonicalize(ledger->getHash(), ledger);
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
|
||||||
mLedgersByHash.insert(std::make_pair(h, ledger));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
|
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
assert(ledger && ledger->isAccepted());
|
assert(ledger && ledger->isAccepted());
|
||||||
uint256 h(ledger->getHash());
|
uint256 h(ledger->getHash());
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
|
mLedgersByHash.canonicalize(h, ledger);
|
||||||
mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger));
|
mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger));
|
||||||
mLedgersByHash.insert(std::make_pair(h, ledger));
|
|
||||||
theApp->getIOService().post(boost::bind(&Ledger::saveAcceptedLedger, ledger));
|
theApp->getIOService().post(boost::bind(&Ledger::saveAcceptedLedger, ledger));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)
|
Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
std::map<uint32, Ledger::pointer>::iterator it(mLedgersByIndex.find(index));
|
std::map<uint32, Ledger::pointer>::iterator it(mLedgersByIndex.find(index));
|
||||||
if(it!=mLedgersByIndex.end()) return it->second;
|
if(it!=mLedgersByIndex.end()) return it->second;
|
||||||
sl.unlock();
|
sl.unlock();
|
||||||
|
|
||||||
Ledger::pointer ret(Ledger::loadByIndex(index));
|
Ledger::pointer ret(Ledger::loadByIndex(index));
|
||||||
if(!ret) return ret;
|
if(!ret) return ret;
|
||||||
|
|
||||||
assert(ret->getLedgerSeq()==index);
|
assert(ret->getLedgerSeq()==index);
|
||||||
uint256 h=ret->getHash();
|
|
||||||
sl.lock();
|
sl.lock();
|
||||||
|
mLedgersByHash.canonicalize(ret->getHash(), ret);
|
||||||
mLedgersByIndex.insert(std::make_pair(index, ret));
|
mLedgersByIndex.insert(std::make_pair(index, ret));
|
||||||
mLedgersByHash.insert(std::make_pair(h, ret));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash)
|
Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
Ledger::pointer ret=mLedgersByHash.fetch(hash);
|
||||||
std::map<uint256, Ledger::pointer>::iterator it(mLedgersByHash.find(hash));
|
if(ret) return ret;
|
||||||
if(it!=mLedgersByHash.end()) return it->second;
|
|
||||||
sl.unlock();
|
|
||||||
|
|
||||||
Ledger::pointer ret=Ledger::loadByHash(hash);
|
ret=Ledger::loadByHash(hash);
|
||||||
if(!ret) return ret;
|
if(!ret) return ret;
|
||||||
|
|
||||||
assert(ret->getHash()==hash);
|
assert(ret->getHash()==hash);
|
||||||
sl.lock();
|
|
||||||
mLedgersByHash.insert(std::make_pair(hash, ret));
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
if(ret->isAccepted()) mLedgersByIndex.insert(std::make_pair(ret->getLedgerSeq(), ret));
|
mLedgersByHash.canonicalize(hash, ret);
|
||||||
|
if(ret->isAccepted()) mLedgersByIndex[ret->getLedgerSeq()]=ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,20 +71,16 @@ Ledger::pointer LedgerHistory::canonicalizeLedger(Ledger::pointer ledger, bool s
|
|||||||
{
|
{
|
||||||
uint256 h(ledger->getHash());
|
uint256 h(ledger->getHash());
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
|
||||||
if(!save)
|
if(!save)
|
||||||
{ // return input ledger if not in map, otherwise, return corresponding map ledger
|
{ // return input ledger if not in map, otherwise, return corresponding map ledger
|
||||||
std::map<uint256, Ledger::pointer>::iterator it(mLedgersByHash.find(h));
|
Ledger::pointer ret=mLedgersByHash.fetch(h);
|
||||||
if(it!=mLedgersByHash.end()) return it->second;
|
if(ret) return ret;
|
||||||
}
|
return ledger;
|
||||||
else
|
|
||||||
{ // save input ledger in map if not in map, otherwise return corresponding map ledger
|
|
||||||
std::pair<std::map<uint256,
|
|
||||||
Ledger::pointer>::iterator, bool> sp(mLedgersByHash.insert(std::make_pair(h, ledger)));
|
|
||||||
if(!sp.second) // ledger was not inserted
|
|
||||||
return sp.first->second;
|
|
||||||
if(ledger->isAccepted())
|
|
||||||
mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save input ledger in map if not in map, otherwise return corresponding map ledger
|
||||||
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
|
mLedgersByHash.canonicalize(h, ledger);
|
||||||
|
if(ledger->isAccepted()) mLedgersByIndex[ledger->getLedgerSeq()]=ledger;
|
||||||
return ledger;
|
return ledger;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
#ifndef __LEDGERHISTORY__
|
#ifndef __LEDGERHISTORY__
|
||||||
#define __LEDGERHISTORY__
|
#define __LEDGERHISTORY__
|
||||||
|
|
||||||
|
#include "TaggedCache.h"
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
|
|
||||||
class LedgerHistory
|
class LedgerHistory
|
||||||
{
|
{
|
||||||
boost::recursive_mutex mLock;
|
TaggedCache<uint256, Ledger> mLedgersByHash;
|
||||||
|
std::map<uint32, Ledger::pointer> mLedgersByIndex; // accepted ledgers
|
||||||
std::map<uint32, Ledger::pointer> mLedgersByIndex;
|
|
||||||
std::map<uint256, Ledger::pointer> mLedgersByHash;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LedgerHistory() { ; }
|
LedgerHistory();
|
||||||
|
|
||||||
void addLedger(Ledger::pointer ledger);
|
void addLedger(Ledger::pointer ledger);
|
||||||
void addAcceptedLedger(Ledger::pointer ledger);
|
void addAcceptedLedger(Ledger::pointer ledger);
|
||||||
@@ -21,4 +20,4 @@ public:
|
|||||||
Ledger::pointer canonicalizeLedger(Ledger::pointer, bool cache);
|
Ledger::pointer canonicalizeLedger(Ledger::pointer, bool cache);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <boost/thread/recursive_mutex.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
// This class implemented a cache and a map. The cache keeps objects alive
|
// This class implemented a cache and a map. The cache keeps objects alive
|
||||||
@@ -21,7 +22,7 @@ public:
|
|||||||
typedef std::pair<time_t, data_ptr> cache_entry;
|
typedef std::pair<time_t, data_ptr> cache_entry;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable boost::mutex mLock;
|
mutable boost::recursive_mutex mLock;
|
||||||
|
|
||||||
int mTargetSize, mTargetAge;
|
int mTargetSize, mTargetAge;
|
||||||
std::map<key_type, cache_entry> mCache; // Hold strong reference to recent objects
|
std::map<key_type, cache_entry> mCache; // Hold strong reference to recent objects
|
||||||
@@ -43,8 +44,10 @@ public:
|
|||||||
|
|
||||||
bool touch(const key_type& key);
|
bool touch(const key_type& key);
|
||||||
bool del(const key_type& key);
|
bool del(const key_type& key);
|
||||||
boost::shared_ptr<c_Data> canonicalize(const key_type& key, boost::shared_ptr<c_Data> data);
|
bool canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data);
|
||||||
boost::shared_ptr<c_Data> fetch(const key_type& key);
|
boost::shared_ptr<c_Data> fetch(const key_type& key);
|
||||||
|
|
||||||
|
boost::recursive_mutex& peekMutex() { return mLock; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTargetSize() const
|
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTargetSize() const
|
||||||
@@ -65,13 +68,13 @@ template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getTar
|
|||||||
|
|
||||||
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getCacheSize()
|
template<typename c_Key, typename c_Data> int TaggedCache<c_Key, c_Data>::getCacheSize()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
return mCache.size();
|
return mCache.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep()
|
template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
if(mCache.size()<mTargetSize) return;
|
if(mCache.size()<mTargetSize) return;
|
||||||
|
|
||||||
@@ -110,7 +113,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
|
|||||||
|
|
||||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch(const key_type& key)
|
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch(const key_type& key)
|
||||||
{ // If present, make current in cache
|
{ // If present, make current in cache
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
// Is the object in the map?
|
// Is the object in the map?
|
||||||
typename std::map<key_type, weak_data_ptr>::iterator mit=mMap.find(key);
|
typename std::map<key_type, weak_data_ptr>::iterator mit=mMap.find(key);
|
||||||
@@ -136,7 +139,7 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch
|
|||||||
|
|
||||||
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(const key_type& key)
|
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(const key_type& key)
|
||||||
{ // Remove from cache, map unaffected
|
{ // Remove from cache, map unaffected
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
||||||
if(cit==mCache.end()) return false;
|
if(cit==mCache.end()) return false;
|
||||||
@@ -145,57 +148,62 @@ template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::del(c
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename c_Key, typename c_Data>
|
template<typename c_Key, typename c_Data>
|
||||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key,
|
bool TaggedCache<c_Key, c_Data>::canonicalize(const key_type& key, boost::shared_ptr<c_Data>& data)
|
||||||
boost::shared_ptr<c_Data> data)
|
|
||||||
{ // Return canonical value, store if needed, refresh in cache
|
{ // Return canonical value, store if needed, refresh in cache
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
// Return values: true=we had the data already
|
||||||
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
typename std::map<key_type, weak_data_ptr>::iterator mit=mMap.find(key);
|
typename std::map<key_type, weak_data_ptr>::iterator mit=mMap.find(key);
|
||||||
if(mit==mMap.end())
|
if(mit==mMap.end())
|
||||||
{ // not in map
|
{ // not in map
|
||||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||||
mMap.insert(std::make_pair(key, data));
|
mMap.insert(std::make_pair(key, data));
|
||||||
return data;
|
return false;
|
||||||
}
|
}
|
||||||
if(mit->second->expired())
|
if(mit->second.expired())
|
||||||
{ // in map, but expired
|
{ // in map, but expired
|
||||||
mit->second=data;
|
mit->second=data;
|
||||||
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||||
return data;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data=mit->second.lock();
|
||||||
|
assert(!!data);
|
||||||
|
|
||||||
// Valid in map, is it in cache?
|
// Valid in map, is it in cache?
|
||||||
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
||||||
if(cit!=mCache.end())
|
if(cit!=mCache.end())
|
||||||
cit->second->first=time(NULL); // Yes, refesh
|
cit->second.first=time(NULL); // Yes, refesh
|
||||||
else // no, add to cache
|
else // no, add to cache
|
||||||
cit.insert(std::make_pair(key, std::make_pair(time(NULL), weak_data_ptr(mit->second))));
|
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||||
|
|
||||||
return mit->second;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename c_Key, typename c_Data>
|
template<typename c_Key, typename c_Data>
|
||||||
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
// Is it in the map?
|
// Is it in the map?
|
||||||
typename std::map<key_type, weak_data_ptr>::iterator mit=mMap.find(key);
|
typename std::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
|
||||||
if(mit->second->expired())
|
if(mit->second.expired())
|
||||||
{ // in map, but expired
|
{ // in map, but expired
|
||||||
mMap.erase(mit);
|
mMap.erase(mit);
|
||||||
return data_ptr();
|
return data_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<c_Data> data=mit->second.lock();
|
||||||
|
|
||||||
// Valid in map, is it in the cache?
|
// Valid in map, is it in the cache?
|
||||||
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
typename std::map<key_type, cache_entry>::iterator cit=mCache.find(key);
|
||||||
if(cit!=mCache.end())
|
if(cit!=mCache.end())
|
||||||
cit->second->first=time(NULL); // Yes, refresh
|
cit->second.first=time(NULL); // Yes, refresh
|
||||||
else // No, add to cache
|
else // No, add to cache
|
||||||
cit.insert(std::make_pair(key, std::make_pair(time(NULL), weak_data_ptr(mit->second))));
|
mCache.insert(std::make_pair(key, std::make_pair(time(NULL), data)));
|
||||||
|
|
||||||
return mit->second;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user