diff options
| author | Alexander Tkachev | 2016-06-01 12:39:10 +0600 | 
|---|---|---|
| committer | Alexander Tkachev | 2016-08-24 16:07:55 +0600 | 
| commit | a66322408f95ff7b29cf6967eaecaac06dfe5b31 (patch) | |
| tree | a55a9390a3ab12566aec0478e633d30ae988103d | |
| parent | 4b3a8be0b9db448971e6095a24501c66714c484f (diff) | |
| download | scummvm-rg350-a66322408f95ff7b29cf6967eaecaac06dfe5b31.tar.gz scummvm-rg350-a66322408f95ff7b29cf6967eaecaac06dfe5b31.tar.bz2 scummvm-rg350-a66322408f95ff7b29cf6967eaecaac06dfe5b31.zip | |
CLOUD: Implement Storage's isWorking()
It now keeps track of how many Requests are running.
To achieve that, we had to pass a callback to ConnectionManager, so each
Request has a callback paired with it. If that's one of Storage's
Requests, it has a callback, which would decrease a counter. When
Storage adds a Request, it also increases a counter and passes that
callback. Callback is called by ConnMan when Request is deleted.
isWorking() returns true if there is at least one Request running.
| -rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 8 | ||||
| -rw-r--r-- | backends/cloud/dropbox/dropboxstorage.h | 3 | ||||
| -rw-r--r-- | backends/cloud/onedrive/onedrivestorage.cpp | 12 | ||||
| -rw-r--r-- | backends/cloud/onedrive/onedrivestorage.h | 3 | ||||
| -rw-r--r-- | backends/cloud/storage.cpp | 24 | ||||
| -rw-r--r-- | backends/cloud/storage.h | 26 | ||||
| -rw-r--r-- | backends/networking/curl/connectionmanager.cpp | 11 | ||||
| -rw-r--r-- | backends/networking/curl/connectionmanager.h | 13 | 
8 files changed, 70 insertions, 30 deletions
| diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index f51819ccae..861a58db4b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -110,11 +110,11 @@ void DropboxStorage::printStorageFile(UploadResponse response) {  }  Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) { -	return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); +	return addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive));  }  Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { -	return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback)); +	return addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback));  }  Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { @@ -134,14 +134,14 @@ Networking::Request *DropboxStorage::streamFile(Common::String path, Networking:  Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) {  	if (!errorCallback) errorCallback = getErrorPrintingCallback(); -	return ConnMan.addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); +	return addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback));  }  Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) {  	Networking::JsonCallback innerCallback = new Common::CallbackBridge<DropboxStorage, StorageInfoResponse, Networking::JsonResponse>(this, &DropboxStorage::infoInnerCallback, outerCallback);  	Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info");  	request->addHeader("Authorization: Bearer " + _token); -	return ConnMan.addRequest(request); +	return addRequest(request);  	//that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback  	//so, when CurlJsonRequest is finished, it calls the innerCallback  	//innerCallback (which is DropboxStorage::infoInnerCallback in this case) processes the void *ptr diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 2c60097701..c186d1e5d6 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -91,9 +91,6 @@ public:  	/** Returns storage's saves directory path with the trailing slash. */  	virtual Common::String savesDirectoryPath(); -	/** Returns whether there are any requests running. */ -	virtual bool isWorking() { return false; } //TODO -  	/**  	 * Load token and user id from configs and return DropboxStorage for those.	  	 * @return pointer to the newly created DropboxStorage or 0 if some problem occured. diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 190a7ab603..98f0ac5a4d 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -84,7 +84,7 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code)  	request->addPostField("client_id=" + Common::String(KEY));  	request->addPostField("client_secret=" + Common::String(SECRET));  	request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); -	ConnMan.addRequest(request); +	addRequest(request);  }  void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse response) { @@ -198,11 +198,11 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out  }  Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { -	return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); +	return addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive));  }  Networking::Request *OneDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { -	return ConnMan.addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback)); +	return addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback));  }  Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { @@ -210,7 +210,7 @@ Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking  	Networking::JsonCallback innerCallback = new Common::CallbackBridge<OneDriveStorage, Networking::NetworkReadStreamResponse, Networking::JsonResponse>(this, &OneDriveStorage::fileInfoCallback, outerCallback);  	Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str());  	request->addHeader("Authorization: Bearer " + _token); -	return ConnMan.addRequest(request); +	return addRequest(request);  }  void OneDriveStorage::fileDownloaded(BoolResponse response) { @@ -238,14 +238,14 @@ void OneDriveStorage::printFile(UploadResponse response) {  Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) {  	if (!errorCallback) errorCallback = getErrorPrintingCallback(); -	return ConnMan.addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); +	return addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback));  }  Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) {  	Networking::JsonCallback innerCallback = new Common::CallbackBridge<OneDriveStorage, StorageInfoResponse, Networking::JsonResponse>(this, &OneDriveStorage::infoInnerCallback, callback);  	Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot");  	request->addHeader("Authorization: bearer " + _token); -	return ConnMan.addRequest(request); +	return addRequest(request);  }  Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 5edd96e59c..a09d68b6fd 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -98,9 +98,6 @@ public:  	/** Returns storage's saves directory path with the trailing slash. */  	virtual Common::String savesDirectoryPath(); -	/** Returns whether there are any requests running. */ -	virtual bool isWorking() { return false; } //TODO -  	/**  	 * Load token and user id from configs and return OneDriveStorage for those.	  	 * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 90e095a146..0f9a2a168a 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -30,6 +30,10 @@  namespace Cloud { +Storage::Storage(): _runningRequestsCount(0) {} + +Storage::~Storage() {} +  Networking::ErrorCallback Storage::getErrorPrintingCallback() {  	return new Common::Callback<Storage, Networking::ErrorResponse>(this, &Storage::printErrorResponse);  } @@ -39,6 +43,17 @@ void Storage::printErrorResponse(Networking::ErrorResponse error) {  	debug("%s", error.response.c_str());  } +Networking::Request *Storage::addRequest(Networking::Request *request) { +	++_runningRequestsCount; +	if (_runningRequestsCount == 1) debug("Storage is working now"); +	return ConnMan.addRequest(request, new Common::Callback<Storage, Networking::Request *>(this, &Storage::requestFinishedCallback)); +} + +void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer) { +	--_runningRequestsCount; +	if (_runningRequestsCount == 0) debug("Storage is not working now"); +} +  Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {  	if (!errorCallback) errorCallback = getErrorPrintingCallback(); @@ -68,19 +83,22 @@ Networking::Request *Storage::download(Common::String remotePath, Common::String  		return nullptr;  	} -	return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); +	return addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f));  }  Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) {  	if (!errorCallback) errorCallback = getErrorPrintingCallback(); -	return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); +	return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive));  }  Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) {  	if (!errorCallback) errorCallback = getErrorPrintingCallback(); -	return ConnMan.addRequest(new SavesSyncRequest(this, callback, errorCallback)); +	return addRequest(new SavesSyncRequest(this, callback, errorCallback));  } +bool Storage::isWorking() { +	return _runningRequestsCount > 0; +}  } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1efee85bb3..b1c62ba05b 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -48,7 +48,9 @@ public:  	typedef Common::BaseCallback<UploadResponse> *UploadCallback;  	typedef Common::BaseCallback<ListDirectoryResponse> *ListDirectoryCallback; -protected:	 +protected: +	/** Keeps track of running requests. */ +	uint32 _runningRequestsCount;  	/** Returns default error callback (printErrorResponse). */  	virtual Networking::ErrorCallback getErrorPrintingCallback(); @@ -56,9 +58,25 @@ protected:  	/** Prints ErrorResponse contents with debug(). */  	virtual void printErrorResponse(Networking::ErrorResponse error); +	/** +	 * Adds request to the ConnMan, but also increases _runningRequestsCount. +	 * This method should be used by Storage implementations instead of +	 * direct ConnMan.addRequest() call. +	 * +	 * @return the same Request pointer, just as a shortcut +	 */ +	virtual Networking::Request *addRequest(Networking::Request *request); + +	/** +	 * Decreases _runningRequestCount. It's called from ConnMan automatically. +	 * Passed pointer is dangling, but one can use the address to determine +	 * some special Requests (which addresses were remembered somewhere). +	 */ +	virtual void requestFinishedCallback(Networking::Request *invalidRequestPointer); +  public: -	Storage() {} -	virtual ~Storage() {} +	Storage(); +	virtual ~Storage();  	/**  	 * Storage methods, which are used by CloudManager to save @@ -113,7 +131,7 @@ public:  	virtual Common::String savesDirectoryPath() = 0;  	/** Returns whether there are any requests running. */ -	virtual bool isWorking() = 0; +	virtual bool isWorking();  };  } // End of namespace Cloud diff --git a/backends/networking/curl/connectionmanager.cpp b/backends/networking/curl/connectionmanager.cpp index 949dc949f1..ef3c858bec 100644 --- a/backends/networking/curl/connectionmanager.cpp +++ b/backends/networking/curl/connectionmanager.cpp @@ -51,8 +51,8 @@ void ConnectionManager::registerEasyHandle(CURL *easy) {  	curl_multi_add_handle(_multi, easy);  } -Request *ConnectionManager::addRequest(Request *request) { -	_requests.push_back(request); +Request *ConnectionManager::addRequest(Request *request, RequestCallback callback) { +	_requests.push_back(RequestWithCallback(request, callback));  	if (!_timerStarted) startTimer();  	return request;  } @@ -89,10 +89,11 @@ void ConnectionManager::handle() {  void ConnectionManager::interateRequests() {  	//call handle() of all running requests (so they can do their work)  	debug("handling %d request(s)", _requests.size());	 -	for (Common::Array<Request *>::iterator i = _requests.begin(); i != _requests.end();) { -		Request *request = *i; +	for (Common::Array<RequestWithCallback>::iterator i = _requests.begin(); i != _requests.end();) { +		Request *request = i->request;  		if (!request || request->state() == FINISHED) { -			delete (*i); +			delete (i->request); +			if (i->callback) (*i->callback)(i->request); //that's not a mistake (we're passing an address and that method knows there is no object anymore)  			_requests.erase(i);  			continue;  		} diff --git a/backends/networking/curl/connectionmanager.h b/backends/networking/curl/connectionmanager.h index c632fa54ef..b39a779558 100644 --- a/backends/networking/curl/connectionmanager.h +++ b/backends/networking/curl/connectionmanager.h @@ -39,9 +39,18 @@ class NetworkReadStream;  class ConnectionManager : public Common::Singleton<ConnectionManager> {  	friend void connectionsThread(void *); //calls handle() +	typedef Common::BaseCallback<Request *> *RequestCallback; + +	struct RequestWithCallback { //I'm completely out of ideas +		Request *request; +		RequestCallback callback; +		 +		RequestWithCallback(Request *rq = nullptr, RequestCallback cb = nullptr): request(rq), callback(cb) {} +	}; +  	CURLM *_multi;	  	bool _timerStarted; -	Common::Array<Request *> _requests;	 +	Common::Array<RequestWithCallback> _requests;  	void startTimer(int interval = 1000000); //1 second is the default interval  	void stopTimer(); @@ -71,7 +80,7 @@ public:  	 *  	 * @return the same Request pointer, just as a shortcut  	 */ -	Request *addRequest(Request *request); +	Request *addRequest(Request *request, RequestCallback callback = nullptr);  };  /** Shortcut for accessing the connection manager. */ | 
