Fix and tidy up NodeStore

* Use std::unique_ptr
* Move globals to Manager singleton (fixes RocksDB exit crash)
This commit is contained in:
Vinnie Falco
2014-01-17 11:58:55 -05:00
parent c341d1a71e
commit 7570b6489d
50 changed files with 842 additions and 640 deletions

View File

@@ -1545,12 +1545,24 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Backend.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="..\..\src\ripple_core\nodestore\impl\BatchWriter.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="..\..\src\ripple_core\nodestore\impl\Database.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="..\..\src\ripple_core\nodestore\impl\DecodedBlob.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -1569,12 +1581,36 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Factory.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="..\..\src\ripple_core\nodestore\impl\Manager.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="..\..\src\ripple_core\nodestore\impl\NodeObject.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="..\..\src\ripple_core\nodestore\impl\Scheduler.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="..\..\src\ripple_core\nodestore\impl\Task.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="..\..\src\ripple_core\nodestore\NodeStore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -2490,6 +2526,7 @@
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Database.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\DummyScheduler.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Factory.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Manager.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\NodeObject.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Scheduler.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Task.h" />
@@ -2504,7 +2541,7 @@
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\DatabaseImp.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\DecodedBlob.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\EncodedBlob.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\Factories.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\Tuning.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\NodeStore.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\tests\TestBase.h" />
<ClInclude Include="..\..\src\ripple_core\ripple_core.h" />

View File

@@ -1419,6 +1419,24 @@
<ClCompile Include="..\..\src\ripple_basics\containers\KeyCache.cpp">
<Filter>[2] Old Ripple\ripple_basics\containers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Backend.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Factory.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Scheduler.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Task.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Database.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple_core\nodestore\impl\Manager.cpp">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ripple_basics\containers\KeyCache.h">
@@ -2262,9 +2280,6 @@
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Factory.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\api</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\Factories.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\api\VisitCallback.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\api</Filter>
</ClInclude>
@@ -2283,9 +2298,6 @@
<ClInclude Include="..\..\src\ripple_core\nodestore\tests\TestBase.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\DatabaseImp.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Task.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\api</Filter>
</ClInclude>
@@ -2895,6 +2907,15 @@
<ClInclude Include="..\..\src\ripple_core\nodestore\backend\RocksDBFactory.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\backend</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Manager.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\api</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\DatabaseImp.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\Tuning.h">
<Filter>[2] Old Ripple\ripple_core\nodestore\impl</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\src\ripple_data\protocol\ripple.proto">

View File

