From c199214fa824a5ac7967bc088e514a42a26efe32 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Thu, 30 Mar 2017 23:26:12 -0500 Subject: [PATCH] Continue download support --- include/siadrive_api/uploadmanager.h | 448 ++--------------------- src/siadrive/siadriveapp.cpp | 2 + src/siadrive_api/uploadmanager.cpp | 173 ++------- src/siadrive_dokan_api/siadokandrive.cpp | 110 ++++-- 4 files changed, 132 insertions(+), 601 deletions(-) diff --git a/include/siadrive_api/uploadmanager.h b/include/siadrive_api/uploadmanager.h index faf09a3..1419d6e 100644 --- a/include/siadrive_api/uploadmanager.h +++ b/include/siadrive_api/uploadmanager.h @@ -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 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 Clone() const override - { - return std::shared_ptr(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 Clone() const override { - return std::shared_ptr(new FileAddedToQueue(_siaPath, _filePath, _siaDriveFilePath)); + return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override { - return std::shared_ptr(new UploadComplete(_siaPath, _filePath)); + return std::shared_ptr(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 Clone() const override { - return std::shared_ptr(new FileRemoved(_siaPath, _filePath)); + return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override { - return std::shared_ptr(new FailedToDeleteFromSia(_siaPath, _filePath, _curlError)); + return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(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 Clone() const override - { - return std::shared_ptr(new ExistingUploadFound(_siaPath, _filePath, _uploadStatus)); - } -}; - class SourceFileNotFound : public CEvent { diff --git a/src/siadrive/siadriveapp.cpp b/src/siadrive/siadriveapp.cpp index bc26065..218454b 100644 --- a/src/siadrive/siadriveapp.cpp +++ b/src/siadrive/siadriveapp.cpp @@ -393,6 +393,7 @@ void CSiaDriveApp::SiaApiRefreshCallback(CefRefPtr 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 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; diff --git a/src/siadrive_api/uploadmanager.cpp b/src/siadrive_api/uploadmanager.cpp index ac8f7d8..9314915 100644 --- a/src/siadrive_api/uploadmanager.cpp +++ b/src/siadrive_api/uploadmanager.cpp @@ -4,18 +4,18 @@ #include #include #include + 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 l(_uploadMutex); - SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_2_STATUS); - query.bind("@status1", static_cast(UploadStatus::Uploading)); + SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS); + query.bind("@status", static_cast(UploadStatus::Uploading)); fileTree->BuildTree(result); if (query.executeStep()) { SString siaPath = static_cast(query.getColumn(query.getColumnIndex("sia_path"))); SString filePath = static_cast(query.getColumn(query.getColumnIndex("file_path"))); - SString siaDriveFilePath = static_cast(query.getColumn(query.getColumnIndex("sd_file_path"))); UploadStatus uploadStatus = static_cast(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 l(_uploadMutex); SQLite::Statement query(_uploadDatabase, QUERY_UPLOADS_BY_STATUS); query.bind("@status", static_cast(UploadStatus::Queued)); - if (query.executeStep()) { SString siaPath = static_cast(query.getColumn(query.getColumnIndex("sia_path"))); SString filePath = static_cast(query.getColumn(query.getColumnIndex("file_path"))); - SString sdFilePath = static_cast(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(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(siaDriveFilePath)).c_str()); insert.bind("@status", static_cast(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 l(_uploadMutex); - FilePath siaDriveFilePath(GetSiaDriveConfig()->GetCacheFolder(), siaPath + ".siadrive"); - if (!HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath, siaDriveFilePath)) + if (!HandleFileRemove(CSiaCurl(GetHostConfig()), siaPath)) { ret = UploadErrorCode::SourceFileNotFound; } diff --git a/src/siadrive_dokan_api/siadokandrive.cpp b/src/siadrive_dokan_api/siadokandrive.cpp index 31934ce..6c68ff0 100644 --- a/src/siadrive_dokan_api/siadokandrive.cpp +++ b/src/siadrive_dokan_api/siadokandrive.cpp @@ -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(dokanFileInfo->Context); + bool isDummy = false; + SString siaPath; + { + std::lock_guard 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(dokanFileInfo->Context); BOOL opened = FALSE; if (!handle || (handle == INVALID_HANDLE_VALUE)) {