From 683e4430eb0a3bf77e4d2a9a60e57308f36f891c Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 16 May 2018 15:08:33 +0200 Subject: [PATCH] Upload: Adjust timeout for final job based on size #6527 Some servers have virus scanners and the like that can delay the response of the final chunked upload assembly significantly, often breaking the current 5min (!) timeout. See owncloud/enterprise#2480 for details. --- src/libsync/propagateupload.cpp | 10 ++++++++++ src/libsync/propagateupload.h | 11 +++++++++++ src/libsync/propagateuploadng.cpp | 1 + src/libsync/propagateuploadv1.cpp | 2 ++ 4 files changed, 24 insertions(+) diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index 712a08603a5..ef89f41877c 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -545,6 +545,16 @@ void PropagateUploadFileCommon::commonErrorHandling(AbstractNetworkJob *job) abortWithError(status, errorString); } +void PropagateUploadFileCommon::adjustLastJobTimeout(AbstractNetworkJob *job, quint64 fileSize) +{ + job->setTimeout(qBound( + job->timeoutMsec(), + // Calculate 3 minutes for each gigabyte of data + qint64((3 * 60 * 1000) * fileSize / 1e9), + // Maximum of 30 minutes + qint64(30 * 60 * 1000))); +} + void PropagateUploadFileCommon::slotJobDestroyed(QObject *job) { _jobs.erase(std::remove(_jobs.begin(), _jobs.end(), job), _jobs.end()); diff --git a/src/libsync/propagateupload.h b/src/libsync/propagateupload.h index a69ad9e7375..b0c609d2c2c 100644 --- a/src/libsync/propagateupload.h +++ b/src/libsync/propagateupload.h @@ -274,6 +274,17 @@ private slots: */ void commonErrorHandling(AbstractNetworkJob *job); + /** + * Increases the timeout for the final MOVE/PUT for large files. + * + * This is an unfortunate workaround since the drawback is not being able to + * detect real disconnects in a timely manner. Shall go away when the server + * response starts coming quicker, or there is some sort of async api. + * + * See #6527, enterprise#2480 + */ + static void adjustLastJobTimeout(AbstractNetworkJob *job, quint64 fileSize); + // Bases headers that need to be sent with every chunk QMap headers(); }; diff --git a/src/libsync/propagateuploadng.cpp b/src/libsync/propagateuploadng.cpp index a76f3ac387a..1fd9f27f97e 100644 --- a/src/libsync/propagateuploadng.cpp +++ b/src/libsync/propagateuploadng.cpp @@ -303,6 +303,7 @@ void PropagateUploadFileNG::startNextChunk() connect(job, &MoveJob::finishedSignal, this, &PropagateUploadFileNG::slotMoveJobFinished); connect(job, &QObject::destroyed, this, &PropagateUploadFileCommon::slotJobDestroyed); propagator()->_activeJobList.append(this); + adjustLastJobTimeout(job, fileSize); job->start(); return; } diff --git a/src/libsync/propagateuploadv1.cpp b/src/libsync/propagateuploadv1.cpp index f8069dec004..2e5db6395f9 100644 --- a/src/libsync/propagateuploadv1.cpp +++ b/src/libsync/propagateuploadv1.cpp @@ -144,6 +144,8 @@ void PropagateUploadFileV1::startNextChunk() connect(job, &PUTFileJob::uploadProgress, this, &PropagateUploadFileV1::slotUploadProgress); connect(job, &PUTFileJob::uploadProgress, device, &UploadDevice::slotJobUploadProgress); connect(job, &QObject::destroyed, this, &PropagateUploadFileCommon::slotJobDestroyed); + if (isFinalChunk) + adjustLastJobTimeout(job, fileSize); job->start(); propagator()->_activeJobList.append(this); _currentChunk++;