@@ -68,6 +68,8 @@ public:
Application::LockType m_masterMutex;
// These are not Stoppable-derived
std::unique_ptr <NodeStore::Manager> m_nodeStoreManager;
NodeCache m_tempNodeCache;
SLECache m_sleCache;
LocalCredentials m_localCredentials;
@@ -166,12 +168,27 @@ public:
}
};
static std::vector <std::unique_ptr <NodeStore::Factory>> make_Factories ()
{
std::vector <std::unique_ptr <NodeStore::Factory>> list;
// VFALCO NOTE SqliteFactory is here because it has
// dependencies like SqliteDatabase and DatabaseCon
//
list.emplace_back (make_SqliteFactory ());
return list;
}
//--------------------------------------------------------------------------
ApplicationImp ()
: RootStoppable ("Application")
, m_journal (LogPartition::getJournal <ApplicationLog> ())
, m_nodeStoreManager (NodeStore::make_Manager (
std::move (make_Factories ())))
, m_tempNodeCache ("NodeCache", 16384, 90,
get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (),
LogPartition::getJournal <TaggedCacheLog> ())
@@ -233,7 +250,7 @@ public:
#if ! RIPPLE_USE_RPC_SERVICE_MANAGER
, m_rpcServerHandler (*m_networkOPs, *m_resourceManager) // passive object, not a Service
#endif
, m_nodeStore (NodeStore::Database::New ("NodeStore.main", m_nodeStoreScheduler,
, m_nodeStore (m_nodeStoreManager->make_Database ("NodeStore.main", m_nodeStoreScheduler,
LogPartition::getJournal <NodeObject> (),
getConfig ().nodeDatabase, getConfig ().ephemeralNodeDatabase))
@@ -1335,8 +1352,9 @@ void ApplicationImp::updateTables ()
if (getConfig ().doImport)
{
NodeStore::DummyScheduler scheduler;
std::unique_ptr <NodeStore::Database> source (NodeStore::Database::New (
"NodeStore.import", scheduler, LogPartition::getJournal <NodeObject> (),
std::unique_ptr <NodeStore::Database> source (
m_nodeStoreManager->make_Database ("NodeStore.import", scheduler,
LogPartition::getJournal <NodeObject> (),
getConfig ().importNodeDatabase));
WriteLog (lsWARNING, NodeObject) <<

View File

@@ -292,16 +292,6 @@ int RippleMain::run (int argc, char const* const* argv)
po::positional_options_description p;
p.add ("parameters", -1);
// NOTE: These must be added before the
// Application object is created.
//
NodeStore::Database::addAvailableBackends ();
// VFALCO NOTE SqliteFactory is here because it has
// dependencies like SqliteDatabase and DatabaseCon
//
NodeStore::Database::addFactory (SqliteFactory::getInstance ());
if (! RandomNumbers::getInstance ().initialize ())
{
Log::out() << "Unable to add system entropy";

View File

@@ -43,10 +43,10 @@ static int s_nodeStoreDBCount = NUMBER (s_nodeStoreDBInit);
//------------------------------------------------------------------------------
class SqliteFactory::BackendImp : public NodeStore::Backend
class SqliteBackend : public NodeStore::Backend
{
public:
BackendImp (size_t keyBytes, std::string const& path, NodeStore::Scheduler& scheduler)
SqliteBackend (size_t keyBytes, std::string const& path, NodeStore::Scheduler& scheduler)
: m_keyBytes (keyBytes)
, m_name (path)
, m_db (new DatabaseCon(path, s_nodeStoreDBInit, s_nodeStoreDBCount))
@@ -60,7 +60,7 @@ public:
m_db->getDB()->executeSQL (s.toStdString ().c_str ());
}
~BackendImp()
~SqliteBackend()
{
}
@@ -224,29 +224,26 @@ private:
//------------------------------------------------------------------------------
SqliteFactory::SqliteFactory ()
class SqliteFactory : public NodeStore::Factory
{
}
SqliteFactory::~SqliteFactory ()
{
}
SqliteFactory* SqliteFactory::getInstance ()
{
return new SqliteFactory;
}
String SqliteFactory::getName () const
public:
String getName () const
{
return "Sqlite";
}
NodeStore::Backend* SqliteFactory::createInstance (
size_t keyBytes,
NodeStore::Parameters const& keyValues,
NodeStore::Scheduler& scheduler,
Journal)
std::unique_ptr <NodeStore::Backend> createInstance (
size_t keyBytes, NodeStore::Parameters const& keyValues,
NodeStore::Scheduler& scheduler, Journal)
{
return new BackendImp (keyBytes, keyValues ["path"].toStdString (), scheduler);
return std::make_unique <SqliteBackend> (
keyBytes, keyValues ["path"].toStdString (), scheduler);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <NodeStore::Factory> make_SqliteFactory ()
{
return std::make_unique <SqliteFactory> ();
}

View File

@@ -21,26 +21,8 @@
#define RIPPLE_APP_SQLITEFACTORY_H_INCLUDED
/** Factory to produce SQLite backends for the NodeStore.
@see Database
*/
class SqliteFactory : public NodeStore::Factory
{
private:
SqliteFactory ();
~SqliteFactory ();
public:
class BackendImp;
static SqliteFactory* getInstance ();
String getName () const;
NodeStore::Backend* createInstance (size_t keyBytes,
NodeStore::Parameters const& keyValues,
NodeStore::Scheduler& scheduler,
Journal journal);
};
std::unique_ptr <NodeStore::Factory> make_SqliteFactory ();
#endif

View File

@@ -62,6 +62,9 @@ namespace ripple {
# include "main/FatalErrorReporter.h"
#include "main/FatalErrorReporter.cpp"
# include "node/SqliteFactory.h"
#include "node/SqliteFactory.cpp"
# include "peers/PeerDoor.h"
#include "peers/PeerDoor.cpp"
@@ -94,8 +97,6 @@ namespace ripple {
// RippleMain
//
# include "main/RippleMain.h"
# include "node/SqliteFactory.h"
#include "node/SqliteFactory.cpp"
#include "main/RippleMain.cpp"
}

View File

@@ -17,13 +17,17 @@
*/
//==============================================================================
#include <memory>
#include <vector>
// backend support
#include "../ripple_hyperleveldb/ripple_hyperleveldb.h"
#include "../ripple_leveldb/ripple_leveldb.h"
#include "../ripple/rocksdb/ripple_rocksdb.h"
namespace ripple {
#include "beast/beast/make_unique.h"
#include "impl/Tuning.h"
# include "impl/DecodedBlob.h"
# include "impl/EncodedBlob.h"
# include "impl/BatchWriter.h"
@@ -38,18 +42,21 @@ namespace ripple {
# include "backend/RocksDBFactory.h"
#include "backend/RocksDBFactory.cpp"
#include "impl/Backend.cpp"
#include "impl/BatchWriter.cpp"
# include "impl/Factories.h"
# include "impl/DatabaseImp.h"
#include "impl/Database.cpp"
#include "impl/DummyScheduler.cpp"
#include "impl/DecodedBlob.cpp"
#include "impl/EncodedBlob.cpp"
#include "impl/Factory.cpp"
#include "impl/Manager.cpp"
#include "impl/NodeObject.cpp"
#include "impl/Scheduler.cpp"
#include "impl/Task.cpp"
# include "tests/TestBase.h"
#include "tests/BackendTests.cpp"
#include "tests/BasicTests.cpp"
#include "tests/DatabaseTests.cpp"
#include "tests/TimingTests.cpp"
}

View File

@@ -20,9 +20,6 @@
#ifndef RIPPLE_NODESTORE_H_INCLUDED
#define RIPPLE_NODESTORE_H_INCLUDED
namespace ripple
{
#include "api/NodeObject.h"
#include "api/Types.h"
#include "api/VisitCallback.h"
@@ -32,7 +29,6 @@ namespace ripple
#include "api/DummyScheduler.h"
#include "api/Factory.h"
#include "api/Database.h"
}
#include "api/Manager.h"
#endif

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_BACKEND_H_INCLUDED
#define RIPPLE_NODESTORE_BACKEND_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** A backend used for the store.
@@ -41,61 +41,52 @@ public:
or other tasks scheduled, they will be completed before this call
returns.
*/
virtual ~Backend () { }
virtual ~Backend () = 0;
/** Get the human-readable name of this backend.
This is used for diagnostic output.
*/
virtual std::string getName() = 0;
/** Fetch a single object.
If the object is not found or an error is encountered, the
result will indicate the condition.
@note This will be called concurrently.
@param key A pointer to the key data.
@param pObject [out] The created object if successful.
@return The result of the operation.
*/
virtual Status fetch (void const* key, NodeObject::Ptr* pObject) = 0;
/** Store a single object.
Depending on the implementation this may happen immediately
or deferred using a scheduled task.
@note This will be called concurrently.
@param object The object to store.
*/
virtual void store (NodeObject::Ptr const& object) = 0;
/** Store a group of objects.
@note This function will not be called concurrently with
itself or @ref store.
*/
virtual void storeBatch (Batch const& batch) = 0;
/** Visit every object in the database
This is usually called during import.
@note This routine will not be called concurrently with itself
or other methods.
@see import, VisitCallback
*/
virtual void visitAll (VisitCallback& callback) = 0;
// VFALCO TODO Implement
//virtual void visitAll (std::function <void (NodeObject::Ptr)> f) = 0;
/** Estimate the number of write operations pending. */
virtual int getWriteLoad () = 0;
};
}
}
#endif

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASE_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Persistency layer for NodeObject
@@ -39,40 +39,11 @@ namespace NodeStore
class Database
{
public:
/** Construct a node store database.
The parameters are key value pairs passed to the backend. The
'type' key must exist, it defines the choice of backend. Most
backends also require a 'path' field.
Some choices for 'type' are:
HyperLevelDB, LevelDBFactory, SQLite, MDB
If the fastBackendParameter is omitted or empty, no ephemeral database
is used. If the scheduler parameter is omited or unspecified, a
synchronous scheduler is used which performs all tasks immediately on
the caller's thread.
@note If the database cannot be opened or created, an exception is thrown.
@param name A diagnostic label for the database.
@param scheduler The scheduler to use for performing asynchronous tasks.
@param backendParameters The parameter string for the persistent backend.
@param fastBackendParameters [optional] The parameter string for the ephemeral backend.
@return The opened database.
*/
static Database* New (char const* name,
Scheduler& scheduler,
Journal journal,
Parameters const& backendParameters,
Parameters fastBackendParameters = Parameters ());
/** Destroy the node store.
All pending operations are completed, pending writes flushed,
and files closed before this returns.
*/
virtual ~Database () { }
virtual ~Database () = 0 ;
/** Retrieve the name associated with this backend.
This is used for diagnostics and may not reflect the actual path
@@ -80,14 +51,6 @@ public:
*/
virtual String getName () const = 0;
/** Add the specified backend factory to the list of available factories.
The names of available factories are compared against the "type"
value in the parameter list on construction. Ownership of the object
is transferred. The object must be allocated using new.
@param factory The factory to add.
*/
static void addFactory (Factory* factory);
/** Fetch an object.
If the object is known to be not in the database, isn't found in the
database during the fetch, or failed to load correctly during the fetch,
@@ -142,12 +105,9 @@ public:
// VFALCO TODO Document this.
virtual void sweep () = 0;
/** Add the known Backend factories to the singleton.
*/
static void addAvailableBackends ();
};
}
}
#endif

View File

@@ -20,22 +20,20 @@
#ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#define RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
// Simple Scheduler that just peforms the tasks synchronously.
/** Simple NodeStore Scheduler that just peforms the tasks synchronously. */
class DummyScheduler : public Scheduler
{
public:
DummyScheduler ();
~DummyScheduler ();
void scheduleTask (Task& task);
void scheduledTasksStopped ();
};
}
}
#endif

View File

@@ -20,32 +20,30 @@
#ifndef RIPPLE_NODESTORE_FACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_FACTORY_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Factory to produce backends. */
class Factory
{
public:
virtual ~Factory () { }
virtual ~Factory () = 0;
/** Retrieve the name of this factory. */
virtual String getName () const = 0;
/** Create an instance of this factory's backend.
@param keyBytes The fixed number of bytes per key.
@param keyValues A set of key/value configuration pairs.
@param scheduler The scheduler to use for running tasks.
@return A pointer to the Backend object.
*/
virtual Backend* createInstance (size_t keyBytes,
Parameters const& parameters,
Scheduler& scheduler,
virtual std::unique_ptr <Backend> createInstance (size_t keyBytes,
Parameters const& parameters, Scheduler& scheduler,
Journal journal) = 0;
};
}
}
#endif

View File

@@ -0,0 +1,89 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_NODESTORE_MANAGER_H_INCLUDED
#define RIPPLE_NODESTORE_MANAGER_H_INCLUDED
namespace ripple {
namespace NodeStore {
/** Singleton for managing NodeStore factories and back ends. */
class Manager
{
public:
virtual ~Manager () = 0;
/** Add the specified factory to the manager.
Thread safety:
Not thread-safe.
*/
virtual void add_factory (std::unique_ptr <Factory> factory) = 0;
/** Return a pointer to the matching factory if it exists.
@param name The name to match, performed case-insensitive.
@return `nullptr` if a match was not found.
*/
virtual Factory* find (std::string const& name) const = 0;
/** Create a backend. */
virtual std::unique_ptr <Backend> make_Backend (Parameters const& parameters,
Scheduler& scheduler, Journal journal) = 0;
/** Construct a node store database.
The parameters are key value pairs passed to the backend. The
'type' key must exist, it defines the choice of backend. Most
backends also require a 'path' field.
Some choices for 'type' are:
HyperLevelDB, LevelDBFactory, SQLite, MDB
If the fastBackendParameter is omitted or empty, no ephemeral database
is used. If the scheduler parameter is omited or unspecified, a
synchronous scheduler is used which performs all tasks immediately on
the caller's thread.
@note If the database cannot be opened or created, an exception is thrown.
@param name A diagnostic label for the database.
@param scheduler The scheduler to use for performing asynchronous tasks.
@param backendParameters The parameter string for the persistent backend.
@param fastBackendParameters [optional] The parameter string for the ephemeral backend.
@return The opened database.
*/
virtual std::unique_ptr <Database> make_Database (std::string const& name,
Scheduler& scheduler, Journal journal,
Parameters const& backendParameters,
Parameters fastBackendParameters = Parameters ()) = 0;
};
//------------------------------------------------------------------------------
/** Create a Manager.
@param factories An optional array of additional factories to add.
*/
std::unique_ptr <Manager> make_Manager (
std::vector <std::unique_ptr <Factory>> factories =
std::vector <std::unique_ptr <Factory>>() );
}
}
#endif

View File

@@ -22,7 +22,7 @@
// VFALCO NOTE Intentionally not in the NodeStore namespace
namespace ripple {
/** The types of node objects. */
enum NodeObjectType
@@ -148,4 +148,6 @@ private:
Blob mData;
};
}
#endif

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
#define RIPPLE_NODESTORE_SCHEDULER_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Scheduling for asynchronous backend activity
@@ -34,7 +34,7 @@ namespace NodeStore
class Scheduler
{
public:
virtual ~Scheduler() { }
virtual ~Scheduler() = 0;
/** Schedules a task.
Depending on the implementation, the task may be invoked either on
@@ -44,6 +44,7 @@ public:
virtual void scheduleTask (Task& task) = 0;
};
}
}
#endif

View File

@@ -20,13 +20,13 @@
#ifndef RIPPLE_NODESTORE_TASK_H_INCLUDED
#define RIPPLE_NODESTORE_TASK_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Derived classes perform scheduled tasks. */
struct Task
{
virtual ~Task () { }
virtual ~Task () = 0;
/** Performs the task.
The call may take place on a foreign thread.
@@ -34,6 +34,7 @@ struct Task
virtual void performScheduledTask () = 0;
};
}
}
#endif

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_TYPES_H_INCLUDED
#define RIPPLE_NODESTORE_TYPES_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
enum
{
@@ -46,8 +46,10 @@ enum Status
typedef std::vector <NodeObject::Ptr> Batch;
/** A list of key/value parameter pairs passed to the backend. */
// VFALCO TODO Use std::string, pair, vector
typedef StringPairArray Parameters;
}
}
#endif

