From a3264a291a08be10036565a2bfa73e145fea3e7f Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 23 Jul 2013 14:53:48 -0700 Subject: [PATCH] Add memory backend for node store --- Builds/VisualStudio2012/RippleD.vcxproj | 12 +- .../VisualStudio2012/RippleD.vcxproj.filters | 12 +- .../node/ripple_HyperLevelDBBackendFactory.h | 2 + .../node/ripple_KeyvaDBBackendFactory.h | 2 + .../node/ripple_LevelDBBackendFactory.h | 2 + .../node/ripple_MdbBackendFactory.h | 2 + .../node/ripple_MemoryBackendFactory.cpp | 113 ++++++++++++++++++ .../node/ripple_MemoryBackendFactory.h | 32 +++++ modules/ripple_app/node/ripple_NodeStore.cpp | 62 +++++----- .../node/ripple_NullBackendFactory.h | 2 + .../node/ripple_SqliteBackendFactory.h | 2 + modules/ripple_app/ripple_app.cpp | 2 + src/cpp/ripple/ripple_Main.cpp | 1 + 13 files changed, 206 insertions(+), 40 deletions(-) create mode 100644 modules/ripple_app/node/ripple_MemoryBackendFactory.cpp create mode 100644 modules/ripple_app/node/ripple_MemoryBackendFactory.h diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index bdf45f6cc1..c2a401321f 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -157,12 +157,6 @@ true true - - true - true - true - true - true true @@ -175,6 +169,10 @@ true true + + true + true + true true @@ -1415,9 +1413,9 @@ - + diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index beaa45d3af..866db09fc2 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -891,9 +891,6 @@ [1] Ripple\ripple_app\node - - [1] Ripple\ripple_app\node - [1] Ripple\ripple_app\node @@ -906,6 +903,9 @@ [0] Subtrees\beast + + [1] Ripple\ripple_app\node + @@ -1677,9 +1677,6 @@ [1] Ripple\ripple_app\node - - [1] Ripple\ripple_app\node - [1] Ripple\ripple_app\node @@ -1695,6 +1692,9 @@ [1] Ripple\ripple_core\functional + + [1] Ripple\ripple_app\node + diff --git a/modules/ripple_app/node/ripple_HyperLevelDBBackendFactory.h b/modules/ripple_app/node/ripple_HyperLevelDBBackendFactory.h index 43920477d8..b2f405d3bf 100644 --- a/modules/ripple_app/node/ripple_HyperLevelDBBackendFactory.h +++ b/modules/ripple_app/node/ripple_HyperLevelDBBackendFactory.h @@ -10,6 +10,8 @@ #if RIPPLE_HYPERLEVELDB_AVAILABLE /** Factory to produce HyperLevelDB backends for the NodeStore. + + @see NodeStore */ class HyperLevelDBBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/node/ripple_KeyvaDBBackendFactory.h b/modules/ripple_app/node/ripple_KeyvaDBBackendFactory.h index 40e76f1994..65d8700b28 100644 --- a/modules/ripple_app/node/ripple_KeyvaDBBackendFactory.h +++ b/modules/ripple_app/node/ripple_KeyvaDBBackendFactory.h @@ -8,6 +8,8 @@ #define RIPPLE_KEYVABACKENDFACTORY_H_INCLUDED /** Factory to produce KeyvaDB backends for the NodeStore. + + @see NodeStore */ class KeyvaDBBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/node/ripple_LevelDBBackendFactory.h b/modules/ripple_app/node/ripple_LevelDBBackendFactory.h index 3646125d1d..1ec1937856 100644 --- a/modules/ripple_app/node/ripple_LevelDBBackendFactory.h +++ b/modules/ripple_app/node/ripple_LevelDBBackendFactory.h @@ -8,6 +8,8 @@ #define RIPPLE_LEVELDBBACKENDFACTORY_H_INCLUDED /** Factory to produce LevelDB backends for the NodeStore. + + @see NodeStore */ class LevelDBBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/node/ripple_MdbBackendFactory.h b/modules/ripple_app/node/ripple_MdbBackendFactory.h index 2e1cd7db65..a05bef970a 100644 --- a/modules/ripple_app/node/ripple_MdbBackendFactory.h +++ b/modules/ripple_app/node/ripple_MdbBackendFactory.h @@ -12,6 +12,8 @@ /** Factory to produce a backend using MDB. @note MDB is not currently available for Win32 + + @see NodeStore */ class MdbBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/node/ripple_MemoryBackendFactory.cpp b/modules/ripple_app/node/ripple_MemoryBackendFactory.cpp new file mode 100644 index 0000000000..3a379c3a5e --- /dev/null +++ b/modules/ripple_app/node/ripple_MemoryBackendFactory.cpp @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +class MemoryBackendFactory::Backend : public NodeStore::Backend +{ +private: + typedef std::map Map; + +public: + Backend (size_t keyBytes, StringPairArray const& keyValues) + : m_keyBytes (keyBytes) + { + } + + ~Backend () + { + } + + std::string getName () + { + return "memory"; + } + + //-------------------------------------------------------------------------- + + Status fetch (void const* key, NodeObject::Ptr* pObject) + { + uint256 const hash (key); + + Map::iterator iter = m_map.find (hash); + + if (iter != m_map.end ()) + { + *pObject = iter->second; + } + else + { + pObject->reset (); + } + + return ok; + } + + void store (NodeObject::ref object) + { + Map::iterator iter = m_map.find (object->getHash ()); + + if (iter == m_map.end ()) + { + m_map.insert (std::make_pair (object->getHash (), object)); + } + } + + void storeBatch (NodeStore::Batch const& batch) + { + for (int i = 0; i < batch.size (); ++i) + store (batch [i]); + } + + void visitAll (VisitCallback& callback) + { + for (Map::const_iterator iter = m_map.begin (); iter != m_map.end (); ++iter) + callback.visitObject (iter->second); + } + + int getWriteLoad () + { + return 0; + } + + //-------------------------------------------------------------------------- + +private: + size_t const m_keyBytes; + + Map m_map; +}; + +//------------------------------------------------------------------------------ + +MemoryBackendFactory::MemoryBackendFactory () +{ +} + +MemoryBackendFactory::~MemoryBackendFactory () +{ +} + +MemoryBackendFactory& MemoryBackendFactory::getInstance () +{ + static MemoryBackendFactory instance; + + return instance; +} + +String MemoryBackendFactory::getName () const +{ + return "Memory"; +} + +NodeStore::Backend* MemoryBackendFactory::createInstance ( + size_t keyBytes, + StringPairArray const& keyValues, + NodeStore::Scheduler& scheduler) +{ + return new MemoryBackendFactory::Backend (keyBytes, keyValues); +} + +//------------------------------------------------------------------------------ + diff --git a/modules/ripple_app/node/ripple_MemoryBackendFactory.h b/modules/ripple_app/node/ripple_MemoryBackendFactory.h new file mode 100644 index 0000000000..a548b16cb5 --- /dev/null +++ b/modules/ripple_app/node/ripple_MemoryBackendFactory.h @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +/* + Copyright (c) 2011-2013, OpenCoin, Inc. +*/ +//============================================================================== + +#ifndef RIPPLE_MEMORYBACKENDFACTORY_H_INCLUDED +#define RIPPLE_MEMORYBACKENDFACTORY_H_INCLUDED + +/** Factory to produce a RAM based backend for the NodeStore. + + @see NodeStore +*/ +class MemoryBackendFactory : public NodeStore::BackendFactory +{ +private: + class Backend; + + MemoryBackendFactory (); + ~MemoryBackendFactory (); + +public: + static MemoryBackendFactory& getInstance (); + + String getName () const; + + NodeStore::Backend* createInstance (size_t keyBytes, + StringPairArray const& keyValues, + NodeStore::Scheduler& scheduler); +}; + +#endif diff --git a/modules/ripple_app/node/ripple_NodeStore.cpp b/modules/ripple_app/node/ripple_NodeStore.cpp index b0ddd751d7..61b05b9dd7 100644 --- a/modules/ripple_app/node/ripple_NodeStore.cpp +++ b/modules/ripple_app/node/ripple_NodeStore.cpp @@ -1043,7 +1043,10 @@ public: //-------------------------------------------------------------------------- - void testNodeStore (String type, bool const useEphemeralDatabase, int64 const seedValue) + void testNodeStore (String type, + bool const useEphemeralDatabase, + bool const testPersistence, + int64 const seedValue) { String s; s << String ("NodeStore backend '") + type + "'"; @@ -1092,33 +1095,36 @@ public: } } + if (testPersistence) { - // Re-open the database without the ephemeral DB - ScopedPointer db (NodeStore::New (nodeParams)); + { + // Re-open the database without the ephemeral DB + ScopedPointer db (NodeStore::New (nodeParams)); - // Read it back in - NodeStore::Batch copy; - fetchCopyOfBatch (*db, ©, batch); + // Read it back in + NodeStore::Batch copy; + fetchCopyOfBatch (*db, ©, batch); - // Canonicalize the source and destination batches - std::sort (batch.begin (), batch.end (), NodeObject::LessThan ()); - std::sort (copy.begin (), copy.end (), NodeObject::LessThan ()); - expect (areBatchesEqual (batch, copy), "Should be equal"); - } + // Canonicalize the source and destination batches + std::sort (batch.begin (), batch.end (), NodeObject::LessThan ()); + std::sort (copy.begin (), copy.end (), NodeObject::LessThan ()); + expect (areBatchesEqual (batch, copy), "Should be equal"); + } - if (useEphemeralDatabase) - { - // Verify the ephemeral db - ScopedPointer db (NodeStore::New (tempParams, StringPairArray ())); + if (useEphemeralDatabase) + { + // Verify the ephemeral db + ScopedPointer db (NodeStore::New (tempParams, StringPairArray ())); - // Read it back in - NodeStore::Batch copy; - fetchCopyOfBatch (*db, ©, batch); + // Read it back in + NodeStore::Batch copy; + fetchCopyOfBatch (*db, ©, batch); - // Canonicalize the source and destination batches - std::sort (batch.begin (), batch.end (), NodeObject::LessThan ()); - std::sort (copy.begin (), copy.end (), NodeObject::LessThan ()); - expect (areBatchesEqual (batch, copy), "Should be equal"); + // Canonicalize the source and destination batches + std::sort (batch.begin (), batch.end (), NodeObject::LessThan ()); + std::sort (copy.begin (), copy.end (), NodeObject::LessThan ()); + expect (areBatchesEqual (batch, copy), "Should be equal"); + } } } @@ -1126,18 +1132,18 @@ public: void runBackendTests (bool useEphemeralDatabase, int64 const seedValue) { - testNodeStore ("keyvadb", useEphemeralDatabase, seedValue); + testNodeStore ("keyvadb", useEphemeralDatabase, true, seedValue); - testNodeStore ("leveldb", useEphemeralDatabase, seedValue); + testNodeStore ("leveldb", useEphemeralDatabase, true, seedValue); - testNodeStore ("sqlite", useEphemeralDatabase, seedValue); + testNodeStore ("sqlite", useEphemeralDatabase, true, seedValue); #if RIPPLE_HYPERLEVELDB_AVAILABLE - testNodeStore ("hyperleveldb", useEphemeralDatabase, seedValue); + testNodeStore ("hyperleveldb", useEphemeralDatabase, true, seedValue); #endif #if RIPPLE_MDB_AVAILABLE - testNodeStore ("mdb", useEphemeralDatabase, seedValue); + testNodeStore ("mdb", useEphemeralDatabase, true, seedValue); #endif } @@ -1166,6 +1172,8 @@ public: { int64 const seedValue = 50; + testNodeStore ("memory", false, false, seedValue); + runBackendTests (false, seedValue); runBackendTests (true, seedValue); diff --git a/modules/ripple_app/node/ripple_NullBackendFactory.h b/modules/ripple_app/node/ripple_NullBackendFactory.h index a68c1838ea..b406336801 100644 --- a/modules/ripple_app/node/ripple_NullBackendFactory.h +++ b/modules/ripple_app/node/ripple_NullBackendFactory.h @@ -10,6 +10,8 @@ /** Factory to produce a null backend. This is for standalone / testing mode. + + @see NodeStore */ class NullBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/node/ripple_SqliteBackendFactory.h b/modules/ripple_app/node/ripple_SqliteBackendFactory.h index 828588fd74..0b1c373809 100644 --- a/modules/ripple_app/node/ripple_SqliteBackendFactory.h +++ b/modules/ripple_app/node/ripple_SqliteBackendFactory.h @@ -8,6 +8,8 @@ #define RIPPLE_SQLITEBACKENDFACTORY_H_INCLUDED /** Factory to produce SQLite backends for the NodeStore. + + @see NodeStore */ class SqliteBackendFactory : public NodeStore::BackendFactory { diff --git a/modules/ripple_app/ripple_app.cpp b/modules/ripple_app/ripple_app.cpp index ae84625c3b..992f925443 100644 --- a/modules/ripple_app/ripple_app.cpp +++ b/modules/ripple_app/ripple_app.cpp @@ -108,6 +108,7 @@ namespace ripple #include "node/ripple_KeyvaDBBackendFactory.h" #include "node/ripple_LevelDBBackendFactory.h" #include "node/ripple_MdbBackendFactory.h" +#include "node/ripple_MemoryBackendFactory.h" #include "node/ripple_NullBackendFactory.h" #include "node/ripple_SqliteBackendFactory.h" @@ -250,6 +251,7 @@ static const uint64 tenTo17m1 = tenTo17 - 1; #include "node/ripple_HyperLevelDBBackendFactory.cpp" #include "node/ripple_KeyvaDBBackendFactory.cpp" #include "node/ripple_LevelDBBackendFactory.cpp" +#include "node/ripple_MemoryBackendFactory.cpp" #include "node/ripple_NullBackendFactory.cpp" #include "node/ripple_MdbBackendFactory.cpp" #include "node/ripple_SqliteBackendFactory.cpp" diff --git a/src/cpp/ripple/ripple_Main.cpp b/src/cpp/ripple/ripple_Main.cpp index 598962ebf8..cdb1bf68f8 100644 --- a/src/cpp/ripple/ripple_Main.cpp +++ b/src/cpp/ripple/ripple_Main.cpp @@ -259,6 +259,7 @@ int rippleMain (int argc, char** argv) // These must be added before the Application object is created NodeStore::addBackendFactory (KeyvaDBBackendFactory::getInstance ()); NodeStore::addBackendFactory (LevelDBBackendFactory::getInstance ()); + NodeStore::addBackendFactory (MemoryBackendFactory::getInstance ()); NodeStore::addBackendFactory (NullBackendFactory::getInstance ()); NodeStore::addBackendFactory (SqliteBackendFactory::getInstance ()); #if RIPPLE_HYPERLEVELDB_AVAILABLE