aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Tkachev2016-06-01 12:39:10 +0600
committerAlexander Tkachev2016-08-24 16:07:55 +0600
commita66322408f95ff7b29cf6967eaecaac06dfe5b31 (patch)
treea55a9390a3ab12566aec0478e633d30ae988103d
parent4b3a8be0b9db448971e6095a24501c66714c484f (diff)
downloadscummvm-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.cpp8
-rw-r--r--backends/cloud/dropbox/dropboxstorage.h3
-rw-r--r--backends/cloud/onedrive/onedrivestorage.cpp12
-rw-r--r--backends/cloud/onedrive/onedrivestorage.h3
-rw-r--r--backends/cloud/storage.cpp24
-rw-r--r--backends/cloud/storage.h26
-rw-r--r--backends/networking/curl/connectionmanager.cpp11
-rw-r--r--backends/networking/curl/connectionmanager.h13
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. */