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)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple_core\nodestore\impl\BatchWriter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple_core\nodestore\impl\DecodedBlob.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|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)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple_core\nodestore\impl\NodeObject.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </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"> <ClCompile Include="..\..\src\ripple_core\nodestore\NodeStore.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|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\Database.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\DummyScheduler.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\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\NodeObject.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Scheduler.h" /> <ClInclude Include="..\..\src\ripple_core\nodestore\api\Scheduler.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\api\Task.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\DatabaseImp.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\impl\DecodedBlob.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\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\NodeStore.h" />
<ClInclude Include="..\..\src\ripple_core\nodestore\tests\TestBase.h" /> <ClInclude Include="..\..\src\ripple_core\nodestore\tests\TestBase.h" />
<ClInclude Include="..\..\src\ripple_core\ripple_core.h" /> <ClInclude Include="..\..\src\ripple_core\ripple_core.h" />

View File

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

View File

@@ -68,6 +68,8 @@ public:
Application::LockType m_masterMutex; Application::LockType m_masterMutex;
// These are not Stoppable-derived // These are not Stoppable-derived
std::unique_ptr <NodeStore::Manager> m_nodeStoreManager;
NodeCache m_tempNodeCache; NodeCache m_tempNodeCache;
SLECache m_sleCache; SLECache m_sleCache;
LocalCredentials m_localCredentials; 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 () ApplicationImp ()
: RootStoppable ("Application") : RootStoppable ("Application")
, m_journal (LogPartition::getJournal <ApplicationLog> ()) , m_journal (LogPartition::getJournal <ApplicationLog> ())
, m_nodeStoreManager (NodeStore::make_Manager (
std::move (make_Factories ())))
, m_tempNodeCache ("NodeCache", 16384, 90, , m_tempNodeCache ("NodeCache", 16384, 90,
get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (), get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (),
LogPartition::getJournal <TaggedCacheLog> ()) LogPartition::getJournal <TaggedCacheLog> ())
@@ -233,7 +250,7 @@ public:
#if ! RIPPLE_USE_RPC_SERVICE_MANAGER #if ! RIPPLE_USE_RPC_SERVICE_MANAGER
, m_rpcServerHandler (*m_networkOPs, *m_resourceManager) // passive object, not a Service , m_rpcServerHandler (*m_networkOPs, *m_resourceManager) // passive object, not a Service
#endif #endif
, m_nodeStore (NodeStore::Database::New ("NodeStore.main", m_nodeStoreScheduler, , m_nodeStore (m_nodeStoreManager->make_Database ("NodeStore.main", m_nodeStoreScheduler,
LogPartition::getJournal <NodeObject> (), LogPartition::getJournal <NodeObject> (),
getConfig ().nodeDatabase, getConfig ().ephemeralNodeDatabase)) getConfig ().nodeDatabase, getConfig ().ephemeralNodeDatabase))
@@ -1335,9 +1352,10 @@ void ApplicationImp::updateTables ()
if (getConfig ().doImport) if (getConfig ().doImport)
{ {
NodeStore::DummyScheduler scheduler; NodeStore::DummyScheduler scheduler;
std::unique_ptr <NodeStore::Database> source (NodeStore::Database::New ( std::unique_ptr <NodeStore::Database> source (
"NodeStore.import", scheduler, LogPartition::getJournal <NodeObject> (), m_nodeStoreManager->make_Database ("NodeStore.import", scheduler,
getConfig ().importNodeDatabase)); LogPartition::getJournal <NodeObject> (),
getConfig ().importNodeDatabase));
WriteLog (lsWARNING, NodeObject) << WriteLog (lsWARNING, NodeObject) <<
"Node import from '" << source->getName () << "' to '" "Node import from '" << source->getName () << "' to '"

View File

@@ -292,16 +292,6 @@ int RippleMain::run (int argc, char const* const* argv)
po::positional_options_description p; po::positional_options_description p;
p.add ("parameters", -1); 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 ()) if (! RandomNumbers::getInstance ().initialize ())
{ {
Log::out() << "Unable to add system entropy"; 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: 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_keyBytes (keyBytes)
, m_name (path) , m_name (path)
, m_db (new DatabaseCon(path, s_nodeStoreDBInit, s_nodeStoreDBCount)) , m_db (new DatabaseCon(path, s_nodeStoreDBInit, s_nodeStoreDBCount))
@@ -60,7 +60,7 @@ public:
m_db->getDB()->executeSQL (s.toStdString ().c_str ()); m_db->getDB()->executeSQL (s.toStdString ().c_str ());
} }
~BackendImp() ~SqliteBackend()
{ {
} }
@@ -224,29 +224,26 @@ private:
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
SqliteFactory::SqliteFactory () class SqliteFactory : public NodeStore::Factory
{ {
} public:
String getName () const
{
return "Sqlite";
}
SqliteFactory::~SqliteFactory () std::unique_ptr <NodeStore::Backend> createInstance (
{ size_t keyBytes, NodeStore::Parameters const& keyValues,
} NodeStore::Scheduler& scheduler, Journal)
{
return std::make_unique <SqliteBackend> (
keyBytes, keyValues ["path"].toStdString (), scheduler);
}
};
SqliteFactory* SqliteFactory::getInstance () //------------------------------------------------------------------------------
{
return new SqliteFactory;
}
String SqliteFactory::getName () const std::unique_ptr <NodeStore::Factory> make_SqliteFactory ()
{ {
return "Sqlite"; return std::make_unique <SqliteFactory> ();
}
NodeStore::Backend* SqliteFactory::createInstance (
size_t keyBytes,
NodeStore::Parameters const& keyValues,
NodeStore::Scheduler& scheduler,
Journal)
{
return new BackendImp (keyBytes, keyValues ["path"].toStdString (), scheduler);
} }

View File

@@ -21,26 +21,8 @@
#define RIPPLE_APP_SQLITEFACTORY_H_INCLUDED #define RIPPLE_APP_SQLITEFACTORY_H_INCLUDED
/** Factory to produce SQLite backends for the NodeStore. /** Factory to produce SQLite backends for the NodeStore.
@see Database @see Database
*/ */
class SqliteFactory : public NodeStore::Factory std::unique_ptr <NodeStore::Factory> make_SqliteFactory ();
{
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);
};
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED #ifndef RIPPLE_NODESTORE_DATABASE_H_INCLUDED
#define RIPPLE_NODESTORE_DATABASE_H_INCLUDED #define RIPPLE_NODESTORE_DATABASE_H_INCLUDED
namespace NodeStore namespace ripple {
{ namespace NodeStore {
/** Persistency layer for NodeObject /** Persistency layer for NodeObject
@@ -39,40 +39,11 @@ namespace NodeStore
class Database class Database
{ {
public: 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. /** Destroy the node store.
All pending operations are completed, pending writes flushed, All pending operations are completed, pending writes flushed,
and files closed before this returns. and files closed before this returns.
*/ */
virtual ~Database () { } virtual ~Database () = 0 ;
/** Retrieve the name associated with this backend. /** Retrieve the name associated with this backend.
This is used for diagnostics and may not reflect the actual path This is used for diagnostics and may not reflect the actual path
@@ -80,14 +51,6 @@ public:
*/ */
virtual String getName () const = 0; 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. /** Fetch an object.
If the object is known to be not in the database, isn't found in the 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, database during the fetch, or failed to load correctly during the fetch,
@@ -142,12 +105,9 @@ public:
// VFALCO TODO Document this. // VFALCO TODO Document this.
virtual void sweep () = 0; virtual void sweep () = 0;
/** Add the known Backend factories to the singleton.
*/
static void addAvailableBackends ();
}; };
}
} }
#endif #endif