View File

@@ -20,18 +20,20 @@
#ifndef RIPPLE_NODESTORE_VISITCALLBACK_H_INCLUDED
#define RIPPLE_NODESTORE_VISITCALLBACK_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Callback for iterating through objects.
@see visitAll
*/
// VFALCO DEPRECATED Use std::function instead
struct VisitCallback
{
virtual void visitObject (NodeObject::Ptr const& object) = 0;
};
}
}
#endif

View File

@@ -19,19 +19,26 @@
#if RIPPLE_HYPERLEVELDB_AVAILABLE
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class HyperDBFactory::BackendImp
class HyperDBBackend
: public Backend
, public BatchWriter::Callback
, public LeakChecked <HyperDBFactory::BackendImp>
, public LeakChecked <HyperDBBackend>
{
public:
BackendImp (size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler)
: m_keyBytes (keyBytes)
Journal m_journal;
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
std::string m_name;
std::unique_ptr <hyperleveldb::DB> m_db;
HyperDBBackend (size_t keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal)
: m_journal (journal)
, m_keyBytes (keyBytes)
, m_scheduler (scheduler)
, m_batch (*this, scheduler)
, m_name (keyValues ["path"].toStdString ())
@@ -69,12 +76,13 @@ public:
hyperleveldb::DB* db = nullptr;
hyperleveldb::Status status = hyperleveldb::DB::Open (options, m_name, &db);
if (!status.ok () || !db)
Throw (std::runtime_error (std::string("Unable to open/create leveldb: ") + status.ToString()));
Throw (std::runtime_error (std::string (
"Unable to open/create hyperleveldb: ") + status.ToString()));
m_db = db;
m_db.reset (db);
}
~BackendImp ()
~HyperDBBackend ()
{
}
@@ -143,6 +151,7 @@ public:
EncodedBlob encoded;
// VFALCO Use range based for
BOOST_FOREACH (NodeObject::ref object, batch)
{
encoded.prepare (object);
@@ -163,7 +172,7 @@ public:
{
hyperleveldb::ReadOptions const options;
ScopedPointer <hyperleveldb::Iterator> it (m_db->NewIterator (options));
std::unique_ptr <hyperleveldb::Iterator> it (m_db->NewIterator (options));
for (it->SeekToFirst (); it->Valid (); it->Next ())
{
@@ -181,14 +190,16 @@ public:
else
{
// Uh oh, corrupted data!
WriteLog (lsFATAL, NodeObject) << "Corrupt NodeObject #" << uint256::fromVoid (it->key ().data ());
m_journal.fatal <<
"Corrupt NodeObject #" << uint256::fromVoid (it->key ().data ());
}
}
else
{
// VFALCO NOTE What does it mean to find an
// incorrectly sized key? Corruption?
WriteLog (lsFATAL, NodeObject) << "Bad key size = " << it->key ().size ();
m_journal.fatal <<
"Bad key size = " << it->key ().size ();
}
}
}
@@ -204,44 +215,34 @@ public:
{
storeBatch (batch);
}
private:
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
std::string m_name;
ScopedPointer <hyperleveldb::DB> m_db;
};
//------------------------------------------------------------------------------
HyperDBFactory::HyperDBFactory ()
class HyperDBFactory : public NodeStore::Factory
{
}
HyperDBFactory::~HyperDBFactory ()
{
}
HyperDBFactory* HyperDBFactory::getInstance ()
{
return new HyperDBFactory;
}
String HyperDBFactory::getName () const
public:
String getName () const
{
return "HyperLevelDB";
}
Backend* HyperDBFactory::createInstance (
size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
std::unique_ptr <Backend> createInstance (size_t keyBytes,
Parameters const& keyValues, Scheduler& scheduler, Journal journal)
{
return new HyperDBFactory::BackendImp (keyBytes, keyValues, scheduler);
return std::make_unique <HyperDBBackend> (
keyBytes, keyValues, scheduler, journal);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <Factory> make_HyperDBFactory ()
{
return std::make_unique <HyperDBFactory> ();
}
}
}
#endif

