propagateupload.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (C) by Olivier Goffart <ogoffart@owncloud.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. #pragma once
  15. #include "owncloudpropagator.h"
  16. #include "networkjobs.h"
  17. #include <QBuffer>
  18. #include <QFile>
  19. #include <QDebug>
  20. namespace OCC {
  21. class BandwidthManager;
  22. /**
  23. * @brief The UploadDevice class
  24. * @ingroup libsync
  25. */
  26. class UploadDevice : public QIODevice {
  27. Q_OBJECT
  28. public:
  29. UploadDevice(BandwidthManager *bwm);
  30. ~UploadDevice();
  31. /** Reads the data from the file and opens the device */
  32. bool prepareAndOpen(const QString& fileName, qint64 start, qint64 size);
  33. qint64 writeData(const char* , qint64 ) Q_DECL_OVERRIDE;
  34. qint64 readData(char* data, qint64 maxlen) Q_DECL_OVERRIDE;
  35. bool atEnd() const Q_DECL_OVERRIDE;
  36. qint64 size() const Q_DECL_OVERRIDE;
  37. qint64 bytesAvailable() const Q_DECL_OVERRIDE;
  38. bool isSequential() const Q_DECL_OVERRIDE;
  39. bool seek ( qint64 pos ) Q_DECL_OVERRIDE;
  40. #if QT_VERSION < QT_VERSION_CHECK(5, 4, 2)
  41. bool reset() Q_DECL_OVERRIDE { emit wasReset(); return QIODevice::reset(); }
  42. #endif
  43. void setBandwidthLimited(bool);
  44. bool isBandwidthLimited() { return _bandwidthLimited; }
  45. void setChoked(bool);
  46. bool isChoked() { return _choked; }
  47. void giveBandwidthQuota(qint64 bwq);
  48. signals:
  49. #if QT_VERSION < 0x050402
  50. void wasReset();
  51. #endif
  52. private:
  53. // The file data
  54. QByteArray _data;
  55. // Position in the data
  56. qint64 _read;
  57. // Bandwidth manager related
  58. QPointer<BandwidthManager> _bandwidthManager;
  59. qint64 _bandwidthQuota;
  60. qint64 _readWithProgress;
  61. bool _bandwidthLimited; // if _bandwidthQuota will be used
  62. bool _choked; // if upload is paused (readData() will return 0)
  63. friend class BandwidthManager;
  64. protected slots:
  65. void slotJobUploadProgress(qint64 sent, qint64 t);
  66. };
  67. /**
  68. * @brief The PUTFileJob class
  69. * @ingroup libsync
  70. */
  71. class PUTFileJob : public AbstractNetworkJob {
  72. Q_OBJECT
  73. private:
  74. QScopedPointer<QIODevice> _device;
  75. QMap<QByteArray, QByteArray> _headers;
  76. QString _errorString;
  77. public:
  78. // Takes ownership of the device
  79. explicit PUTFileJob(AccountPtr account, const QString& path, QIODevice *device,
  80. const QMap<QByteArray, QByteArray> &headers, int chunk, QObject* parent = 0)
  81. : AbstractNetworkJob(account, path, parent), _device(device), _headers(headers), _chunk(chunk) {}
  82. ~PUTFileJob();
  83. int _chunk;
  84. virtual void start() Q_DECL_OVERRIDE;
  85. virtual bool finished() Q_DECL_OVERRIDE {
  86. emit finishedSignal();
  87. return true;
  88. }
  89. QString errorString() {
  90. return _errorString.isEmpty() ? reply()->errorString() : _errorString;
  91. }
  92. virtual void slotTimeout() Q_DECL_OVERRIDE;
  93. signals:
  94. void finishedSignal();
  95. void uploadProgress(qint64,qint64);
  96. private slots:
  97. #if QT_VERSION < 0x050402
  98. void slotSoftAbort();
  99. #endif
  100. };
  101. /**
  102. * @brief This job implements the asynchronous PUT
  103. *
  104. * If the server replies to a PUT with a OC-Finish-Poll url, we will query this url until the server
  105. * replies with an etag. https://github.com/owncloud/core/issues/12097
  106. * @ingroup libsync
  107. */
  108. class PollJob : public AbstractNetworkJob {
  109. Q_OBJECT
  110. SyncJournalDb *_journal;
  111. QString _localPath;
  112. public:
  113. SyncFileItemPtr _item;
  114. // Takes ownership of the device
  115. explicit PollJob(AccountPtr account, const QString &path, const SyncFileItemPtr &item,
  116. SyncJournalDb *journal, const QString &localPath, QObject *parent)
  117. : AbstractNetworkJob(account, path, parent), _journal(journal), _localPath(localPath), _item(item) {}
  118. void start() Q_DECL_OVERRIDE;
  119. bool finished() Q_DECL_OVERRIDE;
  120. void slotTimeout() Q_DECL_OVERRIDE {
  121. // emit finishedSignal(false);
  122. // deleteLater();
  123. qDebug() << Q_FUNC_INFO;
  124. reply()->abort();
  125. }
  126. signals:
  127. void finishedSignal();
  128. };
  129. /**
  130. * @brief The PropagateUploadFileQNAM class
  131. * @ingroup libsync
  132. */
  133. class PropagateUploadFileQNAM : public PropagateItemJob {
  134. Q_OBJECT
  135. private:
  136. /**
  137. * That's the start chunk that was stored in the database for resuming.
  138. * In the non-resuming case it is 0.
  139. * If we are resuming, this is the first chunk we need to send
  140. */
  141. int _startChunk;
  142. /**
  143. * This is the next chunk that we need to send. Starting from 0 even if _startChunk != 0
  144. * (In other words, _startChunk + _currentChunk is really the number of the chunk we need to send next)
  145. * (In other words, _currentChunk is the number of the chunk that we already sent or started sending)
  146. */
  147. int _currentChunk;
  148. int _chunkCount; /// Total number of chunks for this file
  149. int _transferId; /// transfer id (part of the url)
  150. QElapsedTimer _duration;
  151. QVector<PUTFileJob*> _jobs; /// network jobs that are currently in transit
  152. bool _finished; // Tells that all the jobs have been finished
  153. // measure the performance of checksum calc and upload
  154. Utility::StopWatch _stopWatch;
  155. QByteArray _transmissionChecksum;
  156. QByteArray _transmissionChecksumType;
  157. public:
  158. PropagateUploadFileQNAM(OwncloudPropagator* propagator,const SyncFileItemPtr& item)
  159. : PropagateItemJob(propagator, item), _startChunk(0), _currentChunk(0), _chunkCount(0), _transferId(0), _finished(false) {}
  160. void start() Q_DECL_OVERRIDE;
  161. private slots:
  162. void slotPutFinished();
  163. void slotPollFinished();
  164. void slotUploadProgress(qint64,qint64);
  165. void abort() Q_DECL_OVERRIDE;
  166. void startNextChunk();
  167. void finalize(const SyncFileItem&);
  168. void slotJobDestroyed(QObject *job);
  169. void slotStartUpload(const QByteArray& transmissionChecksumType, const QByteArray& transmissionChecksum);
  170. void slotComputeTransmissionChecksum(const QByteArray& contentChecksumType, const QByteArray& contentChecksum);
  171. private:
  172. void startPollJob(const QString& path);
  173. void abortWithError(SyncFileItem::Status status, const QString &error);
  174. };
  175. }