View File

@@ -20,22 +20,20 @@
#ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED #ifndef RIPPLE_NODESTORE_DUMMYSCHEDULER_H_INCLUDED
#define 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 class DummyScheduler : public Scheduler
{ {
public: public:
DummyScheduler (); DummyScheduler ();
~DummyScheduler (); ~DummyScheduler ();
void scheduleTask (Task& task); void scheduleTask (Task& task);
void scheduledTasksStopped (); void scheduledTasksStopped ();
}; };
}
} }
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,19 +19,26 @@
#if RIPPLE_HYPERLEVELDB_AVAILABLE #if RIPPLE_HYPERLEVELDB_AVAILABLE
namespace NodeStore namespace ripple {
{ namespace NodeStore {
class HyperDBFactory::BackendImp class HyperDBBackend
: public Backend : public Backend
, public BatchWriter::Callback , public BatchWriter::Callback
, public LeakChecked <HyperDBFactory::BackendImp> , public LeakChecked <HyperDBBackend>
{ {
public: public:
BackendImp (size_t keyBytes, Journal m_journal;
Parameters const& keyValues, size_t const m_keyBytes;
Scheduler& scheduler) Scheduler& m_scheduler;
: m_keyBytes (keyBytes) 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_scheduler (scheduler)
, m_batch (*this, scheduler) , m_batch (*this, scheduler)
, m_name (keyValues ["path"].toStdString ()) , m_name (keyValues ["path"].toStdString ())
@@ -69,12 +76,13 @@ public:
hyperleveldb::DB* db = nullptr; hyperleveldb::DB* db = nullptr;
hyperleveldb::Status status = hyperleveldb::DB::Open (options, m_name, &db); hyperleveldb::Status status = hyperleveldb::DB::Open (options, m_name, &db);
if (!status.ok () || !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; EncodedBlob encoded;
// VFALCO Use range based for
BOOST_FOREACH (NodeObject::ref object, batch) BOOST_FOREACH (NodeObject::ref object, batch)
{ {
encoded.prepare (object); encoded.prepare (object);
@@ -163,7 +172,7 @@ public:
{ {
hyperleveldb::ReadOptions const options; 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 ()) for (it->SeekToFirst (); it->Valid (); it->Next ())
{ {
@@ -181,14 +190,16 @@ public:
else else
{ {
// Uh oh, corrupted data! // 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 else
{ {
// VFALCO NOTE What does it mean to find an // VFALCO NOTE What does it mean to find an
// incorrectly sized key? Corruption? // 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); 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
{ {
public:
String getName () const
{
return "HyperLevelDB";
}
std::unique_ptr <Backend> createInstance (size_t keyBytes,
Parameters const& keyValues, Scheduler& scheduler, Journal journal)
{
return std::make_unique <HyperDBBackend> (
keyBytes, keyValues, scheduler, journal);
}
};
//------------------------------------------------------------------------------
std::unique_ptr <Factory> make_HyperDBFactory ()
{
return std::make_unique <HyperDBFactory> ();
} }
HyperDBFactory::~HyperDBFactory ()
{
} }
HyperDBFactory* HyperDBFactory::getInstance ()
{
return new HyperDBFactory;
}
String HyperDBFactory::getName () const
{
return "HyperLevelDB";
}
Backend* HyperDBFactory::createInstance (
size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
{
return new HyperDBFactory::BackendImp (keyBytes, keyValues, scheduler);
}
} }
#endif #endif

View File

@@ -22,32 +22,15 @@
#if RIPPLE_HYPERLEVELDB_AVAILABLE #if RIPPLE_HYPERLEVELDB_AVAILABLE
namespace NodeStore namespace ripple {
{ namespace NodeStore {
/** Factory to produce HyperLevelDB backends for the NodeStore. /** Factory to produce HyperLevelDB backends for the NodeStore.
@see Database @see Database
*/ */
class HyperDBFactory : public NodeStore::Factory std::unique_ptr <Factory> make_HyperDBFactory ();
{
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);
};
}
} }
#endif #endif

View File

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

View File

@@ -20,35 +20,15 @@
#ifndef RIPPLE_NODESTORE_LEVELDBFACTORY_H_INCLUDED #ifndef RIPPLE_NODESTORE_LEVELDBFACTORY_H_INCLUDED
#define 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. /** Factory to produce LevelDBFactory backends for the NodeStore.
@see Database @see Database
*/ */
class LevelDBFactory : public Factory std::unique_ptr <Factory> make_LevelDBFactory ();
{
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;
};
}
} }
#endif #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: public:
BackendImp (size_t keyBytes, Parameters const& keyValues, typedef std::map <uint256 const, NodeObject::Ptr> Map;
Scheduler& scheduler) Journal m_journal;
: m_keyBytes (keyBytes) 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) , m_scheduler (scheduler)
{ {
} }
~BackendImp () ~MemoryBackend ()
{ {
} }
@@ -88,43 +92,33 @@ public:
{ {
return 0; return 0;
} }
//--------------------------------------------------------------------------
private:
size_t const m_keyBytes;
Map m_map;
Scheduler& m_scheduler;
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
MemoryFactory::MemoryFactory () class MemoryFactory : public Factory
{ {
} public:
String getName () const
{
return "Memory";
}
MemoryFactory::~MemoryFactory () std::unique_ptr <Backend> createInstance (
{ size_t keyBytes, Parameters const& keyValues,
} Scheduler& scheduler, Journal journal)
{
return std::make_unique <MemoryBackend> (
keyBytes, keyValues, scheduler, journal);
}
};
MemoryFactory* MemoryFactory::getInstance () //------------------------------------------------------------------------------
{
return new MemoryFactory;
}
String MemoryFactory::getName () const std::unique_ptr <Factory> make_MemoryFactory ()
{ {
return "Memory"; return std::make_unique <MemoryFactory> ();
}
Backend* MemoryFactory::createInstance (
size_t keyBytes,
Parameters const& keyValues,
Scheduler& scheduler,
Journal journal)
{
return new MemoryFactory::BackendImp (keyBytes, keyValues, scheduler);
} }
} }
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,20 +20,15 @@
#ifndef RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED #ifndef RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED
#define RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED #define RIPPLE_NODESTORE_ROCKSDBFACTORY_H_INCLUDED
namespace ripple {
namespace NodeStore { namespace NodeStore {
/** Factory to produce RocksDB backends for the NodeStore. /** Factory to produce RocksDB backends for the NodeStore.
@see Database @see Database
*/ */
class RocksDBFactory : public Factory std::unique_ptr <Factory> make_RocksDBFactory ();
{
public:
class BackendImp;
static RocksDBFactory* New ();
virtual ~RocksDBFactory () = 0;
};
}
} }
#endif #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) BatchWriter::BatchWriter (Callback& callback, Scheduler& scheduler)
: m_callback (callback) : m_callback (callback)
@@ -99,3 +99,4 @@ void BatchWriter::waitForWriting ()
} }
} }
}

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED #ifndef RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
#define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED #define RIPPLE_NODESTORE_BATCHWRITER_H_INCLUDED
namespace NodeStore namespace ripple {
{ namespace NodeStore {
/** Batch-writing assist logic. /** Batch-writing assist logic.
@@ -81,6 +81,7 @@ private:
Batch mWriteSet; Batch mWriteSet;
}; };
}
} }
#endif #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 { namespace NodeStore {
class DatabaseImp class DatabaseImp
: public Database : public Database
, LeakChecked <DatabaseImp> , public LeakChecked <DatabaseImp>
{ {
public: 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, Scheduler& scheduler,
Parameters const& backendParameters, std::unique_ptr <Backend> backend,
Parameters const& fastBackendParameters, std::unique_ptr <Backend> fastBackend,
Journal journal) Journal journal)
: m_journal (journal) : m_journal (journal)
, m_scheduler (scheduler) , m_scheduler (scheduler)
, m_backend (createBackend (backendParameters, scheduler, journal)) , m_backend (std::move (backend))
, m_fastBackend ((fastBackendParameters.size () > 0) , m_fastBackend (std::move (fastBackend))
? createBackend (fastBackendParameters, scheduler, journal) : nullptr) , m_cache ("NodeStore", cacheTargetSize, cacheTargetSeconds,
, m_cache ("NodeStore", 16384, 300,
get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (), get_abstract_clock <std::chrono::steady_clock, std::chrono::seconds> (),
LogPartition::getJournal <TaggedCacheLog> ()) LogPartition::getJournal <TaggedCacheLog> ())
{ {
@@ -67,7 +78,7 @@ public:
// //
if (m_fastBackend != nullptr) 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 we found the object, avoid storing it again later.
if (obj != nullptr) if (obj != nullptr)
@@ -89,7 +100,7 @@ public:
// //
//LoadEvent::autoptr event (getApp().getJobQueue ().getLoadEventAP (jtHO_READ, "HOS::retrieve")); //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; return obj;
} }
NodeObject::Ptr fetchInternal (Backend* backend, uint256 const& hash) NodeObject::Ptr fetchInternal (Backend& backend,
uint256 const& hash)
{ {
NodeObject::Ptr object; NodeObject::Ptr object;
Status const status = backend->fetch (hash.begin (), &object); Status const status = backend.fetch (hash.begin (), &object);
switch (status) switch (status)
{ {
@@ -254,96 +266,9 @@ public:
sourceDatabase.visitAll (callback); 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 #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) 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 #ifndef RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED #define RIPPLE_NODESTORE_DECODEDBLOB_H_INCLUDED
namespace NodeStore namespace ripple {
{ namespace NodeStore {
/** Parsed key/value blob into NodeObject components. /** Parsed key/value blob into NodeObject components.
@@ -55,6 +55,7 @@ private:
int m_dataBytes; int m_dataBytes;
}; };
}
} }
#endif #endif

View File

@@ -17,8 +17,8 @@
*/ */
//============================================================================== //==============================================================================
namespace NodeStore namespace ripple {
{ namespace NodeStore {
DummyScheduler::DummyScheduler () 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) 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 #ifndef RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
#define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED #define RIPPLE_NODESTORE_ENCODEDBLOB_H_INCLUDED
namespace NodeStore namespace ripple {
{ namespace NodeStore {
/** Utility for producing flattened node objects. /** Utility for producing flattened node objects.
These get recycled to prevent many small allocations.
@note This defines the database format of a NodeObject! @note This defines the database format of a NodeObject!
*/ */
// VFALCO TODO Make allocator aware and use short_alloc
struct EncodedBlob struct EncodedBlob
{ {
public: public:
void prepare (NodeObject::Ptr const& object); void prepare (NodeObject::Ptr const& object);
void const* getKey () const noexcept { return m_key; } void const* getKey () const noexcept { return m_key; }
size_t getSize () const noexcept { return m_size; } size_t getSize () const noexcept { return m_size; }
void const* getData () const noexcept { return m_data.getData (); } void const* getData () const noexcept { return m_data.getData (); }
private: private:
@@ -46,6 +41,7 @@ private:
size_t m_size; size_t m_size;
}; };
}
} }
#endif #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) 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 #ifndef RIPPLE_NODESTORE_TUNING_H_INCLUDED
#define RIPPLE_NODESTORE_FACTORIES_H_INCLUDED #define RIPPLE_NODESTORE_TUNING_H_INCLUDED
namespace NodeStore namespace ripple {
namespace NodeStore {
enum
{ {
// Target cache size of the TaggedCache used to hold nodes
cacheTargetSize = 16384
// Holds the list of Backend factories // Expiration time for cached nodes
class Factories ,cacheTargetSeconds = 300
{
public:
Factories ()
{
}
~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;
}; };
}
} }
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

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