|
|
|
@@ -1,10 +1,8 @@
|
|
|
|
|
|
|
|
|
|
#include <SQLiteCpp/Exception.h>
|
|
|
|
|
#include <uploadmanager.h>
|
|
|
|
|
#include <siaapi.h>
|
|
|
|
|
#include <eventsystem.h>
|
|
|
|
|
#include <siadriveconfig.h>
|
|
|
|
|
#include <sqlite3.h>
|
|
|
|
|
#include <filepath.h>
|
|
|
|
|
using namespace Sia::Api;
|
|
|
|
|
|
|
|
|
@@ -67,9 +65,6 @@ SString CUploadManager::UploadStatusToString(const UploadStatus& uploadStatus)
|
|
|
|
|
case UploadStatus::Complete:
|
|
|
|
|
return L"Complete";
|
|
|
|
|
|
|
|
|
|
case UploadStatus::Copying:
|
|
|
|
|
return L"Copying";
|
|
|
|
|
|
|
|
|
|
case UploadStatus::Error:
|
|
|
|
|
return L"Error";
|
|
|
|
|
|
|
|
|
@@ -95,8 +90,7 @@ SString CUploadManager::UploadStatusToString(const UploadStatus& uploadStatus)
|
|
|
|
|
|
|
|
|
|
CUploadManager::CUploadManager(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) :
|
|
|
|
|
CAutoThread(siaCurl, siaDriveConfig),
|
|
|
|
|
_uploadDatabase(siaDriveConfig->GetRenter_UploadDbFilePath(), SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE),
|
|
|
|
|
_fileThread(siaCurl, siaDriveConfig, [this](const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) { this->FileThreadCallback(siaCurl, siaDriveConfig); })
|
|
|
|
|
_uploadDatabase(siaDriveConfig->GetRenter_UploadDbFilePath(), SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE)
|
|
|
|
|
{
|
|
|
|
|
CreateTableIfNotFound(&_uploadDatabase, UPLOAD_TABLE, UPLOAD_TABLE_COLUMNS);
|
|
|
|
|
|
|
|
|
@@ -119,13 +113,11 @@ CUploadManager::CUploadManager(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriv
|
|
|
|
|
|
|
|
|
|
// Begin normal processing
|
|
|
|
|
StartAutoThread();
|
|
|
|
|
_fileThread.StartAutoThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CUploadManager::~CUploadManager()
|
|
|
|
|
{
|
|
|
|
|
// Stop all processing
|
|
|
|
|
_fileThread.StopAutoThread();
|
|
|
|
|
StopAutoThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -134,9 +126,8 @@ void CUploadManager::UpdateFileQueueOnStartup()
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Re-add Copying and Remove
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_SIA_PATH_AND_2_STATUS);
|
|
|
|
|
query.bind("@status1", static_cast<unsigned>(UploadStatus::Copying));
|
|
|
|
|
query.bind("@status1", static_cast<unsigned>(UploadStatus::Remove));
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS);
|
|
|
|
|
query.bind("@status", static_cast<unsigned>(UploadStatus::Remove));
|
|
|
|
|
while (query.executeStep())
|
|
|
|
|
{
|
|
|
|
|
SString siaPath = static_cast<const char*>(query.getColumn(query.getColumnIndex("sia_path")));
|
|
|
|
@@ -152,16 +143,10 @@ void CUploadManager::UpdateFileQueueOnStartup()
|
|
|
|
|
SString siaDriveFileName = GenerateSha256(&filePath[3]) + L".siadrive";
|
|
|
|
|
FilePath tempSourcePath(rootPath, (siaDriveFileName + L".temp"));
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> l(_fileQueueMutex);
|
|
|
|
|
if (uploadStatus == UploadStatus::Remove)
|
|
|
|
|
{
|
|
|
|
|
_fileQueue.push_back([=]() { this->FileAction(CSiaCurl(GetHostConfig()), siaPath, filePath, "", siaDriveFilePath, true); });
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileRemoveAdded(siaPath)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_fileQueue.push_back([=]() { this->FileAction(CSiaCurl(GetHostConfig()), siaPath, filePath, tempSourcePath, siaDriveFilePath, false); });
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(NewFileAdded(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
this->HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath, siaDriveFilePath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -192,24 +177,6 @@ void CUploadManager::DeleteFilesRemovedFromSia(const CSiaCurl& siaCurl, CSiaDriv
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CUploadManager::FileThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig)
|
|
|
|
|
{
|
|
|
|
|
std::function<void()> nextFile = nullptr;
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l(_fileQueueMutex);
|
|
|
|
|
if (_fileQueue.size())
|
|
|
|
|
{
|
|
|
|
|
nextFile = _fileQueue.front();
|
|
|
|
|
_fileQueue.pop_front();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nextFile)
|
|
|
|
|
{
|
|
|
|
|
nextFile();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CUploadManager::HandleFileRemove(const CSiaCurl& siaCurl, const SString& siaPath, const SString& siaDriveFilePath)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
@@ -244,11 +211,9 @@ void CUploadManager::HandleFileRemove(const CSiaCurl& siaCurl, const SString& si
|
|
|
|
|
if (deleteFromDb)
|
|
|
|
|
{
|
|
|
|
|
json response;
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete") + siaPath, {}, response);
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete/") + siaPath, {}, response);
|
|
|
|
|
if (ApiSuccess(cerror))
|
|
|
|
|
{
|
|
|
|
|
// TODO validate response
|
|
|
|
|
|
|
|
|
|
SQLite::Statement del(_uploadDatabase, DELETE_UPLOAD);
|
|
|
|
|
del.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
|
|
|
|
|
if (del.exec() == 1)
|
|
|
|
@@ -275,129 +240,58 @@ void CUploadManager::HandleFileRemove(const CSiaCurl& siaCurl, const SString& si
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CUploadManager::HandleAddFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath)
|
|
|
|
|
bool CUploadManager::CreateSiaDriveFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath)
|
|
|
|
|
{
|
|
|
|
|
// Check for retry condition
|
|
|
|
|
if (!FilePath(tempSourcePath).IsFile() && FilePath(siaDriveFilePath).IsFile())
|
|
|
|
|
bool ret = false;
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(CreatingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
if (RetryableAction(::CopyFile(filePath.str().c_str(), tempSourcePath.str().c_str(), FALSE), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
// Delete existing '.siadrive' file, if found
|
|
|
|
|
// !!Should never come here. If so, there was a problem with startup clean-up
|
|
|
|
|
if (!RetryDeleteFileIfExists(siaDriveFilePath))
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l(_uploadMutex);
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_STATUS);
|
|
|
|
|
query.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
|
|
|
|
|
if (query.executeStep())
|
|
|
|
|
{
|
|
|
|
|
UploadStatus uploadStatus = static_cast<UploadStatus>(static_cast<unsigned>(query.getColumn(query.getColumnIndex("status"))));
|
|
|
|
|
if (uploadStatus == UploadStatus::Copying)
|
|
|
|
|
{
|
|
|
|
|
if (RetryDeleteFileIfExists(siaDriveFilePath))
|
|
|
|
|
{
|
|
|
|
|
SET_STATUS(UploadStatus::Queued, UploadAddedToQueue, ModifyUploadStatusFailed)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
}
|
|
|
|
|
catch (SQLite::Exception e)
|
|
|
|
|
|
|
|
|
|
// Rename '.siadrive.temp' to '.siadrive'
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
|
|
|
|
|
if (RetryableAction(::MoveFile(tempSourcePath.str().c_str(), siaDriveFilePath.str().c_str()), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DatabaseExceptionOccurred(e)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(CreatingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
if (RetryableAction(::CopyFile(filePath.str().c_str(), tempSourcePath.str().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))
|
|
|
|
|
if (RetryDeleteFileIfExists(tempSourcePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rename '.siadrive.temp' to '.siadrive'
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFile(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
|
|
|
|
|
if (RetryableAction(::MoveFile(tempSourcePath.str().c_str(), siaDriveFilePath.str().c_str()), DEFAULT_RETRY_COUNT, DEFAULT_RETRY_DELAY_MS))
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!RetryDeleteFileIfExists(tempSourcePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l(_uploadMutex);
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_STATUS);
|
|
|
|
|
query.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
|
|
|
|
|
if (query.executeStep())
|
|
|
|
|
{
|
|
|
|
|
UploadStatus uploadStatus = static_cast<UploadStatus>(static_cast<unsigned>(query.getColumn(query.getColumnIndex("status"))));
|
|
|
|
|
if (uploadStatus == UploadStatus::Copying)
|
|
|
|
|
{
|
|
|
|
|
SET_STATUS(UploadStatus::Queued, UploadAddedToQueue, ModifyUploadStatusFailed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (SQLite::Exception e)
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DatabaseExceptionOccurred(e)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
|
|
|
|
|
if (!RetryDeleteFileIfExists(tempSourcePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RetryDeleteFileIfExists(siaDriveFilePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Requeued
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RenamingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath, siaDriveFilePath)));
|
|
|
|
|
if (!RetryDeleteFileIfExists(tempSourcePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Requeued
|
|
|
|
|
if (!RetryDeleteFileIfExists(siaDriveFilePath))
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(CreatingTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
|
|
|
|
|
void CUploadManager::FileAction(const CSiaCurl& siaCurl, const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath, const bool& remove)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l(_fileActionMutex);
|
|
|
|
|
_activeSiaPath = siaPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (remove)
|
|
|
|
|
{
|
|
|
|
|
HandleFileRemove(siaCurl, siaPath, siaDriveFilePath);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HandleAddFile(siaPath, filePath, tempSourcePath, siaDriveFilePath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l(_fileActionMutex);
|
|
|
|
|
_activeSiaPath = "";
|
|
|
|
|
}
|
|
|
|
|
// 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(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig)
|
|
|
|
@@ -415,7 +309,7 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
|
|
|
|
|
std::lock_guard<std::mutex> l(_uploadMutex);
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_2_STATUS);
|
|
|
|
|
query.bind("@status1", static_cast<unsigned>(UploadStatus::Uploading));
|
|
|
|
|
query.bind("@status2", static_cast<unsigned>(UploadStatus::Modified));
|
|
|
|
|
query.bind("@status2", static_cast<unsigned>(UploadStatus::Modified));
|
|
|
|
|
|
|
|
|
|
fileTree->BuildTree(result);
|
|
|
|
|
if (query.executeStep())
|
|
|
|
@@ -437,17 +331,15 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
|
|
|
|
|
SET_STATUS(UploadStatus::Remove, ExternallyRemovedFileDetected, ModifyUploadStatusFailed)
|
|
|
|
|
if (statusUpdated)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l2(_fileQueueMutex);
|
|
|
|
|
_fileQueue.push_back([=]() { this->FileAction(CSiaCurl(GetHostConfig()), siaPath, filePath, "", siaDriveFilePath, true); });
|
|
|
|
|
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileRemoveAdded(siaPath)));
|
|
|
|
|
this->HandleFileRemove(siaCurl, siaPath, siaDriveFilePath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Changed file detected
|
|
|
|
|
else if (uploadStatus == UploadStatus::Modified)
|
|
|
|
|
{
|
|
|
|
|
json response;
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete") + siaPath, {}, response);
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete/") + siaPath, {}, response);
|
|
|
|
|
if (ApiSuccess(cerror))
|
|
|
|
|
{
|
|
|
|
|
// TODO validate response
|
|
|
|
@@ -491,24 +383,26 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// TODO Rethink this - could hang here for quite a while
|
|
|
|
|
std::lock_guard<std::mutex> l(_uploadMutex);
|
|
|
|
|
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS);
|
|
|
|
|
query.bind("@status", static_cast<unsigned>(UploadStatus::Queued));
|
|
|
|
|
|
|
|
|
|
// Lock here - if file is modified again before a prior upload is complete, delete it and
|
|
|
|
|
// start again later
|
|
|
|
|
if (query.executeStep())
|
|
|
|
|
{
|
|
|
|
|
SString siaPath = static_cast<const char*>(query.getColumn(query.getColumnIndex("sia_path")));
|
|
|
|
|
SString filePath = static_cast<const char*>(query.getColumn(query.getColumnIndex("file_path")));
|
|
|
|
|
|
|
|
|
|
// TODO Validate response
|
|
|
|
|
json response;
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/upload/") + siaPath, { {L"source", filePath} }, response);
|
|
|
|
|
if (ApiSuccess(cerror))
|
|
|
|
|
{
|
|
|
|
|
SET_STATUS(UploadStatus::Uploading, UploadToSiaStarted, ModifyUploadStatusFailed)
|
|
|
|
|
}
|
|
|
|
|
SString filePath = static_cast<const char*>(query.getColumn(query.getColumnIndex("file_path")));
|
|
|
|
|
SString sdFilePath = static_cast<const char*>(query.getColumn(query.getColumnIndex("sd_file_path")));
|
|
|
|
|
if (CreateSiaDriveFile(siaPath, filePath, sdFilePath + ".temp", sdFilePath))
|
|
|
|
|
{
|
|
|
|
|
// TODO Validate response
|
|
|
|
|
json response;
|
|
|
|
|
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/upload/") + siaPath, { {L"source", filePath} }, response);
|
|
|
|
|
if (ApiSuccess(cerror))
|
|
|
|
|
{
|
|
|
|
|
SET_STATUS(UploadStatus::Uploading, UploadToSiaStarted, ModifyUploadStatusFailed)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (const SQLite::Exception& e)
|
|
|
|
@@ -533,21 +427,6 @@ UploadStatus CUploadManager::GetUploadStatus(const SString& siaPath)
|
|
|
|
|
return uploadStatus;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The real source file is copied to a hidden file. The hidden filename is constructed by generating an SHA25 hash of the
|
|
|
|
|
// source path (all lowercase). '.siadrive.temp' will be used as the extension. After copy is successful, the extension
|
|
|
|
|
// is renamed to '.siadrive'. '.siadrive' files will be hidden/system and used by the Dokan API for file i/o until Sia upload
|
|
|
|
|
// is complete. If a change occurs, the file will be deleted from Sia (cancelling the in-progress upload) and renamed to the
|
|
|
|
|
// real source path. The process will then start over again as if the file was new.
|
|
|
|
|
// If the file has been fully uploaded, the hidden file should not exist, so rename will not occur; however, the file
|
|
|
|
|
// will be deleted from Sia and treated as new.
|
|
|
|
|
// Uploads will always use the real file. User i/o will occur against the hidden file temporarily. Since upload will take
|
|
|
|
|
// longer to handle than a normal file copy, this seems to be the best compromise for performance.
|
|
|
|
|
//
|
|
|
|
|
// Error Scenarios:
|
|
|
|
|
// Crash before db update to status copying - file will be re-uploaded automatically, if complete; otherwise, deleted
|
|
|
|
|
// Crash before copy begins - on startup, check for copying status with no .siadrive
|
|
|
|
|
// Crash during copy - on startup, check for copying status and delete .siadrive
|
|
|
|
|
// Crash after copy but before db update - on startup, check for copying status and delete .siadrive
|
|
|
|
|
UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath)
|
|
|
|
|
{
|
|
|
|
|
UploadError ret = UploadError::Success;
|
|
|
|
@@ -568,6 +447,7 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
|
|
|
|
|
query.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
|
|
|
|
|
query.bind("@status1", static_cast<unsigned>(UploadStatus::Uploading));
|
|
|
|
|
query.bind("@status2", static_cast<unsigned>(UploadStatus::Modified));
|
|
|
|
|
|
|
|
|
|
// Check copying
|
|
|
|
|
if (query.executeStep())
|
|
|
|
|
{
|
|
|
|
@@ -585,7 +465,6 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
|
|
|
|
|
// TODO Case sensative file names? Going to be a bit of an issue.
|
|
|
|
|
SString siaDriveFileName = GenerateSha256(&filePath[3]) + L".siadrive";
|
|
|
|
|
FilePath siaDriveFilePath(rootPath, siaDriveFileName);
|
|
|
|
|
FilePath tempSourcePath(rootPath, (siaDriveFileName + L".temp"));
|
|
|
|
|
|
|
|
|
|
// Add to db
|
|
|
|
|
try
|
|
|
|
@@ -594,13 +473,10 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
|
|
|
|
|
insert.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
|
|
|
|
|
insert.bind("@file_path", SString::ToUtf8(filePath).c_str());
|
|
|
|
|
insert.bind("@sd_file_path", SString::ToUtf8(siaDriveFileName).c_str());
|
|
|
|
|
insert.bind("@status", static_cast<unsigned>(UploadStatus::Copying));
|
|
|
|
|
insert.bind("@status", static_cast<unsigned>(UploadStatus::Queued));
|
|
|
|
|
if (insert.exec() == 1)
|
|
|
|
|
{
|
|
|
|
|
// Queue file upload operation
|
|
|
|
|
std::lock_guard<std::mutex> l2(_fileQueueMutex);
|
|
|
|
|
_fileQueue.push_back([=]() { this->FileAction(CSiaCurl(GetHostConfig()), siaPath, filePath, tempSourcePath, siaDriveFilePath, false); });
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(NewFileAdded(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(UploadAddedToQueue(siaPath, filePath, siaDriveFilePath)));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@@ -650,7 +526,6 @@ UploadError CUploadManager::Remove(const SString& siaPath)
|
|
|
|
|
case UploadStatus::Complete:
|
|
|
|
|
case UploadStatus::Queued:
|
|
|
|
|
case UploadStatus::Modified:
|
|
|
|
|
case UploadStatus::Copying:
|
|
|
|
|
case UploadStatus::Uploading:
|
|
|
|
|
{
|
|
|
|
|
SET_STATUS(UploadStatus::Remove, UploadStatusSetToRemoved, ModifyUploadStatusFailed)
|
|
|
|
@@ -671,10 +546,8 @@ UploadError CUploadManager::Remove(const SString& siaPath)
|
|
|
|
|
|
|
|
|
|
if (remove)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> l2(_fileQueueMutex);
|
|
|
|
|
_fileQueue.push_back([=]() { this->FileAction(CSiaCurl(GetHostConfig()), siaPath, filePath, "", siaDriveFilePath, true); });
|
|
|
|
|
|
|
|
|
|
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileRemoveAdded(siaPath)));
|
|
|
|
|
this->HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath, siaDriveFilePath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|