CLOUD: Add ListDirectoryStatus struct

It contains flags to indicate whether Request was interrupted or failed,
so dependent Requests may see that list is incomplete.
This commit is contained in:
Alexander Tkachev 2016-05-30 18:13:31 +06:00
parent a19fc52c32
commit aa987e5c52
14 changed files with 155 additions and 101 deletions

View file

@ -22,23 +22,32 @@
#include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h"
#include "backends/cloud/iso8601.h" #include "backends/cloud/iso8601.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/curljsonrequest.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/json.h" #include "common/json.h"
#include "backends/cloud/storage.h"
namespace Cloud { namespace Cloud {
namespace Dropbox { namespace Dropbox {
DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive): DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive):
Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _filesCallback(cb), Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb),
_token(token), _complete(false), _innerRequest(nullptr) { _token(token), _workingRequest(nullptr), _ignoreCallback(false) {
startupWork(); start();
} }
void DropboxListDirectoryRequest::startupWork() { DropboxListDirectoryRequest::~DropboxListDirectoryRequest() {
_ignoreCallback = true;
if (_workingRequest) _workingRequest->finish();
delete _listDirectoryCallback;
}
void DropboxListDirectoryRequest::start() {
_ignoreCallback = true;
if (_workingRequest) _workingRequest->finish();
_files.clear(); _files.clear();
_complete = false; _ignoreCallback = false;
Networking::JsonCallback innerCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback); Networking::JsonCallback innerCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback);
Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder");
@ -54,39 +63,50 @@ void DropboxListDirectoryRequest::startupWork() {
Common::JSONValue value(jsonRequestParameters); Common::JSONValue value(jsonRequestParameters);
request->addPostField(Common::JSON::stringify(&value)); request->addPostField(Common::JSON::stringify(&value));
_innerRequest = ConnMan.addRequest(request); _workingRequest = ConnMan.addRequest(request);
} }
void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair) { void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair) {
_workingRequest = nullptr;
if (_ignoreCallback) return;
ListDirectoryStatus status(_files);
Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request;
if (rq && rq->getNetworkReadStream())
status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
Common::JSONValue *json = pair.value; Common::JSONValue *json = pair.value;
if (json) { if (json) {
Common::JSONObject response = json->asObject(); Common::JSONObject response = json->asObject();
if (response.contains("error") || response.contains("error_summary")) { if (response.contains("error") || response.contains("error_summary")) {
warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str());
_complete = true; status.failed = true;
status.response = json->stringify();
finishStatus(status);
delete json; delete json;
return; return;
} }
//TODO: check that all keys exist to avoid segfaults //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults
//TODO: get more files in the folder to check "has_more" case
Common::JSONArray items = response.getVal("entries")->asArray(); if (response.contains("entries")) {
for (uint32 i = 0; i < items.size(); ++i) { Common::JSONArray items = response.getVal("entries")->asArray();
Common::JSONObject item = items[i]->asObject(); for (uint32 i = 0; i < items.size(); ++i) {
Common::String path = item.getVal("path_lower")->asString(); Common::JSONObject item = items[i]->asObject();
bool isDirectory = (item.getVal(".tag")->asString() == "folder"); Common::String path = item.getVal("path_lower")->asString();
uint32 size = 0, timestamp = 0; bool isDirectory = (item.getVal(".tag")->asString() == "folder");
if (!isDirectory) { uint32 size = 0, timestamp = 0;
size = item.getVal("size")->asIntegerNumber(); if (!isDirectory) {
timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); size = item.getVal("size")->asIntegerNumber();
timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString());
}
_files.push_back(StorageFile(path, size, timestamp, isDirectory));
} }
_files.push_back(StorageFile(path, size, timestamp, isDirectory));
} }
bool hasMore = response.getVal("has_more")->asBool(); bool hasMore = (response.contains("has_more") && response.getVal("has_more")->asBool());
if (hasMore) { if (hasMore) {
Networking::JsonCallback innerCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback); Networking::JsonCallback innerCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback);
@ -100,40 +120,33 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair
Common::JSONValue value(jsonRequestParameters); Common::JSONValue value(jsonRequestParameters);
request->addPostField(Common::JSON::stringify(&value)); request->addPostField(Common::JSON::stringify(&value));
ConnMan.addRequest(request); _workingRequest = ConnMan.addRequest(request);
} else { } else {
_complete = true; finishStatus(status);
} }
} else { } else {
warning("null, not json"); warning("null, not json");
_complete = true; status.failed = true;
finishStatus(status);
} }
delete json; delete json;
} }
void DropboxListDirectoryRequest::handle() { void DropboxListDirectoryRequest::handle() {}
if (_complete) finishFiles(_files);
}
void DropboxListDirectoryRequest::restart() { void DropboxListDirectoryRequest::restart() { start(); }
if (_innerRequest) {
//TODO: I'm really not sure some CurlRequest would handle this (it must stop corresponding CURL transfer)
_innerRequest->finish(); //may be CANCELED or INTERRUPTED or something?
_innerRequest = nullptr;
}
startupWork();
}
void DropboxListDirectoryRequest::finish() { void DropboxListDirectoryRequest::finish() {
Common::Array<StorageFile> files; Common::Array<StorageFile> files;
finishFiles(files); ListDirectoryStatus status(files);
status.interrupted = true;
finishStatus(status);
} }
void DropboxListDirectoryRequest::finishFiles(Common::Array<StorageFile> &files) { void DropboxListDirectoryRequest::finishStatus(ListDirectoryStatus status) {
Request::finish(); Request::finish();
if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status));
} }
} // End of namespace Dropbox } // End of namespace Dropbox

