/* * Copyright 2021 (c) Matthieu Gallien * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #pragma once #include "owncloudpropagator.h" #include "abstractnetworkjob.h" #include #include #include #include #include namespace OCC { Q_DECLARE_LOGGING_CATEGORY(lcBulkPropagatorJob) class ComputeChecksum; class PutMultiFileJob; class BulkPropagatorJob : public PropagatorJob { Q_OBJECT /* This is a minified version of the SyncFileItem, * that holds only the specifics about the file that's * being uploaded. * * This is needed if we wanna apply changes on the file * that's being uploaded while keeping the original on disk. */ struct UploadFileInfo { QString _file; /// I'm still unsure if I should use a SyncFilePtr here. QString _path; /// the full path on disk. qint64 _size; }; struct BulkUploadItem { AccountPtr _account; SyncFileItemPtr _item; UploadFileInfo _fileToUpload; QString _remotePath; QString _localPath; qint64 _fileSize; QMap _headers; }; public: explicit BulkPropagatorJob(OwncloudPropagator *propagator, const std::deque &items); bool scheduleSelfOrChild() override; JobParallelism parallelism() override; private slots: void startUploadFile(SyncFileItemPtr item, UploadFileInfo fileToUpload); // Content checksum computed, compute the transmission checksum void slotComputeTransmissionChecksum(SyncFileItemPtr item, UploadFileInfo fileToUpload); // transmission checksum computed, prepare the upload void slotStartUpload(SyncFileItemPtr item, UploadFileInfo fileToUpload, const QByteArray &transmissionChecksumType, const QByteArray &transmissionChecksum); // invoked on internal error to unlock a folder and faile void slotOnErrorStartFolderUnlock(SyncFileItemPtr item, SyncFileItem::Status status, const QString &errorString); void slotPutFinished(); void slotUploadProgress(SyncFileItemPtr item, qint64 sent, qint64 total); void slotJobDestroyed(QObject *job); private: void doStartUpload(SyncFileItemPtr item, UploadFileInfo fileToUpload, QByteArray transmissionChecksumHeader); void adjustLastJobTimeout(AbstractNetworkJob *job, qint64 fileSize) const; void finalize(const QJsonObject &fullReply); void finalizeOneFile(const BulkUploadItem &oneFile); void slotPutFinishedOneFile(const BulkUploadItem &singleFile, OCC::PutMultiFileJob *job, const QJsonObject &fullReplyObject); void done(SyncFileItemPtr item, SyncFileItem::Status status, const QString &errorString); /** Bases headers that need to be sent on the PUT, or in the MOVE for chunking-ng */ [[nodiscard]] QMap headers(SyncFileItemPtr item) const; void abortWithError(SyncFileItemPtr item, SyncFileItem::Status status, const QString &error); /** * Checks whether the current error is one that should reset the whole * transfer if it happens too often. If so: Bump UploadInfo::errorCount * and maybe perform the reset. */ void checkResettingErrors(SyncFileItemPtr item) const; /** * Error handling functionality that is shared between jobs. */ void commonErrorHandling(SyncFileItemPtr item, const QString &errorMessage); bool checkFileStillExists(SyncFileItemPtr item, const bool finished, const QString &fullFilePath); bool checkFileChanged(SyncFileItemPtr item, const bool finished, const QString &fullFilePath); void computeFileId(SyncFileItemPtr item, const QJsonObject &fileReply) const; void handleFileRestoration(SyncFileItemPtr item, const QString &errorString) const; void handleBulkUploadBlackList(SyncFileItemPtr item) const; void handleJobDoneErrors(SyncFileItemPtr item, SyncFileItem::Status status); void triggerUpload(); void checkPropagationIsDone(); std::deque _items; QVector _jobs; /// network jobs that are currently in transit QSet _pendingChecksumFiles; std::vector _filesToUpload; SyncFileItem::Status _finalStatus = SyncFileItem::Status::NoStatus; }; }