1 /* 2 * Copyright 2021 (c) Matthieu Gallien <matthieu.gallien@nextcloud.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 */ 14 15 #pragma once 16 17 #include "owncloudpropagator.h" 18 #include "abstractnetworkjob.h" 19 20 #include <QLoggingCategory> 21 #include <QVector> 22 #include <QMap> 23 #include <QByteArray> 24 #include <deque> 25 26 namespace OCC { 27 28 Q_DECLARE_LOGGING_CATEGORY(lcBulkPropagatorJob) 29 30 class ComputeChecksum; 31 class PutMultiFileJob; 32 33 class BulkPropagatorJob : public PropagatorJob 34 { 35 Q_OBJECT 36 37 /* This is a minified version of the SyncFileItem, 38 * that holds only the specifics about the file that's 39 * being uploaded. 40 * 41 * This is needed if we wanna apply changes on the file 42 * that's being uploaded while keeping the original on disk. 43 */ 44 struct UploadFileInfo { 45 QString _file; /// I'm still unsure if I should use a SyncFilePtr here. 46 QString _path; /// the full path on disk. 47 qint64 _size; 48 }; 49 50 struct BulkUploadItem 51 { 52 AccountPtr _account; 53 SyncFileItemPtr _item; 54 UploadFileInfo _fileToUpload; 55 QString _remotePath; 56 QString _localPath; 57 qint64 _fileSize; 58 QMap<QByteArray, QByteArray> _headers; 59 }; 60 61 public: 62 explicit BulkPropagatorJob(OwncloudPropagator *propagator, 63 const std::deque<SyncFileItemPtr> &items); 64 65 bool scheduleSelfOrChild() override; 66 67 JobParallelism parallelism() override; 68 69 private slots: 70 void startUploadFile(SyncFileItemPtr item, UploadFileInfo fileToUpload); 71 72 // Content checksum computed, compute the transmission checksum 73 void slotComputeTransmissionChecksum(SyncFileItemPtr item, 74 UploadFileInfo fileToUpload); 75 76 // transmission checksum computed, prepare the upload 77 void slotStartUpload(SyncFileItemPtr item, 78 UploadFileInfo fileToUpload, 79 const QByteArray &transmissionChecksumType, 80 const QByteArray &transmissionChecksum); 81 82 // invoked on internal error to unlock a folder and faile 83 void slotOnErrorStartFolderUnlock(SyncFileItemPtr item, 84 SyncFileItem::Status status, 85 const QString &errorString); 86 87 void slotPutFinished(); 88 89 void slotUploadProgress(SyncFileItemPtr item, qint64 sent, qint64 total); 90 91 void slotJobDestroyed(QObject *job); 92 93 private: 94 void doStartUpload(SyncFileItemPtr item, 95 UploadFileInfo fileToUpload, 96 QByteArray transmissionChecksumHeader); 97 98 void adjustLastJobTimeout(AbstractNetworkJob *job, 99 qint64 fileSize) const; 100 101 void finalize(const QJsonObject &fullReply); 102 103 void finalizeOneFile(const BulkUploadItem &oneFile); 104 105 void slotPutFinishedOneFile(const BulkUploadItem &singleFile, 106 OCC::PutMultiFileJob *job, 107 const QJsonObject &fullReplyObject); 108 109 void done(SyncFileItemPtr item, 110 SyncFileItem::Status status, 111 const QString &errorString); 112 113 /** Bases headers that need to be sent on the PUT, or in the MOVE for chunking-ng */ 114 QMap<QByteArray, QByteArray> headers(SyncFileItemPtr item) const; 115 116 void abortWithError(SyncFileItemPtr item, 117 SyncFileItem::Status status, 118 const QString &error); 119 120 /** 121 * Checks whether the current error is one that should reset the whole 122 * transfer if it happens too often. If so: Bump UploadInfo::errorCount 123 * and maybe perform the reset. 124 */ 125 void checkResettingErrors(SyncFileItemPtr item) const; 126 127 /** 128 * Error handling functionality that is shared between jobs. 129 */ 130 void commonErrorHandling(SyncFileItemPtr item, 131 const QString &errorMessage); 132 133 bool checkFileStillExists(SyncFileItemPtr item, 134 const bool finished, 135 const QString &fullFilePath); 136 137 bool checkFileChanged(SyncFileItemPtr item, 138 const bool finished, 139 const QString &fullFilePath); 140 141 void computeFileId(SyncFileItemPtr item, 142 const QJsonObject &fileReply) const; 143 144 void handleFileRestoration(SyncFileItemPtr item, 145 const QString &errorString) const; 146 147 void handleBulkUploadBlackList(SyncFileItemPtr item) const; 148 149 void handleJobDoneErrors(SyncFileItemPtr item, 150 SyncFileItem::Status status); 151 152 void triggerUpload(); 153 154 void checkPropagationIsDone(); 155 156 std::deque<SyncFileItemPtr> _items; 157 158 QVector<AbstractNetworkJob *> _jobs; /// network jobs that are currently in transit 159 160 QSet<QString> _pendingChecksumFiles; 161 162 std::vector<BulkUploadItem> _filesToUpload; 163 164 SyncFileItem::Status _finalStatus = SyncFileItem::Status::NoStatus; 165 }; 166 167 } 168