aboutsummaryrefslogtreecommitdiff
path: root/backends/cloud/savessyncrequest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/cloud/savessyncrequest.cpp')
-rw-r--r--backends/cloud/savessyncrequest.cpp151
1 files changed, 99 insertions, 52 deletions
diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp
index e632bfff84..b48a99a48c 100644
--- a/backends/cloud/savessyncrequest.cpp
+++ b/backends/cloud/savessyncrequest.cpp
@@ -32,8 +32,8 @@ namespace Cloud {
const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps";
-SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback):
- Request(nullptr), _storage(storage), _boolCallback(callback),
+SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb):
+ Request(nullptr, ecb), _storage(storage), _boolCallback(callback),
_workingRequest(nullptr), _ignoreCallback(false) {
start();
}
@@ -59,48 +59,35 @@ void SavesSyncRequest::start() {
loadTimestamps();
//list saves directory
- _workingRequest = _storage->listDirectory("/saves", new Common::Callback<SavesSyncRequest, Storage::ListDirectoryResponse>(this, &SavesSyncRequest::directoryListedCallback));
+ _workingRequest = _storage->listDirectory(
+ "/saves",
+ new Common::Callback<SavesSyncRequest, Storage::ListDirectoryResponse>(this, &SavesSyncRequest::directoryListedCallback),
+ new Common::Callback<SavesSyncRequest, Networking::ErrorResponse>(this, &SavesSyncRequest::directoryListedErrorCallback)
+ );
}
-void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) {
+void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse response) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
- ListDirectoryStatus status = pair.value;
- bool irrecoverable = status.interrupted || status.failed;
- if (status.failed) {
- Common::JSONValue *value = Common::JSON::parse(status.response.c_str());
- if (value) {
- if (value->isObject()) {
- Common::JSONObject object = value->asObject();
- //Dropbox-related error:
- if (object.contains("error_summary")) {
- Common::String summary = object.getVal("error_summary")->asString();
- if (summary.contains("not_found")) {
- //oh how lucky we are! It's just user don't have /cloud/ folder yet!
- irrecoverable = false;
- }
- }
- }
- delete value;
- }
+ Common::HashMap<Common::String, bool> localFileNotAvailableInCloud;
+ for (Common::HashMap<Common::String, uint32>::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) {
+ localFileNotAvailableInCloud[i->_key] = true;
}
- if (irrecoverable) {
- finishBool(false);
- return;
- }
-
//determine which files to download and which files to upload
- Common::Array<StorageFile> &remoteFiles = status.files;
+ Common::Array<StorageFile> &remoteFiles = response.value;
for (uint32 i = 0; i < remoteFiles.size(); ++i) {
StorageFile &file = remoteFiles[i];
if (file.isDirectory()) continue;
if (file.name() == TIMESTAMPS_FILENAME) continue;
+
Common::String name = file.name();
if (!_localFilesTimestamps.contains(name))
_filesToDownload.push_back(file);
else {
+ localFileNotAvailableInCloud[name] = false;
+
if (_localFilesTimestamps[name] != INVALID_TIMESTAMP) {
if (_localFilesTimestamps[name] == file.timestamp())
continue;
@@ -115,11 +102,10 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pa
}
}
- //upload files with invalid timestamp (the ones we've added - means they might not have any remote version)
- for (Common::HashMap<Common::String, uint32>::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) {
+ //upload files which are unavailable in cloud
+ for (Common::HashMap<Common::String, bool>::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) {
if (i->_key == TIMESTAMPS_FILENAME) continue;
- if (i->_value == INVALID_TIMESTAMP)
- _filesToUpload.push_back(i->_key);
+ if (i->_value) _filesToUpload.push_back(i->_key);
}
///////
@@ -137,6 +123,50 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pa
downloadNextFile();
}
+void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse error) {
+ _workingRequest = nullptr;
+ if (_ignoreCallback) return;
+
+ bool irrecoverable = error.interrupted || error.failed;
+ if (error.failed) {
+ Common::JSONValue *value = Common::JSON::parse(error.response.c_str());
+ if (value) {
+ if (value->isObject()) {
+ Common::JSONObject object = value->asObject();
+
+ //Dropbox-related error:
+ if (object.contains("error_summary")) {
+ Common::String summary = object.getVal("error_summary")->asString();
+ if (summary.contains("not_found")) {
+ irrecoverable = false;
+ }
+ }
+
+ //OneDrive-related error:
+ if (object.contains("error") && object.getVal("error")->isObject()) {
+ Common::JSONObject errorNode = object.getVal("error")->asObject();
+ if (errorNode.contains("code") && errorNode.contains("message")) {
+ Common::String code = errorNode.getVal("code")->asString();
+ if (code == "itemNotFound") {
+ irrecoverable = false;
+ }
+ }
+ }
+ }
+ delete value;
+ }
+ }
+
+ if (irrecoverable) {
+ finishError(error);
+ return;
+ }
+
+ //we're lucky - user just lacks his "/cloud/" folder
+ Common::Array<StorageFile> files;
+ directoryListedCallback(Storage::ListDirectoryResponse(error.request, files));
+}
+
void SavesSyncRequest::downloadNextFile() {
if (_filesToDownload.empty()) {
uploadNextFile();
@@ -150,17 +180,18 @@ void SavesSyncRequest::downloadNextFile() {
debug("downloading %s", _currentDownloadingFile.name().c_str());
///////
_workingRequest = _storage->download(_currentDownloadingFile.path(), concatWithSavesPath(_currentDownloadingFile.name()),
- new Common::Callback<SavesSyncRequest, Storage::BoolResponse>(this, &SavesSyncRequest::fileDownloadedCallback)
+ new Common::Callback<SavesSyncRequest, Storage::BoolResponse>(this, &SavesSyncRequest::fileDownloadedCallback),
+ new Common::Callback<SavesSyncRequest, Networking::ErrorResponse>(this, &SavesSyncRequest::fileDownloadedErrorCallback)
);
}
-void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) {
+void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
//stop syncing if download failed
- if (!pair.value) {
- finish();
+ if (!response.value) {
+ finishError(Networking::ErrorResponse(this, false, true, "", -1));
return;
}
@@ -171,9 +202,17 @@ void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) {
downloadNextFile();
}
+void SavesSyncRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) {
+ _workingRequest = nullptr;
+ if (_ignoreCallback) return;
+
+ //stop syncing if download failed
+ finishError(error);
+}
+
void SavesSyncRequest::uploadNextFile() {
if (_filesToUpload.empty()) {
- finishBool(true);
+ finishSuccess(true);
return;
}
@@ -184,36 +223,45 @@ void SavesSyncRequest::uploadNextFile() {
debug("uploading %s", _currentUploadingFile.c_str());
///////
_workingRequest = _storage->upload("/saves/" + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile),
- new Common::Callback<SavesSyncRequest, Storage::UploadResponse>(this, &SavesSyncRequest::fileUploadedCallback)
+ new Common::Callback<SavesSyncRequest, Storage::UploadResponse>(this, &SavesSyncRequest::fileUploadedCallback),
+ new Common::Callback<SavesSyncRequest, Networking::ErrorResponse>(this, &SavesSyncRequest::fileUploadedErrorCallback)
);
}
-void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse pair) {
+void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
- UploadStatus status = pair.value;
-
- //stop syncing if upload failed
- if (status.interrupted || status.failed) {
- finish();
- return;
- }
-
+
//update local timestamp for the uploaded file
- _localFilesTimestamps[_currentUploadingFile] = status.file.timestamp();
+ _localFilesTimestamps[_currentUploadingFile] = response.value.timestamp();
//continue uploading files
uploadNextFile();
}
+void SavesSyncRequest::fileUploadedErrorCallback(Networking::ErrorResponse error) {
+ _workingRequest = nullptr;
+ if (_ignoreCallback) return;
+
+ //stop syncing if upload failed
+ finishError(error);
+}
+
void SavesSyncRequest::handle() {}
void SavesSyncRequest::restart() { start(); }
-void SavesSyncRequest::finish() { finishBool(false); }
+void SavesSyncRequest::finishError(Networking::ErrorResponse error) {
+ debug("SavesSync::finishError");
+
+ //save updated timestamps (even if Request failed, there would be only valid timestamps)
+ saveTimestamps();
+
+ Request::finishError(error);
+}
-void SavesSyncRequest::finishBool(bool success) {
- Request::finish();
+void SavesSyncRequest::finishSuccess(bool success) {
+ Request::finishSuccess();
//save updated timestamps (even if Request failed, there would be only valid timestamps)
saveTimestamps();
@@ -233,7 +281,6 @@ void SavesSyncRequest::loadTimestamps() {
warning("SavesSyncRequest: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME);
return;
}
-
while (!file->eos()) {
//read filename into buffer (reading until the first ' ')