CLOUD: Add UploadStatus struct
It contains not just "success" flag, but also "file" struct, so the caller can find out some information about uploaded file - like timestamp.
This commit is contained in:
parent
d917592099
commit
b9e3730ccd
9 changed files with 124 additions and 42 deletions
|
@ -76,11 +76,11 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair
|
|||
Common::JSONArray items = response.getVal("entries")->asArray();
|
||||
for (uint32 i = 0; i < items.size(); ++i) {
|
||||
Common::JSONObject item = items[i]->asObject();
|
||||
Common::String path = item.getVal("path_lower")->asString();
|
||||
Common::String path = item.getVal("path_lower")->asString();
|
||||
bool isDirectory = (item.getVal(".tag")->asString() == "folder");
|
||||
uint32 size = 0, timestamp = 0;
|
||||
if (!isDirectory) {
|
||||
size = item.getVal("size")->asNumber();
|
||||
size = item.getVal("size")->asIntegerNumber();
|
||||
timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString());
|
||||
}
|
||||
_files.push_back(StorageFile(path, size, timestamp, isDirectory));
|
||||
|
|
|
@ -104,14 +104,46 @@ void DropboxStorage::printBool(BoolResponse pair) {
|
|||
debug("bool: %s", (pair.value?"true":"false"));
|
||||
}
|
||||
|
||||
void DropboxStorage::printUploadStatus(UploadResponse pair) {
|
||||
UploadStatus status = pair.value;
|
||||
if (status.interrupted) {
|
||||
debug("upload interrupted by user");
|
||||
return;
|
||||
}
|
||||
if (status.failed) {
|
||||
debug("upload failed with following response:");
|
||||
debug("%s", status.response.c_str());
|
||||
return;
|
||||
}
|
||||
debug("upload HTTP response code = %ld", status.httpResponseCode);
|
||||
if (!status.failed) {
|
||||
debug("uploaded file info:");
|
||||
debug("path: %s", status.file.path().c_str());
|
||||
debug("size: %u", status.file.size());
|
||||
debug("timestamp: %u", status.file.timestamp());
|
||||
}
|
||||
}
|
||||
|
||||
Networking::Request *DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) {
|
||||
return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive));
|
||||
}
|
||||
|
||||
Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) {
|
||||
Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) {
|
||||
return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback));
|
||||
}
|
||||
|
||||
Networking::Request *DropboxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback) {
|
||||
Common::File *f = new Common::File();
|
||||
if (!f->open(localPath)) {
|
||||
warning("DropboxStorage: unable to open file to upload from");
|
||||
UploadStatus status(false, true, StorageFile(), "", -1);
|
||||
if (callback) (*callback)(UploadResponse(nullptr, status));
|
||||
delete f;
|
||||
return nullptr;
|
||||
}
|
||||
return upload(remotePath, f, callback);
|
||||
}
|
||||
|
||||
Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) {
|
||||
Common::JSONObject jsonRequestParameters;
|
||||
jsonRequestParameters.setVal("path", new Common::JSONValue(path));
|
||||
|
@ -155,13 +187,7 @@ Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) {
|
|||
false
|
||||
);
|
||||
*/
|
||||
Common::File *file = new Common::File();
|
||||
if (!file->open("final.bmp")) {
|
||||
warning("no such file");
|
||||
delete file;
|
||||
return nullptr;
|
||||
}
|
||||
return upload("/remote/test3.bmp", file, new Common::Callback<DropboxStorage, BoolResponse>(this, &DropboxStorage::printBool));
|
||||
return upload("/remote/test4.bmp", "final.bmp", new Common::Callback<DropboxStorage, UploadResponse>(this, &DropboxStorage::printUploadStatus));
|
||||
}
|
||||
|
||||
Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) {
|
||||
|
@ -186,13 +212,13 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ
|
|||
if (outerCallback) {
|
||||
//Dropbox documentation states there is no errors for this API method
|
||||
Common::JSONObject info = json->asObject();
|
||||
Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asNumber());
|
||||
Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber());
|
||||
Common::String name = info.getVal("display_name")->asString();
|
||||
Common::String email = info.getVal("email")->asString();
|
||||
Common::JSONObject quota = info.getVal("quota_info")->asObject();
|
||||
uint32 quotaNormal = quota.getVal("normal")->asNumber();
|
||||
uint32 quotaShared = quota.getVal("shared")->asNumber();
|
||||
uint32 quotaAllocated = quota.getVal("quota")->asNumber();
|
||||
uint32 quotaNormal = quota.getVal("normal")->asIntegerNumber();
|
||||
uint32 quotaShared = quota.getVal("shared")->asIntegerNumber();
|
||||
uint32 quotaAllocated = quota.getVal("quota")->asIntegerNumber();
|
||||
(*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated)));
|
||||
delete outerCallback;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ class DropboxStorage: public Cloud::Storage {
|
|||
|
||||
void printFiles(FileArrayResponse pair);
|
||||
void printBool(BoolResponse pair);
|
||||
void printUploadStatus(UploadResponse pair);
|
||||
|
||||
public:
|
||||
virtual ~DropboxStorage();
|
||||
|
@ -70,7 +71,8 @@ public:
|
|||
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false);
|
||||
|
||||
/** Calls the callback when finished. */
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback);
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback);
|
||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback);
|
||||
|
||||
/** Returns pointer to Networking::NetworkReadStream. */
|
||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback);
|
||||
|
|
|
@ -21,17 +21,19 @@
|
|||
*/
|
||||
|
||||
#include "backends/cloud/dropbox/dropboxuploadrequest.h"
|
||||
#include "backends/cloud/iso8601.h"
|
||||
#include "backends/cloud/storage.h"
|
||||
#include "backends/networking/curl/connectionmanager.h"
|
||||
#include "backends/networking/curl/curljsonrequest.h"
|
||||
#include "backends/networking/curl/networkreadstream.h"
|
||||
#include "common/json.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
namespace Cloud {
|
||||
namespace Dropbox {
|
||||
|
||||
DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::BoolCallback callback):
|
||||
Networking::Request(0), _token(token), _savePath(path), _contentsStream(contents), _boolCallback(callback),
|
||||
DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback):
|
||||
Networking::Request(0), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
|
||||
_workingRequest(nullptr), _ignoreCallback(false) {
|
||||
start();
|
||||
}
|
||||
|
@ -40,7 +42,7 @@ DropboxUploadRequest::~DropboxUploadRequest() {
|
|||
_ignoreCallback = true;
|
||||
if (_workingRequest) _workingRequest->finish();
|
||||
delete _contentsStream;
|
||||
delete _boolCallback;
|
||||
delete _uploadCallback;
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,6 +107,11 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) {
|
|||
if (_ignoreCallback) return;
|
||||
_workingRequest = nullptr;
|
||||
|
||||
UploadStatus status;
|
||||
Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request;
|
||||
if (rq && rq->getNetworkReadStream())
|
||||
status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
|
||||
|
||||
Common::JSONValue *json = pair.value;
|
||||
if (json) {
|
||||
bool needsFinishRequest = false;
|
||||
|
@ -117,13 +124,19 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) {
|
|||
if (response.contains("error") || response.contains("error_summary")) {
|
||||
warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str());
|
||||
delete json;
|
||||
finish();
|
||||
status.failed = true;
|
||||
status.response = json->stringify(true);
|
||||
finishUpload(status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.contains("server_modified")) {
|
||||
//finished
|
||||
finishBool(true);
|
||||
Common::String path = response.getVal("path_lower")->asString();
|
||||
uint32 size = response.getVal("size")->asIntegerNumber();
|
||||
uint32 timestamp = ISO8601::convertToTimestamp(response.getVal("server_modified")->asString());
|
||||
status.file = StorageFile(path, size, timestamp, false);
|
||||
finishUpload(status);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -136,13 +149,19 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1))
|
||||
finishBool(true);
|
||||
else
|
||||
if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) {
|
||||
if (status.file.name() == "") {
|
||||
status.file = StorageFile(_savePath, 0, 0, false);
|
||||
warning("no file info to put into status");
|
||||
}
|
||||
finishUpload(status);
|
||||
} else {
|
||||
uploadNextPart();
|
||||
}
|
||||
} else {
|
||||
warning("null, not json");
|
||||
finish();
|
||||
warning("null, not json");
|
||||
status.failed = true;
|
||||
finishUpload(status);
|
||||
}
|
||||
|
||||
delete json;
|
||||
|
@ -152,11 +171,15 @@ void DropboxUploadRequest::handle() {}
|
|||
|
||||
void DropboxUploadRequest::restart() { start(); }
|
||||
|
||||
void DropboxUploadRequest::finish() { finishBool(false); }
|
||||
void DropboxUploadRequest::finish() {
|
||||
UploadStatus status;
|
||||
status.interrupted = true;
|
||||
finishUpload(status);
|
||||
}
|
||||
|
||||
void DropboxUploadRequest::finishBool(bool success) {
|
||||
void DropboxUploadRequest::finishUpload(UploadStatus status) {
|
||||
Request::finish();
|
||||
if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success));
|
||||
if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, status));
|
||||
}
|
||||
|
||||
} // End of namespace Dropbox
|
||||
|
|
|
@ -35,7 +35,7 @@ class DropboxUploadRequest: public Networking::Request {
|
|||
Common::String _token;
|
||||
Common::String _savePath;
|
||||
Common::SeekableReadStream *_contentsStream;
|
||||
Storage::BoolCallback _boolCallback;
|
||||
Storage::UploadCallback _uploadCallback;
|
||||
Request *_workingRequest;
|
||||
bool _ignoreCallback;
|
||||
Common::String _sessionId;
|
||||
|
@ -43,10 +43,10 @@ class DropboxUploadRequest: public Networking::Request {
|
|||
void start();
|
||||
void uploadNextPart();
|
||||
void partUploadedCallback(Networking::JsonResponse pair);
|
||||
void finishBool(bool success);
|
||||
void finishUpload(UploadStatus status);
|
||||
|
||||
public:
|
||||
DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::BoolCallback callback);
|
||||
DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback);
|
||||
virtual ~DropboxUploadRequest();
|
||||
|
||||
virtual void handle();
|
||||
|
|
|
@ -76,7 +76,8 @@ public:
|
|||
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false);
|
||||
|
||||
/** Calls the callback when finished. */
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) { return nullptr; } //TODO
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { return nullptr; } //TODO
|
||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { return nullptr; }
|
||||
|
||||
/** Returns pointer to Networking::NetworkReadStream. */
|
||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback);
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "backends/cloud/savessyncrequest.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
|
||||
namespace Cloud {
|
||||
|
||||
|
@ -85,6 +87,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::FileArrayResponse pair)
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: upload files which are added to local directory (not available on cloud), but have no timestamp
|
||||
|
||||
//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) {
|
||||
if (i->_value == INVALID_TIMESTAMP)
|
||||
|
@ -104,7 +108,7 @@ void SavesSyncRequest::downloadNextFile() {
|
|||
_currentDownloadingFile = _filesToDownload.back();
|
||||
_filesToDownload.pop_back();
|
||||
|
||||
_workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(),
|
||||
_workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(), //TODO: real saves folder here
|
||||
new Common::Callback<SavesSyncRequest, Storage::BoolResponse>(this, &SavesSyncRequest::fileDownloadedCallback)
|
||||
);
|
||||
}
|
||||
|
@ -133,23 +137,24 @@ void SavesSyncRequest::uploadNextFile() {
|
|||
|
||||
_currentUploadingFile = _filesToUpload.back();
|
||||
_filesToUpload.pop_back();
|
||||
|
||||
_workingRequest = _storage->upload("saves/" + _currentUploadingFile, nullptr, //TODO: pass save's read stream
|
||||
new Common::Callback<SavesSyncRequest, Storage::BoolResponse>(this, &SavesSyncRequest::fileUploadedCallback)
|
||||
|
||||
_workingRequest = _storage->upload("saves/" + _currentUploadingFile, g_system->getSavefileManager()->openForLoading(_currentUploadingFile),
|
||||
new Common::Callback<SavesSyncRequest, Storage::UploadResponse>(this, &SavesSyncRequest::fileUploadedCallback)
|
||||
);
|
||||
}
|
||||
|
||||
void SavesSyncRequest::fileUploadedCallback(Storage::BoolResponse pair) {
|
||||
void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse pair) {
|
||||
if (_ignoreCallback) return;
|
||||
UploadStatus status = pair.value;
|
||||
|
||||
//stop syncing if upload failed
|
||||
if (!pair.value) {
|
||||
if (status.interrupted || status.failed) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: update local timestamp for the uploaded file
|
||||
//_localFilesTimestamps[_currentUploadingFile] = pair.request.<what?>;
|
||||
//update local timestamp for the uploaded file
|
||||
_localFilesTimestamps[_currentUploadingFile] = status.file.timestamp();
|
||||
|
||||
//continue uploading files
|
||||
uploadNextFile();
|
||||
|
@ -172,6 +177,7 @@ void SavesSyncRequest::finishBool(bool success) {
|
|||
|
||||
void SavesSyncRequest::loadTimestamps() {
|
||||
Common::File f;
|
||||
//TODO: real saves folder here
|
||||
if (!f.open("saves/timestamps"))
|
||||
error("SavesSyncRequest: failed to open 'saves/timestamps' file to load timestamps");
|
||||
|
||||
|
@ -215,6 +221,7 @@ void SavesSyncRequest::loadTimestamps() {
|
|||
|
||||
void SavesSyncRequest::saveTimestamps() {
|
||||
Common::DumpFile f;
|
||||
//TODO: real saves folder here
|
||||
if (!f.open("saves/timestamps", true))
|
||||
error("SavesSyncRequest: failed to open 'saves/timestamps' file to save timestamps");
|
||||
Common::String data;
|
||||
|
|
|
@ -44,7 +44,7 @@ class SavesSyncRequest: public Networking::Request {
|
|||
void start();
|
||||
void directoryListedCallback(Storage::FileArrayResponse pair);
|
||||
void fileDownloadedCallback(Storage::BoolResponse pair);
|
||||
void fileUploadedCallback(Storage::BoolResponse pair);
|
||||
void fileUploadedCallback(Storage::UploadResponse pair);
|
||||
void downloadNextFile();
|
||||
void uploadNextFile();
|
||||
void finishBool(bool success);
|
||||
|
|
|
@ -34,15 +34,37 @@
|
|||
|
||||
namespace Cloud {
|
||||
|
||||
/** Struct to represent upload() resulting status. */
|
||||
struct UploadStatus {
|
||||
/** true if Request was interrupted (finished by user with finish()) */
|
||||
bool interrupted;
|
||||
/** true if Request has failed (bad server response or some other error occurred) */
|
||||
bool failed;
|
||||
/** Contains uploaded file description (empty if failed) */
|
||||
StorageFile file;
|
||||
/** Server's original response (empty if not failed) */
|
||||
Common::String response;
|
||||
/** Server's HTTP response code. */
|
||||
long httpResponseCode;
|
||||
|
||||
UploadStatus():
|
||||
interrupted(false), failed(false), file(), response(), httpResponseCode(-1) {}
|
||||
|
||||
UploadStatus(bool interrupt, bool failure, StorageFile f, Common::String resp, long code):
|
||||
interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {}
|
||||
};
|
||||
|
||||
class Storage {
|
||||
public:
|
||||
typedef Networking::Response<Common::Array<StorageFile>&> FileArrayResponse;
|
||||
typedef Networking::Response<StorageInfo> StorageInfoResponse;
|
||||
typedef Networking::Response<bool> BoolResponse;
|
||||
typedef Networking::Response<UploadStatus> UploadResponse;
|
||||
|
||||
typedef Common::BaseCallback<FileArrayResponse> *FileArrayCallback;
|
||||
typedef Common::BaseCallback<StorageInfoResponse> *StorageInfoCallback;
|
||||
typedef Common::BaseCallback<BoolResponse> *BoolCallback;
|
||||
typedef Common::BaseCallback<UploadResponse> *UploadCallback;
|
||||
|
||||
Storage() {}
|
||||
virtual ~Storage() {}
|
||||
|
@ -72,7 +94,8 @@ public:
|
|||
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0;
|
||||
|
||||
/** Calls the callback when finished. */
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) = 0;
|
||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) = 0;
|
||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) = 0;
|
||||
|
||||
/** Returns pointer to Networking::NetworkReadStream. */
|
||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue