1
0

Event system and debug consumer added

This commit is contained in:
Scott E. Graves
2017-02-23 13:45:49 -06:00
parent 9bd8d9881b
commit f5e1c66dbc
11 changed files with 400 additions and 63 deletions

View File

@@ -0,0 +1,18 @@
#include "stdafx.h"
#include "DebugConsumer.h"
using namespace Sia::Api;
CDebugConsumer::CDebugConsumer()
{
CEventSystem::EventSystem.AddEventConsumer([this](const CEvent& event) { this->ProcessEvent(event); });
}
CDebugConsumer::~CDebugConsumer()
{
}
void CDebugConsumer::ProcessEvent(const CEvent& eventData)
{
OutputDebugString(eventData.GetSingleLineMessage().c_str());
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <SiaCommon.h>
#include <EventSystem.h>
NS_BEGIN(Sia)
NS_BEGIN(Api)
class AFX_EXT_CLASS CDebugConsumer
{
public:
CDebugConsumer();
public:
~CDebugConsumer();
private:
void ProcessEvent(const CEvent& eventData);
};
NS_END(2);

View File

@@ -5,15 +5,77 @@ using namespace Sia::Api;
CEventSystem CEventSystem::EventSystem;
CEventSystem::CEventSystem()
CEventSystem::CEventSystem() :
_stopEvent(INVALID_HANDLE_VALUE)
{
}
CEventSystem::~CEventSystem()
{
Stop();
::CloseHandle(_stopEvent);
}
void CEventSystem::NotifyEvent(const CEvent& eventData)
void CEventSystem::ProcessEvents()
{
while (::WaitForSingleObject(_stopEvent, 10) == WAIT_TIMEOUT)
{
CEventPtr eventData;
do
{
{
std::lock_guard<std::mutex> l(_eventMutex);
if (_eventQueue.size())
{
eventData = _eventQueue.front();
_eventQueue.pop_front();
}
else
{
eventData.reset();
}
}
if (eventData)
{
for (auto& v : _eventConsumers)
{
v(*eventData);
}
}
} while (eventData);
}
}
void CEventSystem::NotifyEvent(CEventPtr eventData)
{
std::lock_guard<std::mutex> l(_eventMutex);
_eventQueue.push_back(eventData);
}
void CEventSystem::AddEventConsumer(std::function<void(const CEvent&)> consumer)
{
if (!_processThread)
{
_eventConsumers.push_back(consumer);
}
}
void CEventSystem::Start()
{
if (!_processThread)
{
_stopEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
_processThread.reset(new std::thread([this]() {ProcessEvents(); }));
}
}
void CEventSystem::Stop()
{
if (_processThread)
{
::SetEvent(_stopEvent);
_processThread->join();
_processThread.reset();
}
}

View File

@@ -6,9 +6,18 @@ NS_BEGIN(Api)
class AFX_EXT_CLASS CEvent
{
public:
virtual ~CEvent() {}
public:
virtual String GetSingleLineMessage() const = 0;
};
typedef std::shared_ptr<CEvent> CEventPtr;
#define CreateSystemEvent(E) CEventPtr(new E)
#define CreateSystemEventConsumer(E) [=](const CEvent&) -> void { E(e); }
// Singleton
class AFX_EXT_CLASS CEventSystem
{
@@ -25,10 +34,23 @@ public:
CEventSystem& operator=(CEventSystem&&) = delete;
CEventSystem& operator=(const CEventSystem&) = delete;
private:
HANDLE _stopEvent;
std::deque<CEventPtr> _eventQueue;
std::deque<std::function<void(const CEvent&)>> _eventConsumers;
std::mutex _eventMutex;
std::unique_ptr<std::thread> _processThread;
public:
static CEventSystem EventSystem;
private:
void ProcessEvents();
public:
void NotifyEvent(const CEvent& eventData);
void AddEventConsumer(std::function<void(const CEvent&)> consumer);
void NotifyEvent(CEventPtr eventData);
void Start();
void Stop();
};
NS_END(2)

View File

@@ -190,6 +190,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="AutoThread.cpp" />
<ClCompile Include="DebugConsumer.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -229,6 +230,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="AutoThread.h" />
<ClInclude Include="DebugConsumer.h" />
<ClInclude Include="EventSystem.h" />
<ClInclude Include="json.hpp" />
<ClInclude Include="Resource.h" />

View File

@@ -63,6 +63,9 @@
<ClCompile Include="EventSystem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DebugConsumer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="SiaDrive.Api.def">
@@ -106,6 +109,9 @@
<ClInclude Include="EventSystem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DebugConsumer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SiaDrive.Api.rc">

View File

@@ -31,6 +31,36 @@ static void CreateTableIfNotFound(SQLite::Database* database, const String& tabl
database->exec(CW2A(sqlCreate.c_str()));
}
String CUploadManager::UploadStatusToString(const UploadStatus& uploadStatus)
{
switch (uploadStatus)
{
case UploadStatus::Complete:
return L"Complete";
case UploadStatus::Copying:
return L"Copying";
case UploadStatus::Error:
return L"Error";
case UploadStatus::Modified:
return L"Modified";
case UploadStatus::NotFound:
return L"Not Found";
case UploadStatus::Queued:
return L"Queued";
case UploadStatus::Uploading:
return L"Uploading";
default:
return L"!!Not Defined!!";
}
}
CUploadManager::CUploadManager(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) :
CAutoThread(siaCurl, siaDriveConfig),
_uploadDatabase(siaDriveConfig->GetRenter_UploadDbFilePath(), SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE),
@@ -50,33 +80,33 @@ CUploadManager::~CUploadManager()
void CUploadManager::FileUploadAction(const String& siaPath, const String& filePath, const String& tempSourcePath, const String& siaDriveFilePath)
{
CEventSystem::EventSystem.NotifyEvent(CreatingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(CreatingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath)));
if (RetryableAction(::CopyFile(filePath.c_str(), tempSourcePath.c_str(), FALSE), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
{
// Delete existing '.siadrive' file, if found
// !!Should never come here. If so, there was a problem with startup clean-up
if (!RetryDeleteFileIfExists(siaDriveFilePath))
{
CEventSystem::EventSystem.NotifyEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
}
// Rename '.siadrive.temp' to '.siadrive'
CEventSystem::EventSystem.NotifyEvent(RenamingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath, siaDriveFilePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
if (RetryableAction(::MoveFile(tempSourcePath.c_str(), siaDriveFilePath.c_str()), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
{
// TODO Change status to 'Queued'
}
else
{
CEventSystem::EventSystem.NotifyEvent(RenamingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath, siaDriveFilePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
if (!RetryDeleteFileIfExists(tempSourcePath))
{
CEventSystem::EventSystem.NotifyEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
}
if (!RetryDeleteFileIfExists(siaDriveFilePath))
{
CEventSystem::EventSystem.NotifyEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
}
// Requeue
@@ -85,13 +115,13 @@ void CUploadManager::FileUploadAction(const String& siaPath, const String& fileP
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreatingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(CreatingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
// If temp copy fails, try to delete
// If partial copy and file is unable to be deleted, log warning
if (!RetryDeleteFileIfExists(tempSourcePath))
{
CEventSystem::EventSystem.NotifyEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
}
// Requeue
@@ -247,6 +277,7 @@ UploadStatus CUploadManager::GetUploadStatus(const String& siaPath)
UploadError CUploadManager::AddOrUpdate(const String& siaPath, String filePath)
{
UploadError ret = UploadError::Success;
// Relative to absolute and grab parent folder of source
String rootPath;
{
@@ -262,6 +293,8 @@ UploadError CUploadManager::AddOrUpdate(const String& siaPath, String filePath)
rootPath = temp;
}
if (::PathFileExists(filePath.c_str()))
{
// Lock here - if file is modified again before a prior upload is complete, delete it and
// start again later
std::lock_guard<std::mutex> l(_uploadMutex);
@@ -274,7 +307,7 @@ UploadError CUploadManager::AddOrUpdate(const String& siaPath, String filePath)
if (query.executeStep())
{
UploadStatus uploadStatus = static_cast<UploadStatus>(static_cast<unsigned>(query.getColumn(2)));
CEventSystem::EventSystem.NotifyEvent(ExistingUploadFound(siaPath, filePath, uploadStatus));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(ExistingUploadFound(siaPath, filePath, uploadStatus)));
if (uploadStatus == UploadStatus::Uploading)
{
// set to modified
@@ -305,7 +338,12 @@ UploadError CUploadManager::AddOrUpdate(const String& siaPath, String filePath)
// Queue file upload operation
std::lock_guard<std::mutex> l2(_fileQueueMutex);
_fileQueue.push_back([=]() { this->FileUploadAction(siaPath, filePath, tempSourcePath, siaDriveFilePath); });
CEventSystem::EventSystem.NotifyEvent(NewUploadAdded(siaPath, filePath, siaDriveFilePath));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(NewUploadAdded(siaPath, filePath, siaDriveFilePath)));
}
}
else
{
ret = UploadError::SourceFileNotFound;
}
return ret;

View File

@@ -24,7 +24,8 @@ public:
enum class _UploadError
{
Success
Success,
SourceFileNotFound
};
private:
@@ -58,6 +59,9 @@ protected:
virtual void AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) override;
void FileThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig);
public:
static String UploadStatusToString(const _UploadStatus& uploadStatus);
public:
_UploadStatus GetUploadStatus(const String& siaPath);
_UploadError AddOrUpdate(const String& siaPath, String filePath);
@@ -74,8 +78,28 @@ class CreatingTemporarySiaDriveFile :
public CEvent
{
public:
CreatingTemporarySiaDriveFile(const String& siaPath, const String& filePath, const String& tempSourcePath)
CreatingTemporarySiaDriveFile(const String& siaPath, const String& filePath, const String& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~CreatingTemporarySiaDriveFile()
{
}
private:
const String _siaPath;
const String _filePath;
const String _tempSourcePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"CreatingTemporarySiaDriveFile\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tTSP|" + _tempSourcePath;
}
};
@@ -83,70 +107,207 @@ class CreatingTemporarySiaDriveFileFailed :
public CEvent
{
public:
CreatingTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath)
CreatingTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~CreatingTemporarySiaDriveFileFailed()
{
}
private:
const String _siaPath;
const String _filePath;
const String _tempSourcePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"CreatingTemporarySiaDriveFileFailed\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tTSP|" + _tempSourcePath;
}
};
class DeleteSiaDriveFileFailed :
public CEvent
{
public:
DeleteSiaDriveFileFailed(const String& siaPath, const String& filePath, const String& siaDriveFilePath)
DeleteSiaDriveFileFailed(const String& siaPath, const String& filePath, const String& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~DeleteSiaDriveFileFailed()
{
}
private:
const String _siaPath;
const String _filePath;
const String _siaDriveFilePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"DeleteSiaDriveFileFailed\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tSDP|" + _siaDriveFilePath;
}
};
class DeleteTemporarySiaDriveFileFailed :
public CEvent
{
public:
DeleteTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath)
DeleteTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~DeleteTemporarySiaDriveFileFailed()
{
}
private:
const String _siaPath;
const String _filePath;
const String _tempSourcePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"DeleteTemporarySiaDriveFileFailed\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tTSP|" + _tempSourcePath;
}
};
class RenamingTemporarySiaDriveFile :
public CEvent
{
public:
RenamingTemporarySiaDriveFile(const String& siaPath, const String& filePath, const String& tempSourcePath, const String& siaDriveFilePath)
RenamingTemporarySiaDriveFile(const String& siaPath, const String& filePath, const String& tempSourcePath, const String& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~RenamingTemporarySiaDriveFile()
{
}
private:
const String _siaPath;
const String _filePath;
const String _tempSourcePath;
const String _siaDriveFilePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"RenamingTemporarySiaDriveFile\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tTSP|" + _tempSourcePath + L"\n\tSDP|" + _siaDriveFilePath;
}
};
class RenamingTemporarySiaDriveFileFailed :
public CEvent
{
public:
RenamingTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath, const String& siaDriveFilePath)
RenamingTemporarySiaDriveFileFailed(const String& siaPath, const String& filePath, const String& tempSourcePath, const String& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~RenamingTemporarySiaDriveFileFailed()
{
}
private:
const String _siaPath;
const String _filePath;
const String _tempSourcePath;
const String _siaDriveFilePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"RenamingTemporarySiaDriveFileFailed\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tTSP|" + _tempSourcePath + L"\n\tSDP|" + _siaDriveFilePath;
}
};
class ExistingUploadFound :
public CEvent
{
public:
ExistingUploadFound(const String& siaPath, const String& filePath, const UploadStatus& uploadStatus)
ExistingUploadFound(const String& siaPath, const String& filePath, const UploadStatus& uploadStatus) :
_siaPath(siaPath),
_filePath(filePath),
_uploadStatus(uploadStatus)
{
}
public:
virtual ~ExistingUploadFound()
{
}
private:
const String _siaPath;
const String _filePath;
const UploadStatus _uploadStatus;
public:
virtual String GetSingleLineMessage() const override
{
return L"ExistingUploadFound\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tST|" + CUploadManager::UploadStatusToString(_uploadStatus);
}
};
class NewUploadAdded :
public CEvent
{
public:
NewUploadAdded(const String& siaPath, const String& filePath, const String& siaDriveFilePath)
NewUploadAdded(const String& siaPath, const String& filePath, const String& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~NewUploadAdded()
{
}
private:
const String _siaPath;
const String _filePath;
const String _siaDriveFilePath;
public:
virtual String GetSingleLineMessage() const override
{
return L"NewUploadAdded\n\tSP|" + _siaPath + L"\n\tFP|" + _filePath + L"\n\tSDP|" + _siaDriveFilePath;
}
};
NS_END(2)

View File

@@ -39,3 +39,5 @@
#include <afxsock.h> // MFC socket extensions
#include <thread>
#include <deque>
#include <mutex>

View File

@@ -734,8 +734,7 @@ Global
{B3DF927F-A1CE-4F50-A621-A4C3A06E4F8A}.RelWithDebInfo|x64.Build.0 = Release|x64
{B3DF927F-A1CE-4F50-A621-A4C3A06E4F8A}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
{B3DF927F-A1CE-4F50-A621-A4C3A06E4F8A}.RelWithDebInfo|x86.Build.0 = Release|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.Debug|x64.ActiveCfg = Debug|x64
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.Debug|x64.Build.0 = Debug|x64
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.Debug|x64.ActiveCfg = Debug|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.Debug|x86.ActiveCfg = Debug|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.Debug|x86.Build.0 = Debug|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = Release|Win32
@@ -859,8 +858,7 @@ Global
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Win32
{BE7EE71D-6608-36DD-9687-D84AAE20C0A3}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Win32
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.Debug|x64.ActiveCfg = Debug|x64
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.Debug|x64.Build.0 = Debug|x64
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.Debug|x64.ActiveCfg = Debug|Win32
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.Debug|x86.ActiveCfg = Debug|Win32
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.Debug|x86.Build.0 = Debug|Win32
{92EF9CAE-3F0C-31D5-9556-62586CC5072D}.DLL Debug - DLL OpenSSL - DLL LibSSH2|x64.ActiveCfg = Release|Win32

View File

@@ -5,6 +5,7 @@
#include "MockSiad.h"
#include "SiaDriveConfig.h"
#include "UnitTestConfig.h"
#include <DebugConsumer.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Sia::Api;
@@ -16,8 +17,14 @@ namespace UnitTests
private:
const SiaHostConfig hostConfig = { TEST_SERVER_AND_PORT, TEST_SERVER_VERSION };
static std::unique_ptr<CMockSiad> siad;
static CDebugConsumer _debugConsumer;
public:
TEST_CLASS_INITIALIZE(ClassInit)
{
CEventSystem::EventSystem.Start();
}
TEST_METHOD_INITIALIZE(Initialize)
{
// Always delete DB before next test
@@ -62,4 +69,5 @@ namespace UnitTests
};
std::unique_ptr<CMockSiad> UnitTests::siad;
CDebugConsumer UnitTests::_debugConsumer;
}