Refactor Application shutdown using new Service, AsyncService interfaces

This commit is contained in:
Vinnie Falco
2013-09-17 17:32:54 -07:00
parent 97e961a048
commit 89b1859929
57 changed files with 2690 additions and 1602 deletions

View File

@@ -193,6 +193,11 @@ public:
return m_batch.getWriteLoad ();
}
void stopAsync ()
{
m_batch.stopAsync();
}
//--------------------------------------------------------------------------
void writeBatch (NodeStore::Batch const& batch)
@@ -200,6 +205,11 @@ public:
storeBatch (batch);
}
void writeStopped ()
{
m_scheduler.scheduledTasksStopped ();
}
private:
size_t const m_keyBytes;
NodeStore::Scheduler& m_scheduler;

View File

@@ -134,6 +134,11 @@ public:
return 0;
}
void stopAsync ()
{
m_scheduler.scheduledTasksStopped ();
}
//--------------------------------------------------------------------------
private:

View File

@@ -193,6 +193,11 @@ public:
return m_batch.getWriteLoad ();
}
void stopAsync ()
{
m_batch.stopAsync ();
}
//--------------------------------------------------------------------------
void writeBatch (NodeStore::Batch const& batch)
@@ -200,6 +205,11 @@ public:
storeBatch (batch);
}
void writeStopped ()
{
m_scheduler.scheduledTasksStopped ();
}
private:
size_t const m_keyBytes;
NodeStore::Scheduler& m_scheduler;

View File

@@ -229,6 +229,11 @@ public:
return m_batch.getWriteLoad ();
}
void stopAsync ()
{
m_batch.stopAsync();
}
//--------------------------------------------------------------------------
void writeBatch (Batch const& batch)
@@ -236,6 +241,11 @@ public:
storeBatch (batch);
}
void writeStopped ()
{
m_scheduler.scheduledTasksStopped ();
}
private:
size_t const m_keyBytes;
NodeStore::Scheduler& m_scheduler;

View File

@@ -10,8 +10,10 @@ private:
typedef std::map <uint256 const, NodeObject::Ptr> Map;
public:
Backend (size_t keyBytes, StringPairArray const& keyValues)
Backend (size_t keyBytes, StringPairArray const& keyValues,
NodeStore::Scheduler& scheduler)
: m_keyBytes (keyBytes)
, m_scheduler (scheduler)
{
}
@@ -71,12 +73,18 @@ public:
return 0;
}
void stopAsync ()
{
m_scheduler.scheduledTasksStopped ();
}
//--------------------------------------------------------------------------
private:
size_t const m_keyBytes;
Map m_map;
NodeStore::Scheduler& m_scheduler;
};
//------------------------------------------------------------------------------
@@ -104,7 +112,7 @@ NodeStore::Backend* MemoryBackendFactory::createInstance (
StringPairArray const& keyValues,
NodeStore::Scheduler& scheduler)
{
return new MemoryBackendFactory::Backend (keyBytes, keyValues);
return new MemoryBackendFactory::Backend (keyBytes, keyValues, scheduler);
}
//------------------------------------------------------------------------------

View File

@@ -173,7 +173,7 @@ void NodeStore::BatchWriter::store (NodeObject::ref object)
{
mWritePending = true;
m_scheduler.scheduleTask (this);
m_scheduler.scheduleTask (*this);
}
}
@@ -184,6 +184,14 @@ int NodeStore::BatchWriter::getWriteLoad ()
return std::max (mWriteLoad, static_cast<int> (mWriteSet.size ()));
}
void NodeStore::BatchWriter::stopAsync ()
{
LockType::scoped_lock sl (mWriteMutex);
if (! mWritePending)
m_callback.writeStopped ();
}
void NodeStore::BatchWriter::performScheduledTask ()
{
writeBatch ();
@@ -212,6 +220,8 @@ void NodeStore::BatchWriter::writeBatch ()
mWritePending = false;
mWriteLoad = 0;
m_callback.writeStopped ();
// VFALCO NOTE Fix this function to not return from the middle
return;
}
@@ -241,10 +251,13 @@ class NodeStoreImp
, LeakChecked <NodeStoreImp>
{
public:
NodeStoreImp (Parameters const& backendParameters,
NodeStoreImp (char const* name,
Service& parent,
Parameters const& backendParameters,
Parameters const& fastBackendParameters,
Scheduler& scheduler)
: m_scheduler (scheduler)
: NodeStore (name, parent)
, m_scheduler (scheduler)
, m_backend (createBackend (backendParameters, scheduler))
, m_fastBackend ((fastBackendParameters.size () > 0)
? createBackend (fastBackendParameters, scheduler) : nullptr)
@@ -484,6 +497,19 @@ public:
sourceDatabase.visitAll (callback);
}
//------------------------------------------------------------------------------
//
// Service
void onServiceStop ()
{
// notify the Backend
m_backend->stopAsync();
if (m_fastBackend)
m_fastBackend->stopAsync();
}
//------------------------------------------------------------------------------
static void missing_backend ()
@@ -551,9 +577,13 @@ NodeStore::Scheduler& NodeStore::getSynchronousScheduler ()
// Simple scheduler that performs the task immediately
struct SynchronousScheduler : Scheduler
{
void scheduleTask (Task* task)
void scheduleTask (Task& task)
{
task.performScheduledTask ();
}
void scheduledTasksStopped ()
{
task->performScheduledTask ();
}
};
@@ -583,11 +613,24 @@ void NodeStore::addAvailableBackends ()
NodeStore::addBackendFactory (KeyvaDBBackendFactory::getInstance ());
}
NodeStore* NodeStore::New (Parameters const& backendParameters,
//------------------------------------------------------------------------------
NodeStore::NodeStore (char const* name, Service& parent)
: Service (name, parent)
{
}
//------------------------------------------------------------------------------
NodeStore* NodeStore::New (char const* name,
Service& parent,
Parameters const& backendParameters,
Parameters fastBackendParameters,
Scheduler& scheduler)
{
return new NodeStoreImp (backendParameters,
return new NodeStoreImp (name,
parent,
backendParameters,
fastBackendParameters,
scheduler);
}
@@ -1032,10 +1075,17 @@ static NodeStoreTimingTests nodeStoreTimingTests;
class NodeStoreTests : public NodeStoreUnitTest
{
public:
NodeStoreTests () : NodeStoreUnitTest ("NodeStore")
NodeStoreTests ()
: NodeStoreUnitTest ("NodeStore")
{
}
~NodeStoreTests ()
{
}
//--------------------------------------------------------------------------
void testImport (String destBackendType, String srcBackendType, int64 seedValue)
{
File const node_db (File::createTempFile ("node_db"));
@@ -1049,7 +1099,8 @@ public:
// Write to source db
{
ScopedPointer <NodeStore> src (NodeStore::New (srcParams));
ScopedService service ("test");
ScopedPointer <NodeStore> src (NodeStore::New ("test", service, srcParams));
storeBatch (*src, batch);
}
@@ -1057,8 +1108,10 @@ public:
NodeStore::Batch copy;
{
ScopedService service ("test");
// Re-open the db
ScopedPointer <NodeStore> src (NodeStore::New (srcParams));
ScopedPointer <NodeStore> src (NodeStore::New ("test", service, srcParams));
// Set up the destination database
File const dest_db (File::createTempFile ("dest_db"));
@@ -1066,7 +1119,7 @@ public:
destParams.set ("type", destBackendType);
destParams.set ("path", dest_db.getFullPathName ());
ScopedPointer <NodeStore> dest (NodeStore::New (destParams));
ScopedPointer <NodeStore> dest (NodeStore::New ("test", service, destParams));
beginTestCase (String ("import into '") + destBackendType + "' from '" + srcBackendType + "'");
@@ -1116,8 +1169,10 @@ public:
createPredictableBatch (batch, 0, numObjectsToTest, seedValue);
{
ScopedService service ("test");
// Open the database
ScopedPointer <NodeStore> db (NodeStore::New (nodeParams, tempParams));
ScopedPointer <NodeStore> db (NodeStore::New ("test", service, nodeParams, tempParams));
// Write the batch
storeBatch (*db, batch);
@@ -1141,8 +1196,10 @@ public:
if (testPersistence)
{
{
ScopedService service ("test");
// Re-open the database without the ephemeral DB
ScopedPointer <NodeStore> db (NodeStore::New (nodeParams));
ScopedPointer <NodeStore> db (NodeStore::New ("test", service, nodeParams));
// Read it back in
NodeStore::Batch copy;
@@ -1156,8 +1213,11 @@ public:
if (useEphemeralDatabase)
{
ScopedService service ("test");
// Verify the ephemeral db
ScopedPointer <NodeStore> db (NodeStore::New (tempParams, StringPairArray ()));
ScopedPointer <NodeStore> db (NodeStore::New ("test",
service, tempParams, StringPairArray ()));
// Read it back in
NodeStore::Batch copy;

View File

@@ -20,8 +20,11 @@
@see NodeObject
*/
class NodeStore
class NodeStore : public Service
{
protected:
NodeStore (char const* name, Service& parent);
public:
enum
{
@@ -114,7 +117,6 @@ public:
virtual ~Task () { }
/** Performs the task.
The call may take place on a foreign thread.
*/
virtual void performScheduledTask () = 0;
@@ -125,7 +127,10 @@ public:
Depending on the implementation, this could happen
immediately or get deferred.
*/
virtual void scheduleTask (Task* task) = 0;
virtual void scheduleTask (Task& task) = 0;
/** Notifies the scheduler that all tasks are complete. */
virtual void scheduledTasksStopped () = 0;
};
//--------------------------------------------------------------------------
@@ -149,6 +154,9 @@ public:
struct Callback
{
virtual void writeBatch (Batch const& batch) = 0;
// Called after stopAsync when there is no more pending write
virtual void writeStopped () = 0;
};
/** Create a batch writer. */
@@ -170,6 +178,9 @@ public:
/** Get an estimate of the amount of writing I/O pending. */
int getWriteLoad ();
/** Called to notify that the NodeStore wants to stop. */
void stopAsync ();
private:
void performScheduledTask ();
void writeBatch ();
@@ -280,6 +291,9 @@ public:
/** Estimate the number of write operations pending. */
virtual int getWriteLoad () = 0;
/** Called to notify the Backend that the NodeStore wants to stop. */
virtual void stopAsync () = 0;
};
//--------------------------------------------------------------------------
@@ -331,7 +345,9 @@ public:
@return The opened database.
*/
static NodeStore* New (Parameters const& backendParameters,
static NodeStore* New (char const* name,
Service& parent,
Parameters const& backendParameters,
Parameters fastBackendParameters = Parameters (),
Scheduler& scheduler = getSynchronousScheduler ());

View File

@@ -7,7 +7,8 @@
class NullBackendFactory::Backend : public NodeStore::Backend
{
public:
Backend ()
explicit Backend (NodeStore::Scheduler& scheduler)
: m_scheduler (scheduler)
{
}
@@ -41,6 +42,14 @@ public:
{
return 0;
}
void stopAsync ()
{
m_scheduler.scheduledTasksStopped ();
}
private:
NodeStore::Scheduler& m_scheduler;
};
//------------------------------------------------------------------------------
@@ -66,9 +75,9 @@ String NullBackendFactory::getName () const
NodeStore::Backend* NullBackendFactory::createInstance (
size_t,
StringPairArray const&,
NodeStore::Scheduler&)
NodeStore::Scheduler& scheduler)
{
return new NullBackendFactory::Backend;
return new NullBackendFactory::Backend (scheduler);
}
//------------------------------------------------------------------------------