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