Clean up JSONCache

This commit is contained in:
Vinnie Falco
2013-06-12 16:08:50 -07:00
parent 41f69a9992
commit 12d1117623
12 changed files with 291 additions and 145 deletions

View File

@@ -1,127 +0,0 @@
#ifndef JSONCACHE_H
#define JSONCACHE_H
#define JC_OP_ACCOUNT_LINES 1
#define JC_OP_ACCOUNT_OFFERS 2
class JSONCacheKey
{
private:
uint256 mLedger;
uint160 mObject;
int mOperation;
mutable int mLastUse;
std::size_t mHash;
public:
JSONCacheKey(int op, const uint256& ledger, const uint160& object, int lastUse)
: mLedger(ledger), mObject(object), mOperation(op), mLastUse(lastUse)
{
mHash = static_cast<std::size_t>(mOperation);
mLedger.hash_combine(mHash);
mObject.hash_combine(mHash);
}
int compare(const JSONCacheKey& k) const
{
if (mHash < k.mHash) return -1;
if (mHash > k.mHash) return 1;
if (mOperation < k.mOperation) return -1;
if (mOperation > k.mOperation) return 1;
if (mLedger < k.mLedger) return -1;
if (mLedger > k.mLedger) return 1;
if (mObject < k.mObject) return -1;
if (mObject > k.mObject) return 1;
return 0;
}
bool operator<(const JSONCacheKey &k) const { return compare(k) < 0; }
bool operator>(const JSONCacheKey &k) const { return compare(k) > 0; }
bool operator<=(const JSONCacheKey &k) const { return compare(k) <= 0; }
bool operator>=(const JSONCacheKey &k) const { return compare(k) >= 0; }
bool operator!=(const JSONCacheKey &k) const { return compare(k) != 0; }
bool operator==(const JSONCacheKey &k) const { return compare(k) == 0; }
void touch(const JSONCacheKey& key) const { mLastUse = key.mLastUse; }
bool expired(int expireTime) const { return mLastUse < expireTime; }
std::size_t getHash() const { return mHash; }
};
inline std::size_t hash_value(const JSONCacheKey& key) { return key.getHash(); }
template <class Timer>
class JSONCache
{
public:
typedef boost::shared_ptr<Json::Value> data_t;
protected:
boost::recursive_mutex mLock;
boost::unordered_map<JSONCacheKey, data_t> mCache;
int mCacheTime;
uint64 mHits, mMisses;
public:
JSONCache(int cacheTime) : mCacheTime(cacheTime), mHits(0), mMisses(0) { ; }
int upTime() { return Timer::getElapsedSeconds(); }
float getHitRate()
{
boost::recursive_mutex::scoped_lock sl(mLock);
return (static_cast<float>(mHits) * 100) / (1.0f + mHits + mMisses);
}
int getCount()
{
boost::recursive_mutex::scoped_lock sl(mLock);
return mCache.size();
}
data_t getEntry(int operation, const uint256& ledger, const uint160& object)
{
JSONCacheKey key(operation, ledger, object, upTime());
boost::recursive_mutex::scoped_lock sl(mLock);
boost::unordered_map<JSONCacheKey, data_t>::iterator it = mCache.find(key);
if (it == mCache.end())
{
++mMisses;
return data_t();
}
++mHits;
it->first.touch(key);
return it->second;
}
void storeEntry(int operation, const uint256& ledger, const uint160& object, const data_t& data)
{
JSONCacheKey key(operation, ledger, object, upTime());
boost::recursive_mutex::scoped_lock sl(mLock);
mCache.insert(std::pair<JSONCacheKey, data_t>(key, data));
}
void sweep()
{
int sweepTime = upTime();
if (sweepTime < mCacheTime)
return;
sweepTime -= mCacheTime;
boost::recursive_mutex::scoped_lock sl(mLock);
boost::unordered_map<JSONCacheKey, data_t>::iterator it = mCache.begin();
while (it != mCache.end())
{
if (it->first.expired(sweepTime))
it = mCache.erase(it);
else
++it;
}
}
};
#endif

View File

@@ -177,14 +177,16 @@ public:
void sweepFetchPack();
float getJSONHitRate() { return mJSONCache.getHitRate(); }
int getJSONEntries() { return mJSONCache.getCount(); }
void storeJSONCache(int operation, const uint256& ledger, const uint160& object,
const boost::shared_ptr<Json::Value>& data)
{ mJSONCache.storeEntry(operation, ledger, object, data); }
// VFALCO TODO Rename this to getNumberOfCachedJSONItems or something similar
int getJSONEntries() { return mJSONCache.getNumberOfEntries(); }
boost::shared_ptr<Json::Value> getJSONCache(int operation, const uint256& ledger, const uint160& object)
{ return mJSONCache.getEntry(operation, ledger, object); }
void storeJSONCache(JSONCache::Kind kind, const uint256& ledger, const uint160& object,
const boost::shared_ptr <Json::Value>& data)
{ mJSONCache.storeEntry(kind, ledger, object, data); }
boost::shared_ptr<Json::Value> getJSONCache(JSONCache::Kind kind, const uint256& ledger, const uint160& object)
{ return mJSONCache.getEntry(kind, ledger, object); }
// network state machine
void checkState(const boost::system::error_code& result);
@@ -313,7 +315,7 @@ private:
subMapType mSubTransactions; // all accepted transactions
subMapType mSubRTTransactions; // all proposed and accepted transactions
JSONCache<UptimeTimerAdapter> mJSONCache;
JSONCache mJSONCache;
TaggedCache< uint256, Blob , UptimeTimerAdapter > mFetchPack;
uint32 mLastFetchPack;

View File

@@ -1093,7 +1093,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL
jvResult["account"] = raAccount.humanAccountID();
boost::shared_ptr<Json::Value> jvsLines =
theApp->getOPs().getJSONCache(JC_OP_ACCOUNT_LINES, lpLedger->getHash(), raAccount.getAccountID());
theApp->getOPs().getJSONCache(JSONCache::kindLines, lpLedger->getHash(), raAccount.getAccountID());
if (!jvsLines)
{
@@ -1126,7 +1126,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL
}
}
theApp->getOPs().storeJSONCache(JC_OP_ACCOUNT_LINES, lpLedger->getHash(),
theApp->getOPs().storeJSONCache(JSONCache::kindLines, lpLedger->getHash(),
raAccount.getAccountID(), jvsLines);
}
if (!bUnlocked)
@@ -1199,13 +1199,13 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest, int& cost, Scoped
return rpcError(rpcACT_NOT_FOUND);
boost::shared_ptr<Json::Value> jvsOffers =
theApp->getOPs().getJSONCache(JC_OP_ACCOUNT_OFFERS, lpLedger->getHash(), raAccount.getAccountID());
theApp->getOPs().getJSONCache(JSONCache::kindOffers, lpLedger->getHash(), raAccount.getAccountID());
if (!jvsOffers)
{
jvsOffers = boost::make_shared<Json::Value>(Json::arrayValue);
lpLedger->visitAccountItems(raAccount.getAccountID(), BIND_TYPE(&offerAdder, boost::ref(*jvsOffers), P_1));
theApp->getOPs().storeJSONCache(JC_OP_ACCOUNT_OFFERS, lpLedger->getHash(), raAccount.getAccountID(), jvsOffers);
theApp->getOPs().storeJSONCache(JSONCache::kindOffers, lpLedger->getHash(), raAccount.getAccountID(), jvsOffers);
}
if (!bUnlocked)
MasterLockHolder.unlock();