View file

@ -35,20 +35,18 @@ class DropboxListDirectoryRequest: public Networking::Request {
Common::String _requestedPath; Common::String _requestedPath;
bool _requestedRecursive; bool _requestedRecursive;
Storage::FileArrayCallback _filesCallback; Storage::ListDirectoryCallback _listDirectoryCallback;
Common::String _token; Common::String _token;
bool _complete;
Common::Array<StorageFile> _files; Common::Array<StorageFile> _files;
Request *_innerRequest; Request *_workingRequest;
bool _ignoreCallback;
void start();
void responseCallback(Networking::JsonResponse pair); void responseCallback(Networking::JsonResponse pair);
void startupWork(); void finishStatus(ListDirectoryStatus status);
void finishFiles(Common::Array<StorageFile> &files);
public: public:
DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false);
virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } virtual ~DropboxListDirectoryRequest();
virtual void handle(); virtual void handle();
virtual void restart(); virtual void restart();

View file

@ -125,7 +125,7 @@ void DropboxStorage::printUploadStatus(UploadResponse pair) {
} }
} }
Networking::Request *DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, bool recursive) {
return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive));
} }

View file

@ -67,10 +67,10 @@ public:
/** Public Cloud API comes down there. */ /** Public Cloud API comes down there. */
/** Returns Common::Array<StorageFile>. */ /** Returns ListDirectoryStatus struct with list of files. */
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false);
/** Calls the callback when finished. */ /** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback 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); virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback);

View file

@ -45,7 +45,6 @@ DropboxUploadRequest::~DropboxUploadRequest() {
delete _uploadCallback; delete _uploadCallback;
} }
void DropboxUploadRequest::start() { void DropboxUploadRequest::start() {
_ignoreCallback = true; _ignoreCallback = true;
if (_workingRequest) _workingRequest->finish(); if (_workingRequest) _workingRequest->finish();

View file

@ -50,15 +50,21 @@ void FolderDownloadRequest::start() {
//list directory first //list directory first
_workingRequest = _storage->listDirectory( _workingRequest = _storage->listDirectory(
_remoteDirectoryPath, _remoteDirectoryPath,
new Common::Callback<FolderDownloadRequest, Storage::FileArrayResponse>(this, &FolderDownloadRequest::directoryListedCallback), new Common::Callback<FolderDownloadRequest, Storage::ListDirectoryResponse>(this, &FolderDownloadRequest::directoryListedCallback),
_recursive _recursive
); );
} }
void FolderDownloadRequest::directoryListedCallback(Storage::FileArrayResponse pair) { void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) {
if (_ignoreCallback) return; if (_ignoreCallback) return;
//TODO: somehow ListDirectory requests must indicate that file array is incomplete
_files = pair.value; ListDirectoryStatus status = pair.value;
if (status.failed || status.interrupted) {
finish();
return;
}
_files = pair.value.files;
downloadNextFile(); downloadNextFile();
} }

View file

@ -26,7 +26,6 @@
#include "backends/networking/curl/request.h" #include "backends/networking/curl/request.h"
#include "backends/networking/curl/networkreadstream.h" #include "backends/networking/curl/networkreadstream.h"
#include "backends/cloud/storage.h" #include "backends/cloud/storage.h"
#include "common/file.h"
namespace Cloud { namespace Cloud {
@ -41,7 +40,7 @@ class FolderDownloadRequest: public Networking::Request {
bool _ignoreCallback; bool _ignoreCallback;
void start(); void start();
void directoryListedCallback(Storage::FileArrayResponse pair); void directoryListedCallback(Storage::ListDirectoryResponse pair);
void fileDownloadedCallback(Storage::BoolResponse pair); void fileDownloadedCallback(Storage::BoolResponse pair);
void downloadNextFile(); void downloadNextFile();
void finishFiles(Common::Array<StorageFile> &files); void finishFiles(Common::Array<StorageFile> &files);

View file

@ -25,18 +25,25 @@
#include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivetokenrefresher.h"
#include "backends/cloud/iso8601.h" #include "backends/cloud/iso8601.h"
#include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/networkreadstream.h"
#include "common/json.h" #include "common/json.h"
namespace Cloud { namespace Cloud {
namespace OneDrive { namespace OneDrive {
OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive): OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive):
Networking::Request(0), Networking::Request(0),
_requestedPath(path), _requestedRecursive(recursive), _storage(storage), _filesCallback(cb), _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb),
_workingRequest(nullptr), _ignoreCallback(false) { _workingRequest(nullptr), _ignoreCallback(false) {
start(); start();
} }
OneDriveListDirectoryRequest::~OneDriveListDirectoryRequest() {
_ignoreCallback = true;
if (_workingRequest) _workingRequest->finish();
delete _listDirectoryCallback;
}
void OneDriveListDirectoryRequest::start() { void OneDriveListDirectoryRequest::start() {
//cleanup //cleanup
_ignoreCallback = true; _ignoreCallback = true;
@ -48,12 +55,12 @@ void OneDriveListDirectoryRequest::start() {
_ignoreCallback = false; _ignoreCallback = false;
_directoriesQueue.push_back(_requestedPath); _directoriesQueue.push_back(_requestedPath);
listNextDirectory(); listNextDirectory(_files);
} }
void OneDriveListDirectoryRequest::listNextDirectory() { void OneDriveListDirectoryRequest::listNextDirectory(ListDirectoryStatus status) {
if (_directoriesQueue.empty()) { if (_directoriesQueue.empty()) {
finishFiles(_files); finishStatus(status);
return; return;
} }
@ -76,7 +83,8 @@ void OneDriveListDirectoryRequest::makeRequest(Common::String url) {
_workingRequest = ConnMan.addRequest(request); _workingRequest = ConnMan.addRequest(request);
} }
void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) {
_workingRequest = nullptr;
Common::JSONValue *json = pair.value; Common::JSONValue *json = pair.value;
if (_ignoreCallback) { if (_ignoreCallback) {
@ -84,26 +92,29 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo
return; return;
} }
ListDirectoryStatus status(_files);
Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request;
if (rq && rq->getNetworkReadStream())
status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
if (!json) { if (!json) {
finish(); status.failed = true;
finishStatus(status);
return; return;
} }
Common::JSONObject response = json->asObject(); Common::JSONObject response = json->asObject();
//TODO: check that all keys exist to avoid segfaults //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults
Common::JSONArray items = response.getVal("value")->asArray(); Common::JSONArray items = response.getVal("value")->asArray();
for (uint32 i = 0; i < items.size(); ++i) { for (uint32 i = 0; i < items.size(); ++i) {
Common::JSONObject item = items[i]->asObject(); Common::JSONObject item = items[i]->asObject();
Common::String path = _currentDirectory + item.getVal("name")->asString(); Common::String path = _currentDirectory + item.getVal("name")->asString();
bool isDirectory = item.contains("folder"); bool isDirectory = item.contains("folder");
uint32 size = 0, timestamp = 0; uint32 size = item.getVal("size")->asIntegerNumber();
//if (!isDirectory) { uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString());
size = item.getVal("size")->asNumber();
timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString());
//}
StorageFile file(path, size, timestamp, isDirectory); StorageFile file(path, size, timestamp, isDirectory);
_files.push_back(file); _files.push_back(file);
@ -116,21 +127,22 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo
if (hasMore) { if (hasMore) {
makeRequest(response.getVal("@odata.nextLink")->asString()); makeRequest(response.getVal("@odata.nextLink")->asString());
} else { } else {
listNextDirectory(); listNextDirectory(status);
} }
delete json; delete json;
} }
void OneDriveListDirectoryRequest::finish() { void OneDriveListDirectoryRequest::finish() {
//TODO: indicate it's interrupted
Common::Array<StorageFile> files; Common::Array<StorageFile> files;
finishFiles(files); ListDirectoryStatus status(files);
status.interrupted = true;
finishStatus(status);
} }
void OneDriveListDirectoryRequest::finishFiles(Common::Array<StorageFile> &files) { void OneDriveListDirectoryRequest::finishStatus(ListDirectoryStatus status) {
Request::finish(); Request::finish();
if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status));
} }
} // End of namespace OneDrive } // End of namespace OneDrive

View file

@ -37,7 +37,7 @@ class OneDriveListDirectoryRequest: public Networking::Request {
Common::String _requestedPath; Common::String _requestedPath;
bool _requestedRecursive; bool _requestedRecursive;
OneDriveStorage *_storage; OneDriveStorage *_storage;
Storage::FileArrayCallback _filesCallback; Storage::ListDirectoryCallback _listDirectoryCallback;
Common::Array<StorageFile> _files; Common::Array<StorageFile> _files;
Common::Array<Common::String> _directoriesQueue; Common::Array<Common::String> _directoriesQueue;
Common::String _currentDirectory; Common::String _currentDirectory;
@ -45,13 +45,13 @@ class OneDriveListDirectoryRequest: public Networking::Request {
bool _ignoreCallback; bool _ignoreCallback;
void start(); void start();
void listNextDirectory(); void listNextDirectory(ListDirectoryStatus status);
void listedDirectoryCallback(Networking::JsonResponse pair); void listedDirectoryCallback(Networking::JsonResponse pair);
void makeRequest(Common::String url); void makeRequest(Common::String url);
void finishFiles(Common::Array<StorageFile> &files); void finishStatus(ListDirectoryStatus status);
public: public:
OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false);
virtual ~OneDriveListDirectoryRequest() { delete _filesCallback; } virtual ~OneDriveListDirectoryRequest();
virtual void handle() {} virtual void handle() {}
virtual void restart() { start(); } virtual void restart() { start(); }

View file

@ -163,7 +163,7 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out
delete pair.value; delete pair.value;
} }
Networking::Request *OneDriveStorage::listDirectory(Common::String path, FileArrayCallback callback, bool recursive) { Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive) {
return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, recursive)); return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, recursive));
} }

View file

@ -72,10 +72,10 @@ public:
/** Public Cloud API comes down there. */ /** Public Cloud API comes down there. */
/** Returns Common::Array<StorageFile>. */ /** Returns ListDirectoryStatus struct with list of files. */
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false);
/** Calls the callback when finished. */ /** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback 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; } virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { return nullptr; }

View file

@ -55,17 +55,22 @@ void SavesSyncRequest::start() {
loadTimestamps(); loadTimestamps();
//list saves directory //list saves directory
_workingRequest = _storage->listDirectory("saves", new Common::Callback<SavesSyncRequest, Storage::FileArrayResponse>(this, &SavesSyncRequest::directoryListedCallback)); _workingRequest = _storage->listDirectory("saves", new Common::Callback<SavesSyncRequest, Storage::ListDirectoryResponse>(this, &SavesSyncRequest::directoryListedCallback));
} }
void SavesSyncRequest::directoryListedCallback(Storage::FileArrayResponse pair) { void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) {
if (_ignoreCallback) return; if (_ignoreCallback) return;
//TODO: somehow ListDirectory requests must indicate that file array is incomplete
ListDirectoryStatus status = pair.value;
if (status.interrupted || status.failed) {
finishBool(false);
return;
}
const uint32 INVALID_TIMESTAMP = UINT_MAX; const uint32 INVALID_TIMESTAMP = UINT_MAX;
//determine which files to download and which files to upload //determine which files to download and which files to upload
Common::Array<StorageFile> &remoteFiles = pair.value; Common::Array<StorageFile> &remoteFiles = status.files;
for (uint32 i = 0; i < remoteFiles.size(); ++i) { for (uint32 i = 0; i < remoteFiles.size(); ++i) {
StorageFile &file = remoteFiles[i]; StorageFile &file = remoteFiles[i];
if (file.isDirectory()) continue; if (file.isDirectory()) continue;

View file

@ -42,7 +42,7 @@ class SavesSyncRequest: public Networking::Request {
bool _ignoreCallback; bool _ignoreCallback;
void start(); void start();
void directoryListedCallback(Storage::FileArrayResponse pair); void directoryListedCallback(Storage::ListDirectoryResponse pair);
void fileDownloadedCallback(Storage::BoolResponse pair); void fileDownloadedCallback(Storage::BoolResponse pair);
void fileUploadedCallback(Storage::UploadResponse pair); void fileUploadedCallback(Storage::UploadResponse pair);
void downloadNextFile(); void downloadNextFile();

View file

@ -54,17 +54,39 @@ struct UploadStatus {
interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {} interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {}
}; };
/** Struct to represent upload() resulting status. */
struct ListDirectoryStatus {
/** 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 listed files (might be incomplete if failed or interrupted) */
Common::Array<StorageFile> &files;
/** Server's original response (empty if not failed) */
Common::String response;
/** Server's HTTP response code. */
long httpResponseCode;
ListDirectoryStatus(Common::Array<StorageFile> &f) :
interrupted(false), failed(false), files(f), response(), httpResponseCode(-1) {}
ListDirectoryStatus(bool interrupt, bool failure, Common::Array<StorageFile> &f, Common::String resp, long code) :
interrupted(interrupt), failed(failure), files(f), response(resp), httpResponseCode(code) {}
};
class Storage { class Storage {
public: public:
typedef Networking::Response<Common::Array<StorageFile>&> FileArrayResponse; typedef Networking::Response<Common::Array<StorageFile>&> FileArrayResponse;
typedef Networking::Response<StorageInfo> StorageInfoResponse; typedef Networking::Response<StorageInfo> StorageInfoResponse;
typedef Networking::Response<bool> BoolResponse; typedef Networking::Response<bool> BoolResponse;
typedef Networking::Response<UploadStatus> UploadResponse; typedef Networking::Response<UploadStatus> UploadResponse;
typedef Networking::Response<ListDirectoryStatus> ListDirectoryResponse;
typedef Common::BaseCallback<FileArrayResponse> *FileArrayCallback; typedef Common::BaseCallback<FileArrayResponse> *FileArrayCallback;
typedef Common::BaseCallback<StorageInfoResponse> *StorageInfoCallback; typedef Common::BaseCallback<StorageInfoResponse> *StorageInfoCallback;
typedef Common::BaseCallback<BoolResponse> *BoolCallback; typedef Common::BaseCallback<BoolResponse> *BoolCallback;
typedef Common::BaseCallback<UploadResponse> *UploadCallback; typedef Common::BaseCallback<UploadResponse> *UploadCallback;
typedef Common::BaseCallback<ListDirectoryResponse> *ListDirectoryCallback;
Storage() {} Storage() {}
virtual ~Storage() {} virtual ~Storage() {}
@ -90,10 +112,10 @@ public:
* a callback, which is called, when request is complete. * a callback, which is called, when request is complete.
*/ */
/** Returns Common::Array<StorageFile>. */ /** Returns ListDirectoryStatus struct with list of files. */
virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false) = 0;
/** Calls the callback when finished. */ /** Returns UploadStatus struct with info about uploaded file. */
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback 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; virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) = 0;