View File

@@ -22,32 +22,15 @@
#if RIPPLE_HYPERLEVELDB_AVAILABLE
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Factory to produce HyperLevelDB backends for the NodeStore.
@see Database
*/
class HyperDBFactory : public NodeStore::Factory
{
private:
HyperDBFactory ();
~HyperDBFactory ();
public:
class BackendImp;
static HyperDBFactory* getInstance ();
String getName () const;
NodeStore::Backend* createInstance (size_t keyBytes,
Parameters const& keyValues,
NodeStore::Scheduler& scheduler,
Journal journal);
};
std::unique_ptr <Factory> make_HyperDBFactory ();
}
}
#endif

View File

@@ -17,19 +17,27 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class LevelDBFactory::BackendImp
class LevelDBBackend
: public Backend
, public BatchWriter::Callback
, public LeakChecked <LevelDBFactory::BackendImp>
, public LeakChecked <LevelDBBackend>
{
public:
BackendImp (int keyBytes,
Parameters const& keyValues,
Scheduler& scheduler)
: m_keyBytes (keyBytes)
Journal m_journal;
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
StringPool m_stringPool;
std::string m_name;
std::unique_ptr <leveldb::DB> m_db;
LevelDBBackend (int keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal)
: m_journal (journal)
, m_keyBytes (keyBytes)
, m_scheduler (scheduler)
, m_batch (*this, scheduler)
, m_name (keyValues ["path"].toStdString ())
@@ -69,11 +77,7 @@ public:
if (!status.ok () || !db)
Throw (std::runtime_error (std::string("Unable to open/create leveldb: ") + status.ToString()));
m_db = db;
}
~BackendImp ()
{
m_db.reset (db);
}
std::string getName()
@@ -160,7 +164,7 @@ public:
{
leveldb::ReadOptions const options;
ScopedPointer <leveldb::Iterator> it (m_db->NewIterator (options));
std::unique_ptr <leveldb::Iterator> it (m_db->NewIterator (options));
for (it->SeekToFirst (); it->Valid (); it->Next ())
{
@@ -202,52 +206,49 @@ public:
{
storeBatch (batch);
}
private:
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
StringPool m_stringPool;
std::string m_name;
ScopedPointer <leveldb::DB> m_db;
};
//------------------------------------------------------------------------------
LevelDBFactory::LevelDBFactory ()
class LevelDBFactory : public Factory
{
public:
std::unique_ptr <leveldb::Cache> m_lruCache;
class BackendImp;
LevelDBFactory ()
: m_lruCache (nullptr)
{
leveldb::Options options;
options.create_if_missing = true;
options.block_cache = leveldb::NewLRUCache (
getConfig ().getSize (siHashNodeDBCache) * 1024 * 1024);
m_lruCache = options.block_cache;
m_lruCache.reset (options.block_cache);
}
LevelDBFactory::~LevelDBFactory ()
{
leveldb::Cache* cache (reinterpret_cast <leveldb::Cache*> (m_lruCache));
delete cache;
}
LevelDBFactory* LevelDBFactory::getInstance ()
{
return new LevelDBFactory;
}
String LevelDBFactory::getName () const
String getName () const
{
return "LevelDB";
}
Backend* LevelDBFactory::createInstance (
std::unique_ptr <Backend> createInstance (
size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
{
return new LevelDBFactory::BackendImp (keyBytes, keyValues, scheduler);
return std::make_unique <LevelDBBackend> (
keyBytes, keyValues, scheduler, journal);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <Factory> make_LevelDBFactory ()
{
return std::make_unique <LevelDBFactory> ();
}
}
}

View File

@@ -20,35 +20,15 @@
#ifndef RIPPLE_NODESTORE_LEVELDBFACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_LEVELDBFACTORY_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Factory to produce LevelDBFactory backends for the NodeStore.
@see Database
*/
class LevelDBFactory : public Factory
{
private:
LevelDBFactory ();
~LevelDBFactory ();
public:
class BackendImp;
static LevelDBFactory* getInstance ();
String getName () const;
Backend* createInstance (size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal);
private:
void* m_lruCache;
};
std::unique_ptr <Factory> make_LevelDBFactory ();
}
}
#endif

View File

@@ -17,23 +17,27 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class MemoryFactory::BackendImp : public Backend
class MemoryBackend : public Backend
{
private:
typedef std::map <uint256 const, NodeObject::Ptr> Map;
public:
BackendImp (size_t keyBytes, Parameters const& keyValues,
Scheduler& scheduler)
: m_keyBytes (keyBytes)
typedef std::map <uint256 const, NodeObject::Ptr> Map;
Journal m_journal;
size_t const m_keyBytes;
Map m_map;
Scheduler& m_scheduler;
MemoryBackend (size_t keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal)
: m_journal (journal)
, m_keyBytes (keyBytes)
, m_scheduler (scheduler)
{
}
~BackendImp ()
~MemoryBackend ()
{
}
@@ -88,43 +92,33 @@ public:
{
return 0;
}
//--------------------------------------------------------------------------
private:
size_t const m_keyBytes;
Map m_map;
Scheduler& m_scheduler;
};
//------------------------------------------------------------------------------
MemoryFactory::MemoryFactory ()
class MemoryFactory : public Factory
{
}
MemoryFactory::~MemoryFactory ()
{
}
MemoryFactory* MemoryFactory::getInstance ()
{
return new MemoryFactory;
}
String MemoryFactory::getName () const
public:
String getName () const
{
return "Memory";
}
Backend* MemoryFactory::createInstance (
size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
std::unique_ptr <Backend> createInstance (
size_t keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal)
{
return new MemoryFactory::BackendImp (keyBytes, keyValues, scheduler);
return std::make_unique <MemoryBackend> (
keyBytes, keyValues, scheduler, journal);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <Factory> make_MemoryFactory ()
{
return std::make_unique <MemoryFactory> ();
}
}
}

View File

@@ -20,32 +20,15 @@
#ifndef RIPPLE_NODESTORE_MEMORYFACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_MEMORYFACTORY_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Factory to produce a RAM based backend for the NodeStore.
@see Database
*/
class MemoryFactory : public Factory
{
private:
MemoryFactory ();
~MemoryFactory ();
public:
class BackendImp;
static MemoryFactory* getInstance ();
String getName () const;
Backend* createInstance (size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal);
};
std::unique_ptr <Factory> make_MemoryFactory ();
}
}
#endif

