Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "backends/cloud/folderdownloadrequest.h"
00024 #include "backends/cloud/downloadrequest.h"
00025 #include "backends/cloud/id/iddownloadrequest.h"
00026 #include "common/debug.h"
00027 #include "gui/downloaddialog.h"
00028 #include <backends/networking/curl/connectionmanager.h>
00029
00030 namespace Cloud {
00031
00032 FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive):
00033 Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _fileArrayCallback(callback),
00034 _remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive),
00035 _workingRequest(nullptr), _ignoreCallback(false), _totalFiles(0) {
00036 start();
00037 }
00038
00039 FolderDownloadRequest::~FolderDownloadRequest() {
00040 sendCommand(GUI::kDownloadEndedCmd, 0);
00041 _ignoreCallback = true;
00042 if (_workingRequest)
00043 _workingRequest->finish();
00044 delete _fileArrayCallback;
00045 }
00046
00047 void FolderDownloadRequest::start() {
00048
00049 _ignoreCallback = true;
00050 if (_workingRequest)
00051 _workingRequest->finish();
00052 _currentFile = StorageFile();
00053 _pendingFiles.clear();
00054 _failedFiles.clear();
00055 _ignoreCallback = false;
00056 _totalFiles = 0;
00057 _downloadedBytes = _totalBytes = _wasDownloadedBytes = _currentDownloadSpeed = 0;
00058
00059
00060 _workingRequest = _storage->listDirectory(
00061 _remoteDirectoryPath,
00062 new Common::Callback<FolderDownloadRequest, Storage::ListDirectoryResponse>(this, &FolderDownloadRequest::directoryListedCallback),
00063 new Common::Callback<FolderDownloadRequest, Networking::ErrorResponse>(this, &FolderDownloadRequest::directoryListedErrorCallback),
00064 _recursive
00065 );
00066 }
00067
00068 void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse response) {
00069 _workingRequest = nullptr;
00070 if (_ignoreCallback)
00071 return;
00072 _pendingFiles = response.value;
00073
00074
00075
00076 for (Common::Array<StorageFile>::iterator i = _pendingFiles.begin(); i != _pendingFiles.end();)
00077 if (i->isDirectory())
00078 _pendingFiles.erase(i);
00079 else {
00080 _totalBytes += i->size();
00081 ++i;
00082 }
00083
00084 _totalFiles = _pendingFiles.size();
00085 downloadNextFile();
00086 }
00087
00088 void FolderDownloadRequest::directoryListedErrorCallback(Networking::ErrorResponse error) {
00089 _workingRequest = nullptr;
00090 if (_ignoreCallback)
00091 return;
00092 finishError(error);
00093 }
00094
00095 void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse response) {
00096 _workingRequest = nullptr;
00097 if (_ignoreCallback)
00098 return;
00099 if (!response.value) _failedFiles.push_back(_currentFile);
00100 _downloadedBytes += _currentFile.size();
00101 downloadNextFile();
00102 }
00103
00104 void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) {
00105 _workingRequest = nullptr;
00106 if (_ignoreCallback)
00107 return;
00108 fileDownloadedCallback(Storage::BoolResponse(error.request, false));
00109 }
00110
00111 void FolderDownloadRequest::downloadNextFile() {
00112 do {
00113 if (_pendingFiles.empty()) {
00114 sendCommand(GUI::kDownloadEndedCmd, 0);
00115 finishDownload(_failedFiles);
00116 return;
00117 }
00118
00119 _currentFile = _pendingFiles.back();
00120 _pendingFiles.pop_back();
00121 } while (_currentFile.isDirectory());
00122
00123 sendCommand(GUI::kDownloadProgressCmd, (int)(getProgress() * 100));
00124
00125 Common::String remotePath = _currentFile.path();
00126 Common::String localPath = remotePath;
00127 if (_remoteDirectoryPath == "" || remotePath.hasPrefix(_remoteDirectoryPath)) {
00128 localPath.erase(0, _remoteDirectoryPath.size());
00129 if (_remoteDirectoryPath != "" && (_remoteDirectoryPath.lastChar() != '/' && _remoteDirectoryPath.lastChar() != '\\'))
00130 localPath.erase(0, 1);
00131 } else {
00132 warning("FolderDownloadRequest: Can't process the following paths:");
00133 warning("remote directory: %s", _remoteDirectoryPath.c_str());
00134 warning("remote file under that directory: %s", remotePath.c_str());
00135 }
00136 if (_localDirectoryPath != "") {
00137 if (_localDirectoryPath.lastChar() == '/' || _localDirectoryPath.lastChar() == '\\')
00138 localPath = _localDirectoryPath + localPath;
00139 else
00140 localPath = _localDirectoryPath + "/" + localPath;
00141 }
00142 debug(9, "FolderDownloadRequest: %s -> %s", remotePath.c_str(), localPath.c_str());
00143 _workingRequest = _storage->downloadById(
00144 _currentFile.id(), localPath,
00145 new Common::Callback<FolderDownloadRequest, Storage::BoolResponse>(this, &FolderDownloadRequest::fileDownloadedCallback),
00146 new Common::Callback<FolderDownloadRequest, Networking::ErrorResponse>(this, &FolderDownloadRequest::fileDownloadedErrorCallback)
00147 );
00148 }
00149
00150 void FolderDownloadRequest::handle() {
00151 uint32 microsecondsPassed = Networking::ConnectionManager::getCloudRequestsPeriodInMicroseconds();
00152 uint64 currentDownloadedBytes = getDownloadedBytes();
00153 uint64 downloadedThisPeriod = currentDownloadedBytes - _wasDownloadedBytes;
00154 _currentDownloadSpeed = downloadedThisPeriod * (1000000L / microsecondsPassed);
00155 _wasDownloadedBytes = currentDownloadedBytes;
00156 }
00157
00158 void FolderDownloadRequest::restart() { start(); }
00159
00160 void FolderDownloadRequest::finishDownload(Common::Array<StorageFile> &files) {
00161 Request::finishSuccess();
00162 if (_fileArrayCallback)
00163 (*_fileArrayCallback)(Storage::FileArrayResponse(this, files));
00164 }
00165
00166 double FolderDownloadRequest::getProgress() const {
00167 if (_totalFiles == 0 || _totalBytes == 0)
00168 return 0;
00169 return (double)getDownloadedBytes() / (double)getTotalBytesToDownload();
00170 }
00171
00172 uint64 FolderDownloadRequest::getDownloadedBytes() const {
00173 if (_totalFiles == 0)
00174 return 0;
00175
00176 double currentFileProgress = 0;
00177 DownloadRequest *downloadRequest = dynamic_cast<DownloadRequest *>(_workingRequest);
00178 if (downloadRequest != nullptr) {
00179 currentFileProgress = downloadRequest->getProgress();
00180 } else {
00181 Id::IdDownloadRequest *idDownloadRequest = dynamic_cast<Id::IdDownloadRequest *>(_workingRequest);
00182 if (idDownloadRequest != nullptr)
00183 currentFileProgress = idDownloadRequest->getProgress();
00184 }
00185
00186 return _downloadedBytes + (uint64)(currentFileProgress * _currentFile.size());
00187 }
00188
00189 uint64 FolderDownloadRequest::getTotalBytesToDownload() const {
00190 return _totalBytes;
00191 }
00192
00193 uint64 FolderDownloadRequest::getDownloadSpeed() const {
00194 return _currentDownloadSpeed;
00195 }
00196
00197 }