mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Clean up JSONCache
This commit is contained in:
@@ -129,11 +129,6 @@ namespace boost {
|
|||||||
#include "utility/ripple_IntegerTypes.h" // must come first
|
#include "utility/ripple_IntegerTypes.h" // must come first
|
||||||
#include "utility/ripple_Log.h" // Needed by others
|
#include "utility/ripple_Log.h" // Needed by others
|
||||||
|
|
||||||
#include "containers/ripple_KeyCache.h"
|
|
||||||
#include "containers/ripple_RangeSet.h"
|
|
||||||
#include "containers/ripple_SecureAllocator.h"
|
|
||||||
#include "containers/ripple_TaggedCache.h"
|
|
||||||
|
|
||||||
#include "types/ripple_BasicTypes.h"
|
#include "types/ripple_BasicTypes.h"
|
||||||
#include "utility/ripple_ByteOrder.h"
|
#include "utility/ripple_ByteOrder.h"
|
||||||
#include "utility/ripple_DiffieHellmanUtil.h"
|
#include "utility/ripple_DiffieHellmanUtil.h"
|
||||||
@@ -151,4 +146,9 @@ namespace boost {
|
|||||||
#include "utility/ripple_HashUtilities.h" // requires UInt256
|
#include "utility/ripple_HashUtilities.h" // requires UInt256
|
||||||
#include "types/ripple_HashMaps.h"
|
#include "types/ripple_HashMaps.h"
|
||||||
|
|
||||||
|
#include "containers/ripple_KeyCache.h"
|
||||||
|
#include "containers/ripple_RangeSet.h"
|
||||||
|
#include "containers/ripple_SecureAllocator.h"
|
||||||
|
#include "containers/ripple_TaggedCache.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
#include "src/cpp/ripple/ripple_InfoSub.h"
|
#include "src/cpp/ripple/ripple_InfoSub.h"
|
||||||
|
|
||||||
// Order and indentation reflect the hierarchy of dependencies
|
// Order and indentation reflect the hierarchy of dependencies
|
||||||
#include "src/cpp/ripple/JSONCache.h"
|
// VFALCO NOTE Don't add anything here!!!
|
||||||
#include "src/cpp/ripple/ripple_HashedObject.h"
|
#include "src/cpp/ripple/ripple_HashedObject.h"
|
||||||
#include "src/cpp/ripple/ripple_SHAMapItem.h"
|
#include "src/cpp/ripple/ripple_SHAMapItem.h"
|
||||||
#include "src/cpp/ripple/ripple_SHAMapNode.h"
|
#include "src/cpp/ripple/ripple_SHAMapNode.h"
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ static const uint64 tenTo17m1 = tenTo17 - 1;
|
|||||||
#include "protocol/ripple_STAmount.cpp"
|
#include "protocol/ripple_STAmount.cpp"
|
||||||
#include "protocol/ripple_STAmountRound.cpp"
|
#include "protocol/ripple_STAmountRound.cpp"
|
||||||
|
|
||||||
|
#include "utility/ripple_JSONCache.cpp"
|
||||||
|
|
||||||
// VFALCO TODO Fix this for SConstruct
|
// VFALCO TODO Fix this for SConstruct
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include "ripple.pb.cc" // BROKEN because of SConstruct
|
#include "ripple.pb.cc" // BROKEN because of SConstruct
|
||||||
|
|||||||
@@ -87,6 +87,7 @@
|
|||||||
#include "protocol/ripple_LedgerFormat.h" // needs SOTemplate from SerializedObject
|
#include "protocol/ripple_LedgerFormat.h" // needs SOTemplate from SerializedObject
|
||||||
#include "protocol/ripple_TransactionFormat.h"
|
#include "protocol/ripple_TransactionFormat.h"
|
||||||
|
|
||||||
|
#include "utility/ripple_JSONCache.h"
|
||||||
#include "utility/ripple_UptimeTimerAdapter.h"
|
#include "utility/ripple_UptimeTimerAdapter.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
157
modules/ripple_data/utility/ripple_JSONCache.cpp
Normal file
157
modules/ripple_data/utility/ripple_JSONCache.cpp
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JSONCache::Key::Key (int op, uint256 const& ledger, uint160 const& 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 JSONCache::Key::compare (Key const& other) const
|
||||||
|
{
|
||||||
|
if (mHash < other.mHash) return -1;
|
||||||
|
if (mHash > other.mHash) return 1;
|
||||||
|
if (mOperation < other.mOperation) return -1;
|
||||||
|
if (mOperation > other.mOperation) return 1;
|
||||||
|
if (mLedger < other.mLedger) return -1;
|
||||||
|
if (mLedger > other.mLedger) return 1;
|
||||||
|
if (mObject < other.mObject) return -1;
|
||||||
|
if (mObject > other.mObject) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JSONCache::Key::operator< (Key const& rhs) const { return compare (rhs) < 0; }
|
||||||
|
bool JSONCache::Key::operator> (Key const& rhs) const { return compare (rhs) > 0; }
|
||||||
|
bool JSONCache::Key::operator<= (Key const& rhs) const { return compare (rhs) <= 0; }
|
||||||
|
bool JSONCache::Key::operator>= (Key const& rhs) const { return compare (rhs) >= 0; }
|
||||||
|
bool JSONCache::Key::operator!= (Key const& rhs) const { return compare (rhs) != 0; }
|
||||||
|
bool JSONCache::Key::operator== (Key const& rhs) const { return compare (rhs) == 0; }
|
||||||
|
|
||||||
|
void JSONCache::Key::touch (Key const& key) const
|
||||||
|
{
|
||||||
|
mLastUse = key.mLastUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JSONCache::Key::isExpired (int expireTimeSeconds) const
|
||||||
|
{
|
||||||
|
return mLastUse < expireTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t JSONCache::Key::getHash () const
|
||||||
|
{
|
||||||
|
return mHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JSONCache::JSONCache (int expirationTimeInSeconds)
|
||||||
|
: m_expirationTime (expirationTimeInSeconds)
|
||||||
|
, mHits (0)
|
||||||
|
, mMisses (0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
float JSONCache::getHitRate ()
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl (m_lock);
|
||||||
|
|
||||||
|
return (static_cast <float> (mHits) * 100.f) / (1.0f + mHits + mMisses);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int JSONCache::getNumberOfEntries ()
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl (m_lock);
|
||||||
|
|
||||||
|
return m_cache.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
JSONCache::data_t JSONCache::getEntry (Kind kind, LedgerHash const& ledger, uint160 const& object)
|
||||||
|
{
|
||||||
|
JSONCache::data_t result; // default constructor indicates not found
|
||||||
|
|
||||||
|
Key key (kind, ledger, object, getUptime ());
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||||
|
|
||||||
|
boost::unordered_map <Key, data_t>::iterator it = m_cache.find (key);
|
||||||
|
|
||||||
|
if (it != m_cache.end ())
|
||||||
|
{
|
||||||
|
++mHits;
|
||||||
|
|
||||||
|
it->first.touch (key);
|
||||||
|
|
||||||
|
result = it->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++mMisses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void JSONCache::storeEntry (Kind kind, uint256 const& ledger, uint160 const& object, data_t const& data)
|
||||||
|
{
|
||||||
|
Key key (kind, ledger, object, getUptime ());
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||||
|
|
||||||
|
m_cache.insert (std::pair <Key, data_t> (key, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void JSONCache::sweep ()
|
||||||
|
{
|
||||||
|
int sweepTime = getUptime ();
|
||||||
|
|
||||||
|
if (sweepTime >= m_expirationTime)
|
||||||
|
{
|
||||||
|
sweepTime -= m_expirationTime;
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl(m_lock);
|
||||||
|
|
||||||
|
boost::unordered_map <Key, data_t>::iterator it = m_cache.begin();
|
||||||
|
|
||||||
|
while (it != m_cache.end ())
|
||||||
|
{
|
||||||
|
if (it->first.isExpired (sweepTime))
|
||||||
|
{
|
||||||
|
it = m_cache.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int JSONCache::getUptime () const
|
||||||
|
{
|
||||||
|
return UptimeTimer::getInstance().getElapsedSeconds();
|
||||||
|
}
|
||||||
92
modules/ripple_data/utility/ripple_JSONCache.h
Normal file
92
modules/ripple_data/utility/ripple_JSONCache.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#ifndef RIPPLE_JSCONCACHE_H
|
||||||
|
#define RIPPLE_JSCONCACHE_H
|
||||||
|
|
||||||
|
/** A simple cache for JSON.
|
||||||
|
|
||||||
|
@note All member functions are thread-safe.
|
||||||
|
*/
|
||||||
|
class JSONCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Key
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Key (int op, const uint256& ledger, const uint160& object, int lastUse);
|
||||||
|
int compare(const Key& k) const;
|
||||||
|
bool operator<(const Key &k) const;
|
||||||
|
bool operator>(const Key &k) const;
|
||||||
|
bool operator<=(const Key &k) const;
|
||||||
|
bool operator>=(const Key &k) const;
|
||||||
|
bool operator!=(const Key &k) const;
|
||||||
|
bool operator==(const Key &k) const;
|
||||||
|
|
||||||
|
void touch (Key const& key) const;
|
||||||
|
bool isExpired (int expireTime) const;
|
||||||
|
|
||||||
|
std::size_t getHash () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint256 mLedger;
|
||||||
|
uint160 mObject;
|
||||||
|
int mOperation;
|
||||||
|
mutable int mLastUse;
|
||||||
|
std::size_t mHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr <Json::Value> data_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Kind
|
||||||
|
{
|
||||||
|
kindLines,
|
||||||
|
kindOffers
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Construct the cache.
|
||||||
|
|
||||||
|
@param expirationTimeInSeconds The time until cached items expire, in seconds.
|
||||||
|
*/
|
||||||
|
explicit JSONCache (int expirationTimeInSeconds);
|
||||||
|
|
||||||
|
/** Return the fraction of cache hits.
|
||||||
|
*/
|
||||||
|
float getHitRate ();
|
||||||
|
|
||||||
|
/** Return the number of cached items.
|
||||||
|
*/
|
||||||
|
int getNumberOfEntries ();
|
||||||
|
|
||||||
|
/** Retrieve a cached item.
|
||||||
|
|
||||||
|
@return The item, or a default constructed container if it was not found.
|
||||||
|
*/
|
||||||
|
data_t getEntry (Kind kind, LedgerHash const& ledger, uint160 const& object);
|
||||||
|
|
||||||
|
/** Store an item in the cache.
|
||||||
|
*/
|
||||||
|
void storeEntry (Kind kind, LedgerHash const& ledger, uint160 const& object, data_t const& data);
|
||||||
|
|
||||||
|
/** Purge expired items.
|
||||||
|
|
||||||
|
This must be called periodically.
|
||||||
|
*/
|
||||||
|
void sweep ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int getUptime () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int const m_expirationTime;
|
||||||
|
boost::unordered_map <Key, data_t> m_cache;
|
||||||
|
boost::recursive_mutex m_lock;
|
||||||
|
uint64 mHits;
|
||||||
|
uint64 mMisses;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::size_t hash_value (JSONCache::Key const& key)
|
||||||
|
{
|
||||||
|
return key.getHash ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -185,7 +185,6 @@
|
|||||||
#include "src/cpp/ripple/LedgerEntrySet.h"
|
#include "src/cpp/ripple/LedgerEntrySet.h"
|
||||||
#include "src/cpp/ripple/TransactionEngine.h"
|
#include "src/cpp/ripple/TransactionEngine.h"
|
||||||
#include "src/cpp/ripple/ripple_CanonicalTXSet.h"
|
#include "src/cpp/ripple/ripple_CanonicalTXSet.h"
|
||||||
#include "src/cpp/ripple/JSONCache.h"
|
|
||||||
|
|
||||||
#include "src/cpp/ripple/ripple_LedgerHistory.h"
|
#include "src/cpp/ripple/ripple_LedgerHistory.h"
|
||||||
#include "src/cpp/ripple/LedgerMaster.h"
|
#include "src/cpp/ripple/LedgerMaster.h"
|
||||||
|
|||||||
@@ -354,6 +354,12 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="modules\ripple_data\ripple_data.cpp" />
|
<ClCompile Include="modules\ripple_data\ripple_data.cpp" />
|
||||||
|
<ClCompile Include="modules\ripple_data\utility\ripple_JSONCache.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="modules\ripple_db\ripple_db.cpp" />
|
<ClCompile Include="modules\ripple_db\ripple_db.cpp" />
|
||||||
<ClCompile Include="modules\ripple_json\json\json_reader.cpp">
|
<ClCompile Include="modules\ripple_json\json\json_reader.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
@@ -1367,6 +1373,8 @@
|
|||||||
<ClInclude Include="modules\ripple_data\protocol\ripple_TER.h" />
|
<ClInclude Include="modules\ripple_data\protocol\ripple_TER.h" />
|
||||||
<ClInclude Include="modules\ripple_data\protocol\ripple_TransactionFormat.h" />
|
<ClInclude Include="modules\ripple_data\protocol\ripple_TransactionFormat.h" />
|
||||||
<ClInclude Include="modules\ripple_data\ripple_data.h" />
|
<ClInclude Include="modules\ripple_data\ripple_data.h" />
|
||||||
|
<ClInclude Include="modules\ripple_data\utility\ripple_JSONCache.h" />
|
||||||
|
<ClInclude Include="modules\ripple_data\utility\ripple_UptimeTimerAdapter.h" />
|
||||||
<ClInclude Include="modules\ripple_db\ripple_db.h" />
|
<ClInclude Include="modules\ripple_db\ripple_db.h" />
|
||||||
<ClInclude Include="modules\ripple_json\json\json.h" />
|
<ClInclude Include="modules\ripple_json\json\json.h" />
|
||||||
<ClInclude Include="modules\ripple_json\json\json_autolink.h" />
|
<ClInclude Include="modules\ripple_json\json\json_autolink.h" />
|
||||||
|
|||||||
@@ -133,6 +133,9 @@
|
|||||||
<Filter Include="1. Modules\ripple_client">
|
<Filter Include="1. Modules\ripple_client">
|
||||||
<UniqueIdentifier>{97c96b68-70fd-4679-89fc-c1c8c87c265e}</UniqueIdentifier>
|
<UniqueIdentifier>{97c96b68-70fd-4679-89fc-c1c8c87c265e}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="1. Modules\ripple_data\utility">
|
||||||
|
<UniqueIdentifier>{ba524810-8446-4c50-ad59-d284747ba220}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\cpp\database\sqlite3.c">
|
<ClCompile Include="src\cpp\database\sqlite3.c">
|
||||||
@@ -837,6 +840,9 @@
|
|||||||
<ClCompile Include="src\cpp\ripple\ripple_Application.cpp">
|
<ClCompile Include="src\cpp\ripple\ripple_Application.cpp">
|
||||||
<Filter>1. Modules\ripple_main\_unfactored\main</Filter>
|
<Filter>1. Modules\ripple_main\_unfactored\main</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="modules\ripple_data\utility\ripple_JSONCache.cpp">
|
||||||
|
<Filter>1. Modules\ripple_data\utility</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="database\sqlite3ext.h">
|
<ClInclude Include="database\sqlite3ext.h">
|
||||||
@@ -1580,6 +1586,12 @@
|
|||||||
<ClInclude Include="src\cpp\ripple\ripple_IApplication.h">
|
<ClInclude Include="src\cpp\ripple\ripple_IApplication.h">
|
||||||
<Filter>1. Modules\ripple_main\_unfactored\main</Filter>
|
<Filter>1. Modules\ripple_main\_unfactored\main</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="modules\ripple_data\utility\ripple_UptimeTimerAdapter.h">
|
||||||
|
<Filter>1. Modules\ripple_data\utility</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="modules\ripple_data\utility\ripple_JSONCache.h">
|
||||||
|
<Filter>1. Modules\ripple_data\utility</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="SConstruct" />
|
<None Include="SConstruct" />
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -177,14 +177,16 @@ public:
|
|||||||
void sweepFetchPack();
|
void sweepFetchPack();
|
||||||
|
|
||||||
float getJSONHitRate() { return mJSONCache.getHitRate(); }
|
float getJSONHitRate() { return mJSONCache.getHitRate(); }
|
||||||
int getJSONEntries() { return mJSONCache.getCount(); }
|
|
||||||
|
|
||||||
void storeJSONCache(int operation, const uint256& ledger, const uint160& object,
|
// VFALCO TODO Rename this to getNumberOfCachedJSONItems or something similar
|
||||||
const boost::shared_ptr<Json::Value>& data)
|
int getJSONEntries() { return mJSONCache.getNumberOfEntries(); }
|
||||||
{ mJSONCache.storeEntry(operation, ledger, object, data); }
|
|
||||||
|
|
||||||
boost::shared_ptr<Json::Value> getJSONCache(int operation, const uint256& ledger, const uint160& object)
|
void storeJSONCache(JSONCache::Kind kind, const uint256& ledger, const uint160& object,
|
||||||
{ return mJSONCache.getEntry(operation, ledger, 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
|
// network state machine
|
||||||
void checkState(const boost::system::error_code& result);
|
void checkState(const boost::system::error_code& result);
|
||||||
@@ -313,7 +315,7 @@ private:
|
|||||||
subMapType mSubTransactions; // all accepted transactions
|
subMapType mSubTransactions; // all accepted transactions
|
||||||
subMapType mSubRTTransactions; // all proposed and accepted transactions
|
subMapType mSubRTTransactions; // all proposed and accepted transactions
|
||||||
|
|
||||||
JSONCache<UptimeTimerAdapter> mJSONCache;
|
JSONCache mJSONCache;
|
||||||
|
|
||||||
TaggedCache< uint256, Blob , UptimeTimerAdapter > mFetchPack;
|
TaggedCache< uint256, Blob , UptimeTimerAdapter > mFetchPack;
|
||||||
uint32 mLastFetchPack;
|
uint32 mLastFetchPack;
|
||||||
|
|||||||
@@ -1093,7 +1093,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest, int& cost, ScopedL
|
|||||||
jvResult["account"] = raAccount.humanAccountID();
|
jvResult["account"] = raAccount.humanAccountID();
|
||||||
|
|
||||||
boost::shared_ptr<Json::Value> jvsLines =
|
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)
|
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);
|
raAccount.getAccountID(), jvsLines);
|
||||||
}
|
}
|
||||||
if (!bUnlocked)
|
if (!bUnlocked)
|
||||||
@@ -1199,13 +1199,13 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest, int& cost, Scoped
|
|||||||
return rpcError(rpcACT_NOT_FOUND);
|
return rpcError(rpcACT_NOT_FOUND);
|
||||||
|
|
||||||
boost::shared_ptr<Json::Value> jvsOffers =
|
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)
|
if (!jvsOffers)
|
||||||
{
|
{
|
||||||
jvsOffers = boost::make_shared<Json::Value>(Json::arrayValue);
|
jvsOffers = boost::make_shared<Json::Value>(Json::arrayValue);
|
||||||
lpLedger->visitAccountItems(raAccount.getAccountID(), BIND_TYPE(&offerAdder, boost::ref(*jvsOffers), P_1));
|
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)
|
if (!bUnlocked)
|
||||||
MasterLockHolder.unlock();
|
MasterLockHolder.unlock();
|
||||||
|
|||||||
Reference in New Issue
Block a user