View File

@@ -17,18 +17,18 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class NullFactory::BackendImp : public Backend
class NullBackend : public Backend
{
public:
explicit BackendImp (Scheduler& scheduler)
explicit NullBackend (Scheduler& scheduler)
: m_scheduler (scheduler)
{
}
~BackendImp ()
~NullBackend ()
{
}
@@ -65,31 +65,27 @@ private:
//------------------------------------------------------------------------------
NullFactory::NullFactory ()
class NullFactory : public Factory
{
}
NullFactory::~NullFactory ()
{
}
NullFactory* NullFactory::getInstance ()
{
return new NullFactory;
}
String NullFactory::getName () const
public:
String getName () const
{
return "none";
}
Backend* NullFactory::createInstance (
size_t,
Parameters const&,
Scheduler& scheduler,
Journal journal)
std::unique_ptr <Backend> createInstance (
size_t, Parameters const&, Scheduler& scheduler, Journal journal)
{
return new NullFactory::BackendImp (scheduler);
return std::make_unique <NullBackend> (scheduler);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <Factory> make_NullFactory ()
{
return std::make_unique <NullFactory> ();
}
}
}

View File

@@ -20,34 +20,16 @@
#ifndef RIPPLE_NODESTORE_NULLFACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_NULLFACTORY_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Factory to produce a null backend.
This is for standalone / testing mode.
@see Database
*/
class NullFactory : public Factory
{
private:
NullFactory ();
~NullFactory ();
public:
class BackendImp;
static NullFactory* getInstance ();
String getName () const;
Backend* createInstance (size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal);
};
std::unique_ptr <Factory> make_NullFactory ();
}
}
#endif

View File

