#include "utility.h"
#include "filesystem.h"
#include "propagatorjobs.h"
+#include "transmissionchecksumvalidator.h"
+
#include <json.h>
#include <QNetworkAccessManager>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <cmath>
-#include <qtconcurrentrun.h>
namespace OCC {
return;
}
- /* Check if a checksum was transmitted */
- if( job->reply()->hasRawHeader(checkSumHeaderC)) {
- QByteArray header = job->reply()->rawHeader(checkSumHeaderC);
-
- bool ok = true;
-
- int indx = header.indexOf(':');
- if( indx < 0 ) {
- qDebug() << "Checksum header malformed:" << header;
- ok = false;
- }
-
- if( ok ) {
- const QByteArray type = header.left(indx).toUpper();
- _expectedHash = header.mid(indx+1);
-
- connect( &_watcher, SIGNAL(finished()), this, SLOT(slotDownloadChecksumCheckFinished()));
-
- // start the calculation in different thread
- if( type == checkSumMD5C ) {
- _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker, _tmpFile.fileName()));
- } else if( type == checkSumSHA1C ) {
- _watcher.setFuture(QtConcurrent::run(FileSystem::calcSha1Worker, _tmpFile.fileName()));
- }
-#ifdef ZLIB_FOUND
- else if( type == checkSumAdlerUpperC ) {
- _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, _tmpFile.fileName()));
- }
-#endif
- else {
- qDebug() << "Unknown checksum type" << type;
- ok = false;
- }
- }
-
- if( !ok) {
- _tmpFile.remove();
- _propagator->_anotherSyncNeeded = true;
- done(SyncFileItem::SoftError, tr("The checksum header was malformed."));
- return;
- }
- } else {
- // No OC-Checksum header, go directly to continue handle the download
- downloadFinished();
- }
+ // do whatever is needed to add a checksum to the http upload request.
+ // in any case, the validator will emit signal startUpload to let the flow
+ // continue in slotStartUpload here.
+ _validator = new TransmissionChecksumValidator( _tmpFile.fileName() );
+ connect(_validator, SIGNAL(validated()), this, SLOT(downloadFinished()));
+ connect(_validator, SIGNAL(validationFailed(QString)), this, SLOT(slotChecksumFail(QString)));
+ _validator->downloadValidation(job->reply()->rawHeader(checkSumHeaderC));
}
-void PropagateDownloadFileQNAM::slotDownloadChecksumCheckFinished()
+void PropagateDownloadFileQNAM::slotChecksumFail( const QString& errMsg )
{
- const QByteArray hash = _watcher.future().result();
-
- if( hash != _expectedHash ) {
- _tmpFile.remove();
- _propagator->_anotherSyncNeeded = true;
- done(SyncFileItem::SoftError, tr("The file downloaded with a broken checksum, will be redownloaded."));
- return;
- } else {
- qDebug() << "Checksum checked and matching: " << _expectedHash;
- }
-
- downloadFinished();
+ _validator->deleteLater();
+ _tmpFile.remove();
+ _propagator->_anotherSyncNeeded = true;
+ done(SyncFileItem::SoftError, errMsg ); // tr("The file downloaded with a broken checksum, will be redownloaded."));
}
QString makeConflictFileName(const QString &fn, const QDateTime &dt)
void PropagateDownloadFileQNAM::downloadFinished()
{
+ _validator->deleteLater();
+
QString fn = _propagator->getFilePath(_item._file);
// In case of file name clash, report an error
#include <QBuffer>
#include <QFile>
-#include <QFutureWatcher>
namespace OCC {
+class TransmissionChecksumValidator;
+
class GETFileJob : public AbstractNetworkJob {
Q_OBJECT
QFile* _device;
class PropagateDownloadFileQNAM : public PropagateItemJob {
Q_OBJECT
- QPointer<GETFileJob> _job;
-
- QFile _tmpFile;
public:
PropagateDownloadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item)
: PropagateItemJob(propagator, item) {}
void abort() Q_DECL_OVERRIDE;
void downloadFinished();
void slotDownloadProgress(qint64,qint64);
- void slotDownloadChecksumCheckFinished();
+ void slotChecksumFail( const QString& errMsg );
private:
- QByteArray _expectedHash;
- QFutureWatcher<QByteArray> _watcher;
- Utility::StopWatch _stopWatch;
+ // Utility::StopWatch _stopWatch;
+ QPointer<GETFileJob> _job;
+ QFile _tmpFile;
+ TransmissionChecksumValidator *_validator;
};
#include "utility.h"
#include "filesystem.h"
#include "propagatorjobs.h"
+#include "transmissionchecksumvalidator.h"
#include "configfile.h"
#include <json.h>
#include <QDir>
#include <cmath>
#include <cstring>
-#include <QtConcurrent>
#ifdef USE_NEON
#include "propagator_legacy.h"
return true;
}
-
void PropagateUploadFileQNAM::start()
{
if (_propagator->_abortRequested.fetchAndAddRelaxed(0)) {
return;
}
- ConfigFile cfg; // FIXME: Do not open it for each and every propagation.
const QString filePath = _propagator->getFilePath(_item._file);
+
+ // remember the modtime before checksumming to be able to detect a file
+ // change during the checksum calculation
_item._modtime = FileSystem::getModTime(filePath);
- // calculate the files checksum
- const QString transChecksum = cfg.transmissionChecksum();
_stopWatch.start();
- if( transChecksum.isEmpty() ) {
- // no checksumming required, jump to really start the uplaod
- startUpload();
- } else {
- // Calculate the checksum in a different thread first.
- connect( &_watcher, SIGNAL(finished()),
- this, SLOT(slotChecksumCalculated()));
- bool haveFuture = true;
- if( transChecksum == checkSumMD5C ) {
- _item._checksum = checkSumMD5C;
- _item._checksum += ":";
- _watcher.setFuture(QtConcurrent::run(FileSystem::calcMd5Worker,filePath));
-
- } else if( transChecksum == checkSumSHA1C ) {
- _item._checksum = checkSumSHA1C;
- _item._checksum += ":";
- _watcher.setFuture(QtConcurrent::run( FileSystem::calcSha1Worker, filePath));
- }
-#ifdef ZLIB_FOUND
- else if( transChecksum == checkSumAdlerC) {
- _item._checksum = checkSumAdlerC;
- _item._checksum += ":";
- _watcher.setFuture(QtConcurrent::run(FileSystem::calcAdler32Worker, filePath));
- }
-#endif
- else {
- haveFuture = false;
- }
- // in case there is a wrong checksum header, let continue without
- if( !haveFuture ) {
- startUpload();
- }
- }
-
+ // do whatever is needed to add a checksum to the http upload request.
+ // in any case, the validator will emit signal startUpload to let the flow
+ // continue in slotStartUpload here.
+ _validator = new TransmissionChecksumValidator(filePath);
+ connect(_validator, SIGNAL(validated()), this, SLOT(slotStartUpload()));
+ _validator->uploadValidation( &_item );
}
-void PropagateUploadFileQNAM::slotChecksumCalculated( )
+void PropagateUploadFileQNAM::slotStartUpload()
{
- QByteArray checksum = _watcher.future().result();
+ _validator->deleteLater();
- if( !checksum.isEmpty() ) {
- _item._checksum.append(checksum);
- } else {
- _item._checksum.clear();
- }
-
- startUpload();
-}
-
-void PropagateUploadFileQNAM::startUpload()
-{
const QString fullFilePath(_propagator->getFilePath(_item._file));
if (!FileSystem::fileExists(fullFilePath)) {
headers[checkSumHeaderC] = _item._checksum;
}
}
+ } else {
+ // checksum if its only one chunk
+ if( !_item._checksum.isEmpty() ) {
+ headers[checkSumHeaderC] = _item._checksum;
+ }
}
if (! device->prepareAndOpen(_propagator->getFilePath(_item._file), chunkStart, currentChunkSize)) {
#include <QBuffer>
#include <QFile>
#include <QDebug>
-#include <QFutureWatcher>
namespace OCC {
class BandwidthManager;
+class TransmissionChecksumValidator;
class UploadDevice : public QIODevice {
Q_OBJECT
QVector<PUTFileJob*> _jobs; /// network jobs that are currently in transit
bool _finished; // Tells that all the jobs have been finished
- // watcher for the checksum calculation thread
- QFutureWatcher<QByteArray> _watcher;
-
// measure the performance of checksum calc and upload
Utility::StopWatch _stopWatch;
+
+ TransmissionChecksumValidator *_validator;
+
public:
PropagateUploadFileQNAM(OwncloudPropagator* propagator,const SyncFileItem& item)
: PropagateItemJob(propagator, item), _startChunk(0), _currentChunk(0), _chunkCount(0), _transferId(0), _finished(false) {}
void startNextChunk();
void finalize(const SyncFileItem&);
void slotJobDestroyed(QObject *job);
- void startUpload();
- void slotChecksumCalculated();
+ void slotStartUpload();
+
private:
void startPollJob(const QString& path);
void abortWithError(SyncFileItem::Status status, const QString &error);