1
0

Continue download support

This commit is contained in:
Scott E. Graves
2017-03-30 23:26:12 -05:00
parent 0292a56aa4
commit c199214fa8
4 changed files with 132 additions and 601 deletions

View File

@@ -56,12 +56,12 @@ private:
private:
CSiaDriveConfig* GetSiaDriveConfig() const { return _siaDriveConfig; }
bool HandleFileRemove(const CSiaCurl& siaCurl, const SString& siaPath, const SString& siaDriveFilePath = "");
bool CreateSiaDriveFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath);
bool HandleFileRemove(const CSiaCurl& siaCurl, const SString& siaPath);
void DeleteFilesRemovedFromSia(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig, const bool& isStartup = false);
protected:
virtual void AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriveConfig) override;
public:
static SString UploadStatusToString(const _UploadStatus& uploadStatus);
@@ -76,48 +76,13 @@ typedef CUploadManager::_UploadErrorCode UploadErrorCode;
typedef CSiaError<CUploadManager::_UploadErrorCode> UploadError;
// Event Notifications
class CreatingTemporarySiaDriveFile :
public CEvent
{
public:
CreatingTemporarySiaDriveFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~CreatingTemporarySiaDriveFile()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"CreatingTemporarySiaDriveFile|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new CreatingTemporarySiaDriveFile(_siaPath, _filePath, _tempSourcePath));
}
};
class FileAddedToQueue :
public CEvent
{
public:
FileAddedToQueue(const SString& siaPath, const SString& filePath, const SString& siaDriveFilePath) :
FileAddedToQueue(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath),
_siaDriveFilePath(siaDriveFilePath)
_filePath(filePath)
{
}
@@ -130,17 +95,16 @@ public:
private:
const SString _siaPath;
const SString _filePath;
const SString _siaDriveFilePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"FileAddedToQueue|SP|" + _siaPath + L"|FP|" + _filePath + "|SFP|" + _siaDriveFilePath;
return L"FileAddedToQueue|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new FileAddedToQueue(_siaPath, _filePath, _siaDriveFilePath));
return std::shared_ptr<CEvent>(new FileAddedToQueue(_siaPath, _filePath));
}
};
@@ -176,38 +140,6 @@ public:
}
};
class ModifiedUploadQueued :
public CEvent
{
public:
ModifiedUploadQueued(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
}
public:
virtual ~ModifiedUploadQueued()
{
}
private:
const SString _siaPath;
const SString _filePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"ModifiedUploadQueued|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new ModifiedUploadQueued(_siaPath, _filePath));
}
};
class UploadToSiaStarted :
public CEvent
{
@@ -240,11 +172,11 @@ public:
}
};
class UploadComplete :
class UploadToSiaComplete :
public CEvent
{
public:
UploadComplete(const SString& siaPath, const SString& filePath) :
UploadToSiaComplete(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
@@ -252,7 +184,7 @@ public:
}
public:
virtual ~UploadComplete()
virtual ~UploadToSiaComplete()
{
}
@@ -263,20 +195,20 @@ private:
public:
virtual SString GetSingleLineMessage() const override
{
return L"UploadComplete|SP|" + _siaPath + L"|FP|" + _filePath;
return L"UploadToSiaComplete|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new UploadComplete(_siaPath, _filePath));
return std::shared_ptr<CEvent>(new UploadToSiaComplete(_siaPath, _filePath));
}
};
class FileRemoved :
class FileRemovedFromSia :
public CEvent
{
public:
FileRemoved(const SString& siaPath, const SString& filePath) :
FileRemovedFromSia(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
@@ -284,7 +216,7 @@ public:
}
public:
virtual ~FileRemoved()
virtual ~FileRemovedFromSia()
{
}
@@ -295,84 +227,20 @@ private:
public:
virtual SString GetSingleLineMessage() const override
{
return L"FileRemoved|SP|" + _siaPath + L"|FP|" + _filePath;
return L"FileRemovedFromSia|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new FileRemoved(_siaPath, _filePath));
return std::shared_ptr<CEvent>(new FileRemovedFromSia(_siaPath, _filePath));
}
};
class UploadStatusSetToModified :
class FailedToRemoveFileFromSia :
public CEvent
{
public:
UploadStatusSetToModified(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
}
public:
virtual ~UploadStatusSetToModified()
{
}
private:
const SString _siaPath;
const SString _filePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"UploadStatusSetToModified|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new UploadStatusSetToModified(_siaPath, _filePath));
}
};
class UploadStatusSetToRemoved :
public CEvent
{
public:
UploadStatusSetToRemoved(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
}
public:
virtual ~UploadStatusSetToRemoved()
{
}
private:
const SString _siaPath;
const SString _filePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"UploadStatusSetToRemoved|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new UploadStatusSetToRemoved(_siaPath, _filePath));
}
};
class FailedToDeleteFromSia :
public CEvent
{
public:
FailedToDeleteFromSia(const SString& siaPath, const SString& filePath, const SiaCurlError& curlError) :
FailedToRemoveFileFromSia(const SString& siaPath, const SString& filePath, const SiaCurlError& curlError) :
_siaPath(siaPath),
_filePath(filePath),
_curlError(curlError)
@@ -381,7 +249,7 @@ public:
}
public:
virtual ~FailedToDeleteFromSia()
virtual ~FailedToRemoveFileFromSia()
{
}
@@ -393,12 +261,12 @@ private:
public:
virtual SString GetSingleLineMessage() const override
{
return L"FailedToDeleteFromSia|SP|" + _siaPath + L"|FP|" + _filePath;
return L"FailedToRemoveFileFromSia|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new FailedToDeleteFromSia(_siaPath, _filePath, _curlError));
return std::shared_ptr<CEvent>(new FailedToRemoveFileFromSia(_siaPath, _filePath, _curlError));
}
};
@@ -438,214 +306,6 @@ public:
}
};
class CreatingTemporarySiaDriveFileFailed :
public CEvent
{
public:
CreatingTemporarySiaDriveFileFailed(const SString& siaPath, const SString& filePath, const SString& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~CreatingTemporarySiaDriveFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"CreatingTemporarySiaDriveFileFailed|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new CreatingTemporarySiaDriveFileFailed(_siaPath, _filePath, _tempSourcePath));
}
};
class DeleteSiaDriveFileFailed :
public CEvent
{
public:
DeleteSiaDriveFileFailed(const SString& siaPath, const SString& filePath, const SString& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~DeleteSiaDriveFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _siaDriveFilePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"DeleteSiaDriveFileFailed|SP|" + _siaPath + L"|FP|" + _filePath + L"|SDP|" + _siaDriveFilePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new DeleteSiaDriveFileFailed(_siaPath, _filePath, _siaDriveFilePath));
}
};
class RenameModifiedFileFailed :
public CEvent
{
public:
RenameModifiedFileFailed(const SString& siaPath, const SString& filePath, const SString& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~RenameModifiedFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"RenameModifiedFileFailed|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new RenameModifiedFileFailed(_siaPath, _filePath, _tempSourcePath));
}
};
class DeleteTemporarySiaDriveFileFailed :
public CEvent
{
public:
DeleteTemporarySiaDriveFileFailed(const SString& siaPath, const SString& filePath, const SString& tempSourcePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath)
{
}
public:
virtual ~DeleteTemporarySiaDriveFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"DeleteTemporarySiaDriveFileFailed|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new DeleteTemporarySiaDriveFileFailed(_siaPath, _filePath, _tempSourcePath));
}
};
class RenamingTemporarySiaDriveFile :
public CEvent
{
public:
RenamingTemporarySiaDriveFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~RenamingTemporarySiaDriveFile()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
const SString _siaDriveFilePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"RenamingTemporarySiaDriveFile|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath + L"|SDP|" + _siaDriveFilePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new RenamingTemporarySiaDriveFile(_siaPath, _filePath, _tempSourcePath, _siaDriveFilePath));
}
};
class RenamingTemporarySiaDriveFileFailed :
public CEvent
{
public:
RenamingTemporarySiaDriveFileFailed(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath) :
_siaPath(siaPath),
_filePath(filePath),
_tempSourcePath(tempSourcePath),
_siaDriveFilePath(siaDriveFilePath)
{
}
public:
virtual ~RenamingTemporarySiaDriveFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
const SString _tempSourcePath;
const SString _siaDriveFilePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"RenamingTemporarySiaDriveFileFailed|SP|" + _siaPath + L"|FP|" + _filePath + L"|TSP|" + _tempSourcePath + L"|SDP|" + _siaDriveFilePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new RenamingTemporarySiaDriveFileFailed(_siaPath, _filePath, _tempSourcePath, _siaDriveFilePath));
}
};
class DatabaseInsertFailed :
public CEvent
{
@@ -714,72 +374,6 @@ public:
}
};
class RemoveFileFailed :
public CEvent
{
public:
RemoveFileFailed(const SString& siaPath, const SString& filePath) :
_siaPath(siaPath),
_filePath(filePath)
{
}
public:
virtual ~RemoveFileFailed()
{
}
private:
const SString _siaPath;
const SString _filePath;
public:
virtual SString GetSingleLineMessage() const override
{
return L"RemoveFileFailed|SP|" + _siaPath + L"|FP|" + _filePath;
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new RemoveFileFailed(_siaPath, _filePath));
}
};
class ExistingUploadFound :
public CEvent
{
public:
ExistingUploadFound(const SString& siaPath, const SString& filePath, const UploadStatus& uploadStatus) :
_siaPath(siaPath),
_filePath(filePath),
_uploadStatus(uploadStatus)
{
}
public:
virtual ~ExistingUploadFound()
{
}
private:
const SString _siaPath;
const SString _filePath;
const UploadStatus _uploadStatus;
public:
virtual SString GetSingleLineMessage() const override
{
return L"ExistingUploadFound|SP|" + _siaPath + L"|FP|" + _filePath + L"|ST|" + CUploadManager::UploadStatusToString(_uploadStatus);
}
virtual std::shared_ptr<CEvent> Clone() const override
{
return std::shared_ptr<CEvent>(new ExistingUploadFound(_siaPath, _filePath, _uploadStatus));
}
};
class SourceFileNotFound :
public CEvent
{

View File

@@ -393,6 +393,7 @@ void CSiaDriveApp::SiaApiRefreshCallback(CefRefPtr<CefV8Context> context, const
#else
a
#endif
auto uiActions = global->GetValue("uiUpdate");
auto renterActions = uiActions->GetValue("Renter");
auto walletActions = uiActions->GetValue("Wallet");
@@ -421,6 +422,7 @@ void CSiaDriveApp::SiaApiRefreshCallback(CefRefPtr<CefV8Context> context, const
ExecuteSetter(context, renterActions, "setUsedFunds", SiaCurrencyToString(allocatedFunds - unspentFunds));
ExecuteSetter(context, renterActions, "setAvailableFunds", SiaCurrencyToString(unspentFunds));
ExecuteSetter(context, renterActions, "setHostCount", SString::FromUInt64(_siaApi->GetRenter()->GetHosts()));
global->GetValue("uiState")->SetValue("allocatedRenterFunds", CefV8Value::CreateString(SiaCurrencyToString(allocatedFunds).str()), V8_PROPERTY_ATTRIBUTE_NONE);
// Space
SiaCurrency totalUsedGb = _siaApi->GetRenter()->GetTotalUsedBytes() ? _siaApi->GetRenter()->GetTotalUsedBytes() / (1024.0 * 1024.0 * 1024.0) : 0.0;

View File

@@ -4,18 +4,18 @@
#include <eventsystem.h>
#include <siadriveconfig.h>
#include <filepath.h>
using namespace Sia::Api;
#define TABLE_CREATE L"create table if not exists %s (%s);"
#define UPLOAD_TABLE L"upload_table"
#define UPLOAD_TABLE_COLUMNS L"id integer primary key autoincrement, sia_path text unique not null, file_path text unique not null, sd_file_path text unique not null, status integer not null"
#define UPLOAD_TABLE_COLUMNS L"id integer primary key autoincrement, sia_path text unique not null, file_path text unique not null, status integer not null"
#define QUERY_STATUS "select * from upload_table where sia_path=@sia_path order by id desc limit 1;"
#define QUERY_UPLOADS_BY_STATUS "select * from upload_table where status=@status order by id desc limit 1;"
#define QUERY_UPLOADS_BY_2_STATUS "select * from upload_table where (status=@status1 or status=@status2) order by id desc limit 1;"
#define QUERY_UPLOADS_BY_SIA_PATH "select * from upload_table where sia_path=@sia_path order by id desc limit 1;"
#define QUERY_UPLOADS_BY_SIA_PATH_AND_STATUS "select * from upload_table where sia_path=@sia_path and status=@status order by id desc limit 1;"
#define UPDATE_STATUS "update upload_table set status=@status where sia_path=@sia_path;"
#define INSERT_UPLOAD "insert into upload_table (sia_path, status, file_path, sd_file_path) values (@sia_path, @status, @file_path, @sd_file_path);"
#define INSERT_UPLOAD "insert into upload_table (sia_path, status, file_path) values (@sia_path, @status, @file_path);"
#define DELETE_UPLOAD "delete from upload_table where sia_path=@sia_path;"
#define SET_STATUS(status, success_event, fail_event)\
@@ -89,17 +89,6 @@ CUploadManager::CUploadManager(const CSiaCurl& siaCurl, CSiaDriveConfig* siaDriv
{
CreateTableIfNotFound(&_uploadDatabase, UPLOAD_TABLE, UPLOAD_TABLE_COLUMNS);
// Clean-up cache folder
if (!RecurDeleteFilesByExtentsion(siaDriveConfig->GetCacheFolder(), L".siadrive"))
{
throw StartupException(L"Failed to remove '.siadrive' files");
}
if (!RecurDeleteFilesByExtentsion(siaDriveConfig->GetCacheFolder(), L".siadrive.temp"))
{
throw StartupException(L"Failed to remove '.siadrive.temp' files");
}
// Detect files that have been removed since last startup
DeleteFilesRemovedFromSia(siaCurl, siaDriveConfig, true);
@@ -133,102 +122,31 @@ void CUploadManager::DeleteFilesRemovedFromSia(const CSiaCurl& siaCurl, CSiaDriv
}
}
bool CUploadManager::HandleFileRemove(const CSiaCurl& siaCurl, const SString& siaPath, const SString& siaDriveFilePath)
bool CUploadManager::HandleFileRemove(const CSiaCurl& siaCurl, const SString& siaPath)
{
bool ret = false;
FilePath removeFilePath(GetSiaDriveConfig()->GetCacheFolder(), siaPath);
bool deleteFromSia = true;
if (removeFilePath.IsFile())
{
if (RetryDeleteFileIfExists(removeFilePath))
{
if (!siaDriveFilePath.IsNullOrEmpty() && !RetryDeleteFileIfExists(siaDriveFilePath))
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, removeFilePath, siaDriveFilePath)));
}
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(RemoveFileFailed(siaPath, removeFilePath)));
deleteFromSia = false;
}
}
if (deleteFromSia)
{
json response;
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete/") + siaPath, {}, response);
if (ApiSuccess(cerror))
{
SQLite::Statement del(_uploadDatabase, DELETE_UPLOAD);
del.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
if (del.exec() >= 0)
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileRemoved(siaPath, removeFilePath)));
ret = true;
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DatabaseDeleteFailed(siaPath, removeFilePath, del.getErrorMsg())));
}
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FailedToDeleteFromSia(siaPath, removeFilePath, cerror)));
}
}
return ret;
}
bool CUploadManager::CreateSiaDriveFile(const SString& siaPath, const SString& filePath, const SString& tempSourcePath, const SString& siaDriveFilePath)
{
bool ret = FilePath(siaDriveFilePath).IsFile();
if (!ret)
json response;
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/delete/") + siaPath, {}, response);
if (ApiSuccess(cerror))
{
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))
SQLite::Statement del(_uploadDatabase, DELETE_UPLOAD);
del.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
if (del.exec() >= 0)
{
// 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))
{
if (RetryDeleteFileIfExists(tempSourcePath))
{
ret = true;
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
}
}
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)));
}
}
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileRemovedFromSia(siaPath, removeFilePath)));
ret = true;
}
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
if (!RetryDeleteFileIfExists(tempSourcePath))
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteTemporarySiaDriveFileFailed(siaPath, filePath, tempSourcePath)));
}
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DatabaseDeleteFailed(siaPath, removeFilePath, del.getErrorMsg())));
}
}
else
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FailedToRemoveFileFromSia(siaPath, removeFilePath, cerror)));
}
return ret;
}
@@ -246,15 +164,14 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
// Lock here - if file is modified again before previously queued upload is complete, delete it and
// start again later
std::lock_guard<std::mutex> l(_uploadMutex);
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_2_STATUS);
query.bind("@status1", static_cast<unsigned>(UploadStatus::Uploading));
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS);
query.bind("@status", static_cast<unsigned>(UploadStatus::Uploading));
fileTree->BuildTree(result);
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")));
SString siaDriveFilePath = static_cast<const char*>(query.getColumn(query.getColumnIndex("sd_file_path")));
UploadStatus uploadStatus = static_cast<UploadStatus>(query.getColumn(query.getColumnIndex("status")).getUInt());
auto fileList = fileTree->GetFileList();
@@ -266,16 +183,12 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
// Removed by another client
if (it == fileList.end())
{
HandleFileRemove(siaCurl, siaPath, siaDriveFilePath);
HandleFileRemove(siaCurl, siaPath);
}
// Upload is complete
else if ((*it)->GetAvailable())
{
SET_STATUS(UploadStatus::Complete, UploadComplete, ModifyUploadStatusFailed)
if (!RetryDeleteFileIfExists(siaDriveFilePath))
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DeleteSiaDriveFileFailed(siaPath, filePath, siaDriveFilePath)));
}
SET_STATUS(UploadStatus::Complete, UploadToSiaComplete, ModifyUploadStatusFailed)
}
// Upload still active, don't process another file
else
@@ -304,28 +217,16 @@ void CUploadManager::AutoThreadCallback(const CSiaCurl& siaCurl, CSiaDriveConfig
std::lock_guard<std::mutex> l(_uploadMutex);
SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS);
query.bind("@status", static_cast<unsigned>(UploadStatus::Queued));
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")));
SString sdFilePath = static_cast<const char*>(query.getColumn(query.getColumnIndex("sd_file_path")));
if (dokanDrive->LockFile(filePath))
json response;
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/upload/") + siaPath, { {L"source", filePath} }, response);
if (ApiSuccess(cerror))
{
if (CreateSiaDriveFile(siaPath, filePath, sdFilePath + ".temp", sdFilePath))
{
dokanDrive->UnLockFile(filePath, sdFilePath);
json response;
SiaCurlError cerror = siaCurl.Post(SString(L"/renter/upload/") + siaPath, { {L"source", filePath} }, response);
if (ApiSuccess(cerror))
{
SET_STATUS(UploadStatus::Uploading, UploadToSiaStarted, ModifyUploadStatusFailed)
}
}
else
{
dokanDrive->UnLockFile(filePath);
}
SET_STATUS(UploadStatus::Uploading, UploadToSiaStarted, ModifyUploadStatusFailed)
}
}
}
@@ -371,12 +272,6 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
query.bind("@sia_path", SString::ToUtf8(siaPath).c_str());
query.bind("@status", static_cast<unsigned>(UploadStatus::Uploading));
// Strip drive specification (i.e. C:\)
// TODO If mount to folder is ever enabled, this will need to change
// TODO Case sensative file names? Going to be a bit of an issue.
SString siaDriveFileName = GenerateSha256(&filePath[3]) + L".siadrive";
FilePath siaDriveFilePath(rootPath, siaDriveFileName);
// Check uploading
bool addToDatabase = true;
if (query.executeStep())
@@ -385,14 +280,6 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
if (uploadStatus == UploadStatus::Uploading)
{
addToDatabase = HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath);
if (addToDatabase)
{
// Move modified file to real file
if (!siaDriveFilePath.MoveFile(filePath))
{
// TODO Critical failure
}
}
}
else if (uploadStatus == UploadStatus::Queued)
{
@@ -408,11 +295,10 @@ UploadError CUploadManager::AddOrUpdate(const SString& siaPath, SString filePath
SQLite::Statement insert(_uploadDatabase, INSERT_UPLOAD);
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(static_cast<SString>(siaDriveFilePath)).c_str());
insert.bind("@status", static_cast<unsigned>(UploadStatus::Queued));
if (insert.exec() == 1)
{
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileAddedToQueue(siaPath, filePath, siaDriveFilePath)));
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(FileAddedToQueue(siaPath, filePath)));
}
else
{
@@ -448,8 +334,7 @@ UploadError CUploadManager::Remove(const SString& siaPath)
try
{
std::lock_guard<std::mutex> l(_uploadMutex);
FilePath siaDriveFilePath(GetSiaDriveConfig()->GetCacheFolder(), siaPath + ".siadrive");
if (!HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath, siaDriveFilePath))
if (!HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath))
{
ret = UploadErrorCode::SourceFileNotFound;
}

