diff options
| author | Alexander Tkachev | 2016-05-30 13:35:53 +0600 | 
|---|---|---|
| committer | Alexander Tkachev | 2016-08-24 16:07:55 +0600 | 
| commit | b9e3730ccd9a76101ef0cb8812f41c371a24d0d6 (patch) | |
| tree | ac5d34f780c7fbdaae297f8ac5217b46d064a786 | |
| parent | d917592099381402c2681b291d379bda78a1c3f7 (diff) | |
| download | scummvm-rg350-b9e3730ccd9a76101ef0cb8812f41c371a24d0d6.tar.gz scummvm-rg350-b9e3730ccd9a76101ef0cb8812f41c371a24d0d6.tar.bz2 scummvm-rg350-b9e3730ccd9a76101ef0cb8812f41c371a24d0d6.zip  | |
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.
| -rw-r--r-- | backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 | ||||
| -rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 50 | ||||
| -rw-r--r-- | backends/cloud/dropbox/dropboxstorage.h | 4 | ||||
| -rw-r--r-- | backends/cloud/dropbox/dropboxuploadrequest.cpp | 49 | ||||
| -rw-r--r-- | backends/cloud/dropbox/dropboxuploadrequest.h | 6 | ||||
| -rw-r--r-- | backends/cloud/onedrive/onedrivestorage.h | 3 | ||||
| -rw-r--r-- | backends/cloud/savessyncrequest.cpp | 23 | ||||
| -rw-r--r-- | backends/cloud/savessyncrequest.h | 2 | ||||
| -rw-r--r-- | backends/cloud/storage.h | 25 | 
9 files changed, 124 insertions, 42 deletions
diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 6ea90c150d..89e92facb8 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -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)); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 1220a99035..1f983cec67 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -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;  	} diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index cc515fef41..ca285802a4 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -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); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index d068078502..18e1173eef 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -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 diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h index a7d7a6c581..9b68995969 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.h +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -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(); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 41d84f9770..7028667819 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -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); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index d48ec6ba45..be1075cb4d 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -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; diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index dd43cab2a0..dca1fb750b 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -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); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index dbd862822b..1749881a7d 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -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;  | 