@@ -19,19 +19,14 @@
#if RIPPLE_ROCKSDB_AVAILABLE
namespace NodeStore {
#include <atomic>
//------------------------------------------------------------------------------
namespace ripple {
namespace NodeStore {
class RocksDBEnv : public rocksdb::EnvWrapper
{
public:
static RocksDBEnv* get ()
{
static RocksDBEnv instance;
return &instance;
}
RocksDBEnv ()
: EnvWrapper (rocksdb::Env::Default())
{
@@ -56,8 +51,8 @@ public:
void* a (p->a);
delete p;
static Atomic <int> n;
int const id (++n);
static std::atomic <std::size_t> n;
std::size_t const id (++n);
std::stringstream ss;
ss << "rocksdb #" << id;
Thread::setCurrentThreadName (ss.str());
@@ -74,16 +69,21 @@ public:
//------------------------------------------------------------------------------
class RocksDBFactory::BackendImp
class RocksDBBackend
: public Backend
, public BatchWriter::Callback
, public LeakChecked <RocksDBFactory::BackendImp>
, public LeakChecked <RocksDBBackend>
{
public:
BackendImp (int keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
Journal m_journal;
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
std::string m_name;
std::unique_ptr <rocksdb::DB> m_db;
RocksDBBackend (int keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal, RocksDBEnv* env)
: m_journal (journal)
, m_keyBytes (keyBytes)
, m_scheduler (scheduler)
@@ -132,17 +132,17 @@ public:
options.target_file_size_multiplier = keyValues["file_size_mult"].getIntValue();
}
options.env = RocksDBEnv::get();
options.env = env;
rocksdb::DB* db = nullptr;
rocksdb::Status status = rocksdb::DB::Open (options, m_name, &db);
if (!status.ok () || !db)
Throw (std::runtime_error (std::string("Unable to open/create RocksDB: ") + status.ToString()));
m_db = db;
m_db.reset (db);
}
~BackendImp ()
~RocksDBBackend ()
{
}
@@ -233,7 +233,7 @@ public:
{
rocksdb::ReadOptions const options;
ScopedPointer <rocksdb::Iterator> it (m_db->NewIterator (options));
std::unique_ptr <rocksdb::Iterator> it (m_db->NewIterator (options));
for (it->SeekToFirst (); it->Valid (); it->Next ())
{
@@ -275,24 +275,17 @@ public:
{
storeBatch (batch);
}
private:
Journal m_journal;
size_t const m_keyBytes;
Scheduler& m_scheduler;
BatchWriter m_batch;
std::string m_name;
ScopedPointer <rocksdb::DB> m_db;
};
//------------------------------------------------------------------------------
class RocksDBFactoryImp : public RocksDBFactory
class RocksDBFactory : public Factory
{
public:
std::shared_ptr <rocksdb::Cache> m_lruCache;
RocksDBEnv m_env;
RocksDBFactoryImp ()
RocksDBFactory ()
{
rocksdb::Options options;
options.create_if_missing = true;
@@ -302,9 +295,8 @@ public:
m_lruCache = options.block_cache;
}
~RocksDBFactoryImp ()
~RocksDBFactory ()
{
}
String getName () const
@@ -312,26 +304,23 @@ public:
return "RocksDB";
}
Backend* createInstance (
std::unique_ptr <Backend> createInstance (
size_t keyBytes, Parameters const& keyValues,
Scheduler& scheduler, Journal journal)
{
return new RocksDBFactory::BackendImp (
keyBytes, keyValues, scheduler, journal);
return std::make_unique <RocksDBBackend> (
keyBytes, keyValues, scheduler, journal, &m_env);
}
};
//------------------------------------------------------------------------------
RocksDBFactory::~RocksDBFactory ()
std::unique_ptr <Factory> make_RocksDBFactory ()
{
return std::make_unique <RocksDBFactory> ();
}
RocksDBFactory* RocksDBFactory::New ()
{
return new RocksDBFactoryImp;
}
}
#endif

View File

@@ -20,20 +20,15 @@
#ifndef RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED
namespace ripple {
namespace NodeStore {
/** Factory to produce RocksDB backends for the NodeStore.
@see Database
*/
class RocksDBFactory : public Factory
{
public:
class BackendImp;
static RocksDBFactory* New ();
virtual ~RocksDBFactory () = 0;
};
std::unique_ptr <Factory> make_RocksDBFactory ();
}
}
#endif

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
Backend::~Backend ()
{
}
}
}

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
BatchWriter::BatchWriter (Callback& callback, Scheduler& scheduler)
: m_callback (callback)
@@ -99,3 +99,4 @@ void BatchWriter::waitForWriting ()
}
}
}

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
#define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Batch-writing assist logic.
@@ -81,6 +81,7 @@ private:
Batch mWriteSet;
};
}
}
#endif

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
Database::~Database ()
{
}
}
}

View File

@@ -17,24 +17,35 @@
*/
//==============================================================================
#ifndef RIPPLE_NODESTORE_DATABASEIMP_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASEIMP_H_INCLUDED
namespace ripple {
namespace NodeStore {
class DatabaseImp
: public Database
, LeakChecked <DatabaseImp>
, public LeakChecked <DatabaseImp>
{
public:
DatabaseImp (char const* name,
Journal m_journal;
Scheduler& m_scheduler;
// Persistent key/value storage.
std::unique_ptr <Backend> m_backend;
// Larger key/value storage, but not necessarily persistent.
std::unique_ptr <Backend> m_fastBackend;
TaggedCacheType <uint256, NodeObject> m_cache;
DatabaseImp (std::string const& name,
Scheduler& scheduler,
Parameters const& backendParameters,
Parameters const& fastBackendParameters,
std::unique_ptr <Backend> backend,
std::unique_ptr <Backend> fastBackend,
Journal journal)
: m_journal (journal)
, m_scheduler (scheduler)
, m_backend (createBackend (backendParameters, scheduler, journal))
, m_fastBackend ((fastBackendParameters.size () > 0)
? createBackend (fastBackendParameters, scheduler, journal) : nullptr)
, m_cache ("NodeStore", 16384, 300,
, m_backend (std::move (backend))
, m_fastBackend (std::move (fastBackend))
, m_cache ("NodeStore", cacheTargetSize, cacheTargetSeconds,
get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (),
LogPartition::getJournal <TaggedCacheLog> ())
{
@@ -67,7 +78,7 @@ public:
//
if (m_fastBackend != nullptr)
{
obj = fetchInternal (m_fastBackend, hash);
obj = fetchInternal (*m_fastBackend, hash);
// If we found the object, avoid storing it again later.
if (obj != nullptr)
@@ -89,7 +100,7 @@ public:
//
//LoadEvent::autoptr event (getApp().getJobQueue ().getLoadEventAP (jtHO_READ, "HOS::retrieve"));
obj = fetchInternal (m_backend, hash);
obj = fetchInternal (*m_backend, hash);
}
}
@@ -124,11 +135,12 @@ public:
return obj;
}
NodeObject::Ptr fetchInternal (Backend* backend, uint256 const& hash)
NodeObject::Ptr fetchInternal (Backend& backend,
uint256 const& hash)
{
NodeObject::Ptr object;
Status const status = backend->fetch (hash.begin (), &object);
Status const status = backend.fetch (hash.begin (), &object);
switch (status)
{
@@ -254,96 +266,9 @@ public:
sourceDatabase.visitAll (callback);
}
//------------------------------------------------------------------------------
static void missing_backend ()
{
fatal_error ("Your rippled.cfg is missing a [node_db] entry, please see the rippled-example.cfg file!");
}
static Backend* createBackend (Parameters const& parameters,
Scheduler& scheduler, Journal journal)
{
Backend* backend = nullptr;
String const& type = parameters ["type"];
if (type.isNotEmpty ())
{
Factory* factory (Factories::get().find (type));
if (factory != nullptr)
{
backend = factory->createInstance (
NodeObject::keyBytes, parameters, scheduler, journal);
}
else
{
missing_backend ();
}
}
else
{
missing_backend ();
}
return backend;
}
//------------------------------------------------------------------------------
private:
Journal m_journal;
Scheduler& m_scheduler;
// Persistent key/value storage.
ScopedPointer <Backend> m_backend;
// Larger key/value storage, but not necessarily persistent.
ScopedPointer <Backend> m_fastBackend;
// VFALCO NOTE What are these things for? We need comments.
TaggedCacheType <uint256, NodeObject> m_cache;
};
//------------------------------------------------------------------------------
void Database::addFactory (Factory* factory)
{
Factories::get().add (factory);
}
}
void Database::addAvailableBackends ()
{
// This is part of the ripple_app module since it has dependencies
//addFactory (SqliteFactory::getInstance ());
addFactory (LevelDBFactory::getInstance ());
addFactory (MemoryFactory::getInstance ());
addFactory (NullFactory::getInstance ());
#if RIPPLE_HYPERLEVELDB_AVAILABLE
addFactory (HyperDBFactory::getInstance ());
#endif
#if RIPPLE_ROCKSDB_AVAILABLE
addFactory (RocksDBFactory::New ());
#endif
}
//------------------------------------------------------------------------------
Database* Database::New (char const* name,
Scheduler& scheduler,
Journal journal,
Parameters const& backendParameters,
Parameters fastBackendParameters)
{
return new DatabaseImp (name,
scheduler, backendParameters, fastBackendParameters, journal);
}
}

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
DecodedBlob::DecodedBlob (void const* key, void const* value, int valueBytes)
{
@@ -94,3 +94,4 @@ NodeObject::Ptr DecodedBlob::createObject ()
}
}
}

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Parsed key/value blob into NodeObject components.
@@ -55,6 +55,7 @@ private:
int m_dataBytes;
};
}
}
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
DummyScheduler::DummyScheduler ()
{
@@ -39,4 +39,4 @@ void DummyScheduler::scheduledTasksStopped ()
}
}
}

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
void EncodedBlob::prepare (NodeObject::Ptr const& object)
{
@@ -49,3 +49,4 @@ void EncodedBlob::prepare (NodeObject::Ptr const& object)
}
}
}