View File

@@ -7,6 +7,15 @@
using namespace Sia::Api;
using namespace Sia::Api::Dokan;
static __int64 FileSize(const wchar_t* name)
{
struct _stat64 buf;
if (_wstat64(name, &buf) != 0)
return -1; // error, could use errno to find out more
return buf.st_size;
}
// TODO Handle paths greater than MAX_PATH!!
// The general idea is that normal file I/O occurs in a local cache folder and once the file is closed, it is scheduled for upload into Sia.
@@ -54,22 +63,35 @@ private:
return ret;
}
static bool AddFileToCache(const SString& siaPath)
static bool AddFileToCache(const SString& siaPath, PDOKAN_FILE_INFO dokanFileInfo)
{
FilePath tempFilePath = FilePath::GetTempDirectory();
tempFilePath.Append(GenerateSha256(siaPath) + ".siatmp");
bool active = true;
bool ret = false;
// TODO Check cache size is large enough to hold new file
bool ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempFilePath));
if (ret)
{
FilePath src(tempFilePath);
FilePath dest(GetCacheLocation(), siaPath);
ret = src.MoveFile(dest);
if (!ret)
std::thread th([&] {
FilePath tempFilePath = FilePath::GetTempDirectory();
tempFilePath.Append(GenerateSha256(siaPath) + ".siatmp");
// TODO Check cache size is large enough to hold new file
ret = ApiSuccess(_siaApi->GetRenter()->DownloadFile(siaPath, tempFilePath));
if (ret)
{
src.DeleteFile();
FilePath src(tempFilePath);
FilePath dest(GetCacheLocation(), siaPath);
ret = src.MoveFile(dest);
if (!ret)
{
src.DeleteFile();
}
}
active = false;
});
th.detach();
while (active)
{
DokanResetTimeout(60000, dokanFileInfo);
::Sleep(10);
}
return ret;
@@ -270,10 +292,10 @@ private:
}
else
{
bool exists;
if (ApiSuccess(_siaApi->GetRenter()->FileExists(siaPath, exists)))
bool siaExists;
if (ApiSuccess(_siaApi->GetRenter()->FileExists(siaPath, siaExists)))
{
exists = exists || cacheFilePath.IsFile();
bool exists = siaExists || cacheFilePath.IsFile();
// Operations on existing files that are requested to be truncated, overwritten or re-created
// will first be deleted and then replaced if, after the file operation is done, the resulting file
// size is > 0. Sia doesn't support random access to files (upload/download/rename/delete).
@@ -359,11 +381,13 @@ private:
bool isDummy = false;
if (ret == STATUS_SUCCESS)
{
// If file must exist, then check for it in cache location. If not found,
// it must be downloaded first and placed in cache
if (!isCreateOp && !cacheFilePath.IsFile())
if (!isCreateOp)
{
if (exists)
if (cacheFilePath.IsFile())
{
isDummy = (siaExists && (FileSize(&cacheFilePath[0]) == 0));
}
else if (exists)
{
isDummy = AddDummyFileToCache(siaPath);
if (!isDummy)
@@ -441,7 +465,8 @@ private:
auto siaFileTree = GetFileTree();
if (siaFileTree)
{
SString siaFileQuery = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
SString siaFileQuery = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
SString siaRootPath = CSiaApi::FormatToSiaPath(FilePath(fileName).SkipRoot());
FilePath siaDirQuery = siaFileQuery;
FilePath findFile = GetCacheLocation();
FilePath cachePath = GetCacheLocation();
@@ -484,17 +509,22 @@ private:
{
if ((wcscmp(fileName, L"\\") != 0) || (wcscmp(findData.cFileName, L".") != 0) && (wcscmp(findData.cFileName, L"..") != 0))
{
if (!(SString(findData.cFileName).EndsWith(".siadrive") || SString(findData.cFileName).EndsWith(".siadrive.temp")))
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
dirs.insert({ findData.cFileName, 0 });
}
bool exists;
if (!ApiSuccess(_siaApi->GetRenter()->FileExists(CSiaApi::FormatToSiaPath(FilePath(siaRootPath, findData.cFileName)), exists)))
{
::FindClose(findHandle);
return STATUS_INVALID_DEVICE_STATE;
}
if (findData.nFileSizeHigh || findData.nFileSizeLow || !exists)
{
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
dirs.insert({ findData.cFileName, 0 });
}
else
{
files.insert({ findData.cFileName, 1 });
}
fillFindData(&findData, dokanFileInfo);
files.insert({ findData.cFileName, 1 });
}
}
} while (::FindNextFile(findHandle, &findData) != 0);
@@ -709,10 +739,30 @@ private:
PDOKAN_FILE_INFO dokanFileInfo)
{
// TODO Check dummy and add to cache if not found
FilePath filePath(GetCacheLocation(), fileName);
CEventSystem::EventSystem.NotifyEvent(CreateSystemEvent(DokanReadFile(filePath)));
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
bool isDummy = false;
SString siaPath;
{
std::lock_guard<std::mutex> l(_fileTreeMutex);
isDummy = _openFileMap.find(dokanFileInfo->Context) != _openFileMap.end();
if (isDummy)
{
siaPath = _openFileMap[dokanFileInfo->Context].SiaPath;
}
}
if (isDummy)
{
if (!AddFileToCache(siaPath, dokanFileInfo))
{
return STATUS_INVALID_DEVICE_STATE;
}
}
HANDLE handle = reinterpret_cast<HANDLE>(dokanFileInfo->Context);
BOOL opened = FALSE;
if (!handle || (handle == INVALID_HANDLE_VALUE))
{