mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Complete NodeStore documentation
* Complete README.md * Add missing doxygen * Fix getHitRate bug
This commit is contained in:
committed by
Vinnie Falco
parent
3ca9646329
commit
06d6e4901e
@@ -283,15 +283,6 @@
|
|||||||
<Filter Include="[1] Ripple\common\impl">
|
<Filter Include="[1] Ripple\common\impl">
|
||||||
<UniqueIdentifier>{6f3085f6-dbe3-4622-a680-682787d0708c}</UniqueIdentifier>
|
<UniqueIdentifier>{6f3085f6-dbe3-4622-a680-682787d0708c}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="[1] Ripple\radmap">
|
|
||||||
<UniqueIdentifier>{1b34e7e8-8260-488c-8d09-bdd3b474f9e3}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="[1] Ripple\radmap\api">
|
|
||||||
<UniqueIdentifier>{19de3695-4341-49db-9da2-b220bc9e0149}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="[1] Ripple\radmap\impl">
|
|
||||||
<UniqueIdentifier>{67371f65-f9be-45b1-81e8-c83ef3336e5c}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="[1] Ripple\peerfinder\sim">
|
<Filter Include="[1] Ripple\peerfinder\sim">
|
||||||
<UniqueIdentifier>{c429638b-4572-44e4-a48a-c18fdd094ae1}</UniqueIdentifier>
|
<UniqueIdentifier>{c429638b-4572-44e4-a48a-c18fdd094ae1}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -337,6 +328,15 @@
|
|||||||
<Filter Include="[1] Ripple\websocket">
|
<Filter Include="[1] Ripple\websocket">
|
||||||
<UniqueIdentifier>{6967f835-a1b0-47e3-9bd9-6fc8bd0f3df7}</UniqueIdentifier>
|
<UniqueIdentifier>{6967f835-a1b0-47e3-9bd9-6fc8bd0f3df7}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="[1] Ripple\proto\radmap">
|
||||||
|
<UniqueIdentifier>{1b34e7e8-8260-488c-8d09-bdd3b474f9e3}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="[1] Ripple\proto\radmap\api">
|
||||||
|
<UniqueIdentifier>{19de3695-4341-49db-9da2-b220bc9e0149}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="[1] Ripple\proto\radmap\impl">
|
||||||
|
<UniqueIdentifier>{67371f65-f9be-45b1-81e8-c83ef3336e5c}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\ripple_basics\containers\RangeSet.cpp">
|
<ClCompile Include="..\..\src\ripple_basics\containers\RangeSet.cpp">
|
||||||
@@ -1330,10 +1330,10 @@
|
|||||||
<Filter>[2] Old Ripple\ripple_app\ledger</Filter>
|
<Filter>[2] Old Ripple\ripple_app\ledger</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\radmap\ripple_radmap.cpp">
|
<ClCompile Include="..\..\src\ripple\radmap\ripple_radmap.cpp">
|
||||||
<Filter>[1] Ripple\radmap</Filter>
|
<Filter>[1] Ripple\proto\radmap</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\radmap\impl\BasicFullBelowCache.cpp">
|
<ClCompile Include="..\..\src\ripple\radmap\impl\BasicFullBelowCache.cpp">
|
||||||
<Filter>[1] Ripple\radmap\impl</Filter>
|
<Filter>[1] Ripple\proto\radmap\impl</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\src\ripple\common\impl\KeyCache.cpp">
|
<ClCompile Include="..\..\src\ripple\common\impl\KeyCache.cpp">
|
||||||
<Filter>[1] Ripple\common\impl</Filter>
|
<Filter>[1] Ripple\common\impl</Filter>
|
||||||
@@ -3057,13 +3057,13 @@
|
|||||||
<Filter>[2] Old Ripple\ripple_basics\containers</Filter>
|
<Filter>[2] Old Ripple\ripple_basics\containers</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\radmap\ripple_radmap.h">
|
<ClInclude Include="..\..\src\ripple\radmap\ripple_radmap.h">
|
||||||
<Filter>[1] Ripple\radmap</Filter>
|
<Filter>[1] Ripple\proto\radmap</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\radmap\api\BasicFullBelowCache.h">
|
<ClInclude Include="..\..\src\ripple\radmap\api\BasicFullBelowCache.h">
|
||||||
<Filter>[1] Ripple\radmap\api</Filter>
|
<Filter>[1] Ripple\proto\radmap\api</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\radmap\api\Tuning.h">
|
<ClInclude Include="..\..\src\ripple\radmap\api\Tuning.h">
|
||||||
<Filter>[1] Ripple\radmap\api</Filter>
|
<Filter>[1] Ripple\proto\radmap\api</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\common\KeyCache.h">
|
<ClInclude Include="..\..\src\ripple\common\KeyCache.h">
|
||||||
<Filter>[1] Ripple\common</Filter>
|
<Filter>[1] Ripple\common</Filter>
|
||||||
@@ -3507,10 +3507,10 @@
|
|||||||
<Filter>[2] Old Ripple\ripple_app\ledger</Filter>
|
<Filter>[2] Old Ripple\ripple_app\ledger</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\ripple\radmap\README.md">
|
<None Include="..\..\src\ripple\radmap\README.md">
|
||||||
<Filter>[1] Ripple\radmap</Filter>
|
<Filter>[1] Ripple\proto\radmap</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\ripple\radmap\TODO.md">
|
<None Include="..\..\src\ripple\radmap\TODO.md">
|
||||||
<Filter>[1] Ripple\radmap</Filter>
|
<Filter>[1] Ripple\proto\radmap</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\src\ripple_rpc\README.md">
|
<None Include="..\..\src\ripple_rpc\README.md">
|
||||||
<Filter>[2] Old Ripple\ripple_rpc</Filter>
|
<Filter>[2] Old Ripple\ripple_rpc</Filter>
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ public:
|
|||||||
float getHitRate ()
|
float getHitRate ()
|
||||||
{
|
{
|
||||||
lock_guard lock (m_mutex);
|
lock_guard lock (m_mutex);
|
||||||
return (static_cast<float> (m_hits) * 100) / (1.0f + m_hits + m_misses);
|
auto const total = static_cast<float> (m_hits + m_misses);
|
||||||
|
return m_hits * (100.0f / std::max (1.0f, total));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearStats ()
|
void clearStats ()
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ public:
|
|||||||
|
|
||||||
statement.bind(1, to_string (object->getHash()));
|
statement.bind(1, to_string (object->getHash()));
|
||||||
statement.bind(2, type);
|
statement.bind(2, type);
|
||||||
statement.bind(3, object->getIndex());
|
statement.bind(3, object->getLedgerIndex());
|
||||||
statement.bindStatic(4, object->getData());
|
statement.bindStatic(4, object->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,102 @@
|
|||||||
|
|
||||||
# NodeStore
|
# NodeStore
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
The NodeStore provides an interface that stores, in a persistent database, the collection of
|
A `NodeObject` is a simple object that the Ledger uses to store entries. It is
|
||||||
NodeObject that rippled uses as its primary representation of ledger items.
|
comprised of a type, a hash, a ledger index and a blob. It can be uniquely
|
||||||
|
identified by the hash, which is a 256 bit hash of the blob. The blob is a
|
||||||
|
variable length block of serialized data. The type identifies what the blob
|
||||||
|
contains. The fields are as follows:
|
||||||
|
|
||||||
|
* `mType`
|
||||||
|
|
||||||
## Module directory structure
|
An enumeration that determines what the blob holds. There are four
|
||||||
|
different types of objects stored.
|
||||||
|
|
||||||
nodestore
|
* **ledger**
|
||||||
|-api // Public Interface
|
|
||||||
|
|
A ledger header.
|
||||||
|-backend // Factory classes for various databases
|
|
||||||
|
|
|
||||||
|-impl // Private Implementation
|
|
||||||
|
|
|
||||||
|-test // Unit tests
|
|
||||||
|
|
||||||
The NodeStore class is a simple object that the Ledger uses to store entries. It has a enumeration type, a hash, a ledger index and a Blob which stores arbritary data.
|
* **transaction**
|
||||||
|
|
||||||
|
A signed transaction.
|
||||||
|
|
||||||
|
* **account node**
|
||||||
|
|
||||||
|
A node in a ledger's account state tree.
|
||||||
|
|
||||||
|
* **transaction node**
|
||||||
|
|
||||||
|
A node in a ledger's transaction tree.
|
||||||
|
|
||||||
|
* `mHash`
|
||||||
|
|
||||||
|
A 256-bit hash of the blob.
|
||||||
|
|
||||||
# Document WIP notes
|
* `mLedgerIndex`
|
||||||
|
|
||||||
|
An unsigned integer that uniquely identifies the ledger in which this
|
||||||
|
NodeObject appears.
|
||||||
|
|
||||||
If the MemoryFactory backend database is used, do we loose persistance?
|
* `mData`
|
||||||
|
|
||||||
|
A blob containing the payload. Stored in the following format.
|
||||||
|
|
||||||
|
|Byte | | |
|
||||||
|
|:------|:--------------------|:-------------------------|
|
||||||
|
|0...3 |ledger index |32-bit big endian integer |
|
||||||
|
|4...7 |reserved ledger index|32-bit big endian integer |
|
||||||
|
|8 |type |NodeObjectType enumeration|
|
||||||
|
|9...end|data |body of the object data |
|
||||||
|
---
|
||||||
|
The `NodeStore` provides an interface that stores, in a persistent database, a
|
||||||
|
collection of NodeObjects that rippled uses as its primary representation of
|
||||||
|
ledger entries. All ledger entries are stored as NodeObjects and as such, need
|
||||||
|
to be persisted between launches. If a NodeObject is accessed and is not in
|
||||||
|
memory, it will be retrieved from the database.
|
||||||
|
|
||||||
|
## Backend
|
||||||
|
|
||||||
|
The `NodeStore` implementation provides the `Backend` abstract interface,
|
||||||
|
which lets different key/value databases to be chosen at run-time. This allows
|
||||||
|
experimentation with different engines. Improvements in the performance of the
|
||||||
|
NodeStore are a constant area of research. The database can be specified in
|
||||||
|
the configuration file [node_db] section as follows.
|
||||||
|
|
||||||
|
One or more lines of key / value pairs
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
type=RocksDB
|
||||||
|
path=rocksdb
|
||||||
|
compression=1
|
||||||
|
```
|
||||||
|
Choices for 'type' (not case-sensitive)
|
||||||
|
|
||||||
|
* **HyperLevelDB**
|
||||||
|
|
||||||
|
An improved version of LevelDB (preferred).
|
||||||
|
|
||||||
|
* **LevelDB**
|
||||||
|
|
||||||
|
Google's LevelDB database (deprecated).
|
||||||
|
|
||||||
|
* **none**
|
||||||
|
|
||||||
|
Use no backend.
|
||||||
|
|
||||||
|
* **RocksDB**
|
||||||
|
|
||||||
|
Facebook's RocksDB database, builds on LevelDB.
|
||||||
|
|
||||||
|
* **SQLite**
|
||||||
|
|
||||||
|
Use SQLite.
|
||||||
|
|
||||||
|
'path' speficies where the backend will store its data files.
|
||||||
|
|
||||||
|
Choices for 'compression'
|
||||||
|
|
||||||
|
* **0** off
|
||||||
|
|
||||||
|
* **1** on (default)
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
|
|
||||||
/** A backend used for the store.
|
/** A backend used for the NodeStore.
|
||||||
|
|
||||||
The NodeStore uses a swappable backend so that other database systems
|
The NodeStore uses a swappable backend so that other database systems
|
||||||
can be tried. Different databases may offer various features such
|
can be tried. Different databases may offer various features such
|
||||||
|
|||||||
@@ -118,14 +118,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual int getWriteLoad () = 0;
|
virtual int getWriteLoad () = 0;
|
||||||
|
|
||||||
// VFALCO TODO Document this.
|
/** Get the positive cache hits to total attempts ratio. */
|
||||||
virtual float getCacheHitRate () = 0;
|
virtual float getCacheHitRate () = 0;
|
||||||
|
|
||||||
// VFALCO TODO Document this.
|
/** Set the maximum number of entries and maximum cache age for both caches.
|
||||||
// TODO Document the parameter meanings.
|
|
||||||
|
@param size Number of cache entries (0 = ignore)
|
||||||
|
@param age Maximum cache age in seconds
|
||||||
|
*/
|
||||||
virtual void tune (int size, int age) = 0;
|
virtual void tune (int size, int age) = 0;
|
||||||
|
|
||||||
// VFALCO TODO Document this.
|
/** Remove expired entries from the positive and negative caches. */
|
||||||
virtual void sweep () = 0;
|
virtual void sweep () = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,17 @@
|
|||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace NodeStore {
|
namespace NodeStore {
|
||||||
|
|
||||||
/** Singleton for managing NodeStore factories and back ends. */
|
/** Singleton for managing NodeStore factories and back ends.
|
||||||
|
Create a Manager like this:
|
||||||
|
@code
|
||||||
|
NodeStore::DummyScheduler scheduler;
|
||||||
|
std::unique_ptr <NodeStore::Manager> m (NodeStore::make_Manager());
|
||||||
|
|
||||||
|
std::unique_ptr <NodeStore::Database> nodeStore (m->make_Database ("nodeStore",
|
||||||
|
scheduler, LogPartition::getJournal <NodeObject> (), 4,
|
||||||
|
getConfig ().nodeDatabase));
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -45,7 +55,7 @@ public:
|
|||||||
virtual std::unique_ptr <Backend> make_Backend (Parameters const& parameters,
|
virtual std::unique_ptr <Backend> make_Backend (Parameters const& parameters,
|
||||||
Scheduler& scheduler, beast::Journal journal) = 0;
|
Scheduler& scheduler, beast::Journal journal) = 0;
|
||||||
|
|
||||||
/** Construct a node store database.
|
/** Construct a NodeStore database.
|
||||||
|
|
||||||
The parameters are key value pairs passed to the backend. The
|
The parameters are key value pairs passed to the backend. The
|
||||||
'type' key must exist, it defines the choice of backend. Most
|
'type' key must exist, it defines the choice of backend. Most
|
||||||
|
|||||||
@@ -34,13 +34,11 @@ enum NodeObjectType
|
|||||||
hotTRANSACTION_NODE = 4
|
hotTRANSACTION_NODE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A blob of data with associated metadata, referenced by hash.
|
/** A simple object that the Ledger uses to store entries.
|
||||||
|
NodeObjects are comprised of a type, a hash, a ledger index and a blob.
|
||||||
The metadata includes the following:
|
They can be uniquely identified by the hash, which is a SHA 256 of the
|
||||||
|
blob. The blob is a variable length block of serialized data. The type
|
||||||
- Type of the blob
|
identifies what the blob contains.
|
||||||
- The ledger index in which it appears
|
|
||||||
- The SHA 256 hash
|
|
||||||
|
|
||||||
@note No checking is performed to make sure the hash matches the data.
|
@note No checking is performed to make sure the hash matches the data.
|
||||||
@see SHAMap
|
@see SHAMap
|
||||||
@@ -107,8 +105,7 @@ public:
|
|||||||
|
|
||||||
/** Retrieve the ledger index in which this object appears.
|
/** Retrieve the ledger index in which this object appears.
|
||||||
*/
|
*/
|
||||||
// VFALCO TODO rename to getLedgerIndex or getLedgerId
|
LedgerIndex getLedgerIndex() const;
|
||||||
LedgerIndex getIndex () const;
|
|
||||||
|
|
||||||
/** Retrieve the binary data.
|
/** Retrieve the binary data.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ namespace NodeStore {
|
|||||||
|
|
||||||
@see Scheduler
|
@see Scheduler
|
||||||
*/
|
*/
|
||||||
// VFALCO NOTE I'm not entirely happy having placed this here,
|
|
||||||
// because whoever needs to use NodeStore certainly doesn't
|
|
||||||
// need to see the implementation details of BatchWriter.
|
|
||||||
//
|
|
||||||
class BatchWriter : private Task
|
class BatchWriter : private Task
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ EncodedBlob::prepare (NodeObject::Ptr const& object)
|
|||||||
m_data.ensureSize (m_size);
|
m_data.ensureSize (m_size);
|
||||||
|
|
||||||
// These sizes must be the same!
|
// These sizes must be the same!
|
||||||
static_bassert (sizeof (std::uint32_t) == sizeof (object->getIndex ()));
|
static_bassert (sizeof (std::uint32_t) == sizeof (object->getLedgerIndex ()));
|
||||||
|
|
||||||
{
|
{
|
||||||
std::uint32_t* buf = static_cast <std::uint32_t*> (m_data.getData ());
|
std::uint32_t* buf = static_cast <std::uint32_t*> (m_data.getData ());
|
||||||
|
|
||||||
buf [0] = beast::ByteOrder::swapIfLittleEndian (object->getIndex ());
|
buf [0] = beast::ByteOrder::swapIfLittleEndian (object->getLedgerIndex ());
|
||||||
buf [1] = beast::ByteOrder::swapIfLittleEndian (object->getIndex ());
|
buf [1] = beast::ByteOrder::swapIfLittleEndian (object->getLedgerIndex ());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,11 +26,9 @@ public:
|
|||||||
typedef std::vector <std::unique_ptr <Factory>> List;
|
typedef std::vector <std::unique_ptr <Factory>> List;
|
||||||
List m_list;
|
List m_list;
|
||||||
|
|
||||||
explicit ManagerImp (std::vector <std::unique_ptr <Factory>> factories)
|
explicit ManagerImp (std::vector <std::unique_ptr <Factory>>&& factories)
|
||||||
: m_list (std::move (factories))
|
: m_list (std::move (factories))
|
||||||
{
|
{
|
||||||
m_list.reserve (20);
|
|
||||||
|
|
||||||
add_known_factories ();
|
add_known_factories ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ NodeObject::getHash () const
|
|||||||
}
|
}
|
||||||
|
|
||||||
LedgerIndex
|
LedgerIndex
|
||||||
NodeObject::getIndex () const
|
NodeObject::getLedgerIndex () const
|
||||||
{
|
{
|
||||||
return mLedgerIndex;
|
return mLedgerIndex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public:
|
|||||||
Blob data (object->getData ());
|
Blob data (object->getData ());
|
||||||
|
|
||||||
db.store (object->getType (),
|
db.store (object->getType (),
|
||||||
object->getIndex (),
|
object->getLedgerIndex (),
|
||||||
std::move (data),
|
std::move (data),
|
||||||
object->getHash ());
|
object->getHash ());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1744,8 +1744,8 @@ private:
|
|||||||
if (obj.has_nodeid ())
|
if (obj.has_nodeid ())
|
||||||
newObj.set_index (obj.nodeid ());
|
newObj.set_index (obj.nodeid ());
|
||||||
|
|
||||||
if (!reply.has_seq () && (hObj->getIndex () != 0))
|
if (!reply.has_seq () && (hObj->getLedgerIndex () != 0))
|
||||||
reply.set_seq (hObj->getIndex ());
|
reply.set_seq (hObj->getLedgerIndex ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user