View File

@@ -20,24 +20,19 @@
#ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
/** Utility for producing flattened node objects.
These get recycled to prevent many small allocations.
@note This defines the database format of a NodeObject!
*/
// VFALCO TODO Make allocator aware and use short_alloc
struct EncodedBlob
{
public:
void prepare (NodeObject::Ptr const& object);
void const* getKey () const noexcept { return m_key; }
size_t getSize () const noexcept { return m_size; }
void const* getData () const noexcept { return m_data.getData (); }
private:
@@ -46,6 +41,7 @@ private:
size_t m_size;
};
}
}
#endif

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
Factory::~Factory ()
{
}
}
}

View File

@@ -0,0 +1,142 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
class ManagerImp : public Manager
{
public:
typedef std::vector <std::unique_ptr <Factory>> List;
List m_list;
explicit ManagerImp (std::vector <std::unique_ptr <Factory>> factories)
: m_list (std::move (factories))
{
m_list.reserve (20);
add_known_factories ();
}
~ManagerImp ()
{
}
void add_factory (std::unique_ptr <Factory> factory)
{
m_list.emplace_back (std::move (factory));
}
void add_known_factories ()
{
// This is part of the ripple_app module since it has dependencies
//addFactory (make_SqliteFactory ());
add_factory (make_LevelDBFactory ());
add_factory (make_MemoryFactory ());
add_factory (make_NullFactory ());
#if RIPPLE_HYPERLEVELDB_AVAILABLE
add_factory (make_HyperDBFactory ());
#endif
#if RIPPLE_ROCKSDB_AVAILABLE
add_factory (make_RocksDBFactory ());
#endif
}
Factory* find (std::string const& name) const
{
for (List::const_iterator iter (m_list.begin ());
iter != m_list.end (); ++iter)
if ((*iter)->getName().compareIgnoreCase (name) == 0)
return iter->get();
return nullptr;
}
static void missing_backend ()
{
fatal_error (
"Your rippled.cfg is missing a [node_db] entry, "
"please see the rippled-example.cfg file!"
);
}
std::unique_ptr <Backend> make_Backend (Parameters const& parameters,
Scheduler& scheduler, Journal journal)
{
std::unique_ptr <Backend> backend;
std::string const type (parameters ["type"].toStdString ());
if (! type.empty ())
{
Factory* const factory (find (type));
if (factory != nullptr)
{
backend = factory->createInstance (
NodeObject::keyBytes, parameters, scheduler, journal);
}
else
{
missing_backend ();
}
}
else
{
missing_backend ();
}
return backend;
}
std::unique_ptr <Database> make_Database (std::string const& name,
Scheduler& scheduler, Journal journal,
Parameters const& backendParameters,
Parameters fastBackendParameters)
{
std::unique_ptr <Backend> backend (make_Backend (
backendParameters, scheduler, journal));
std::unique_ptr <Backend> fastBackend (
(fastBackendParameters.size () > 0)
? make_Backend (fastBackendParameters, scheduler, journal)
: nullptr);
return std::make_unique <DatabaseImp> (name, scheduler,
std::move (backend), std::move (fastBackend), journal);
}
};
//------------------------------------------------------------------------------
Manager::~Manager ()
{
}
std::unique_ptr <Manager> make_Manager (
std::vector <std::unique_ptr <Factory>> factories)
{
return std::make_unique <ManagerImp> (std::move (factories));
}
}
}

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
namespace ripple {
SETUP_LOG (NodeObject)
//------------------------------------------------------------------------------
@@ -86,3 +88,4 @@ bool NodeObject::isCloneOf (NodeObject::Ptr const& other) const
//------------------------------------------------------------------------------
}

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
Scheduler::~Scheduler ()
{
}
}
}

View File

@@ -0,0 +1,28 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
namespace NodeStore {
Task::~Task ()
{
}
}
}

View File

