ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

folderdownloadrequest.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
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     //cleanup
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     //list directory first
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     // remove all directories
00075     // non-empty directories would be created by DumpFile, and empty ones are just ignored
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()); // directories are actually removed earlier, in the directoryListedCallback()
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 } // End of namespace Cloud


Generated on Sat May 18 2019 05:01:02 for ResidualVM by doxygen 1.7.1
curved edge   curved edge