@@ -17,47 +17,22 @@
*/
//==============================================================================
#ifndef RIPPLE_NODESTORE_FACTORIES_H_INCLUDED
#define RIPPLE_NODESTORE_FACTORIES_H_INCLUDED
#ifndef RIPPLE_NODESTORE_TUNING_H_INCLUDED
#define RIPPLE_NODESTORE_TUNING_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
// Holds the list of Backend factories
class Factories
enum
{
public:
Factories ()
{
}
// Target cache size of the TaggedCache used to hold nodes
cacheTargetSize = 16384
~Factories ()
{
}
void add (Factory* factory)
{
m_list.add (factory);
}
Factory* find (String name) const
{
for (int i = 0; i < m_list.size(); ++i)
if (m_list [i]->getName ().compareIgnoreCase (name) == 0)
return m_list [i];
return nullptr;
}
static Factories& get ()
{
return *SharedSingleton <Factories>::get (
SingletonLifetime::persistAfterCreation);
}
private:
OwnedArray <Factory> m_list;
// Expiration time for cached nodes
,cacheTargetSeconds = 300
};
}
}
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
// Tests the Backend interface
//
@@ -27,6 +27,8 @@ class BackendTests : public TestBase
public:
void testBackend (String type, int64 const seedValue, int numObjectsToTest = 2000)
{
std::unique_ptr <Manager> manager (make_Manager ());
DummyScheduler scheduler;
beginTestCase (String ("Backend type=") + type);
@@ -44,7 +46,7 @@ public:
{
// Open the backend
ScopedPointer <Backend> backend (DatabaseImp::createBackend (
std::unique_ptr <Backend> backend (manager->make_Backend (
params, scheduler, j));
// Write the batch
@@ -68,7 +70,7 @@ public:
{
// Re-open the backend
ScopedPointer <Backend> backend (DatabaseImp::createBackend (
std::unique_ptr <Backend> backend (manager->make_Backend (
params, scheduler, j));
// Read it back in
@@ -89,7 +91,9 @@ public:
testBackend ("leveldb", seedValue);
#ifdef RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
testBackend ("sqlite", seedValue);
#endif
#if RIPPLE_HYPERLEVELDB_AVAILABLE
testBackend ("hyperleveldb", seedValue);
@@ -108,3 +112,4 @@ public:
static BackendTests backendTests;
}
}

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
// Tests predictable batches, and NodeObject blob encoding
//
@@ -87,3 +87,4 @@ public:
static BasicTests basicTests;
}
}

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class DatabaseTests : public TestBase
{
@@ -36,6 +36,8 @@ public:
void testImport (String destBackendType, String srcBackendType, int64 seedValue)
{
std::unique_ptr <Manager> manager (make_Manager ());
DummyScheduler scheduler;
File const node_db (File::createTempFile ("node_db"));
@@ -51,7 +53,7 @@ public:
// Write to source db
{
ScopedPointer <Database> src (Database::New (
std::unique_ptr <Database> src (manager->make_Database (
"test", scheduler, j, srcParams));
storeBatch (*src, batch);
}
@@ -60,7 +62,7 @@ public:
{
// Re-open the db
ScopedPointer <Database> src (Database::New (
std::unique_ptr <Database> src (manager->make_Database (
"test", scheduler, j, srcParams));
// Set up the destination database
@@ -69,7 +71,7 @@ public:
destParams.set ("type", destBackendType);
destParams.set ("path", dest_db.getFullPathName ());
ScopedPointer <Database> dest (Database::New (
std::unique_ptr <Database> dest (manager->make_Database (
"test", scheduler, j, destParams));
beginTestCase (String ("import into '") + destBackendType + "' from '" + srcBackendType + "'");
@@ -95,6 +97,8 @@ public:
int64 const seedValue,
int numObjectsToTest = 2000)
{
std::unique_ptr <Manager> manager (make_Manager ());
DummyScheduler scheduler;
String s;
@@ -125,7 +129,7 @@ public:
{
// Open the database
ScopedPointer <Database> db (Database::New ("test", scheduler,
std::unique_ptr <Database> db (manager->make_Database ("test", scheduler,
j, nodeParams, tempParams));
// Write the batch
@@ -151,7 +155,7 @@ public:
{
{
// Re-open the database without the ephemeral DB
ScopedPointer <Database> db (Database::New (
std::unique_ptr <Database> db (manager->make_Database (
"test", scheduler, j, nodeParams));
// Read it back in
@@ -167,7 +171,7 @@ public:
if (useEphemeralDatabase)
{
// Verify the ephemeral db
ScopedPointer <Database> db (Database::New ("test",
std::unique_ptr <Database> db (manager->make_Database ("test",
scheduler, j, tempParams, StringPairArray ()));
// Read it back in
@@ -196,7 +200,9 @@ public:
testNodeStore ("rocksdb", useEphemeralDatabase, true, seedValue);
#endif
#if RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
testNodeStore ("sqlite", useEphemeralDatabase, true, seedValue);
#endif
}
//--------------------------------------------------------------------------
@@ -213,7 +219,9 @@ public:
testImport ("hyperleveldb", "hyperleveldb", seedValue);
#endif
#if RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
testImport ("sqlite", "sqlite", seedValue);
#endif
}
//--------------------------------------------------------------------------
@@ -235,3 +243,4 @@ public:
static DatabaseTests databaseTests;
}
}

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_TESTBASE_H_INCLUDED
#define RIPPLE_NODESTORE_TESTBASE_H_INCLUDED
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
// Some common code for the unit tests
//
@@ -187,6 +187,7 @@ public:
}
};
}
}
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
namespace NodeStore
{
namespace ripple {
namespace NodeStore {
class TimingTests : public TestBase
{
@@ -60,6 +60,8 @@ public:
void testBackend (String type, int64 const seedValue)
{
std::unique_ptr <Manager> manager (make_Manager ());
DummyScheduler scheduler;
String s;
@@ -80,7 +82,7 @@ public:
Journal j ((journal ()));
// Open the backend
ScopedPointer <Backend> backend (DatabaseImp::createBackend (
std::unique_ptr <Backend> backend (manager->make_Backend (
params, scheduler, j));
Stopwatch t;
@@ -125,12 +127,13 @@ public:
testBackend ("rocksdb", seedValue);
#endif
/*
#if RIPPLE_ENABLE_SQLITE_BACKEND_TESTS
testBackend ("sqlite", seedValue);
*/
#endif
}
};
static TimingTests timingTests;
}
}