[Pkg-owncloud-commits] [owncloud-client] 36/484: Propagator: Download disk space checks #2939

Sandro Knauß hefee-guest at moszumanska.debian.org
Wed Dec 16 00:37:08 UTC 2015


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository owncloud-client.

commit 36e8e9ebf5f4703e943540ab7221263a0e245d78
Author: Christian Kamm <mail at ckamm.de>
Date:   Thu Oct 1 11:39:09 2015 +0200

    Propagator: Download disk space checks #2939
    
    * There's a critical 50 MB threshold under which syncs abort
      (OWNCLOUD_CRITICAL_FREE_SPACE)
    * The sync client always keeps 250 MB free
      (OWNCLOUD_FREE_SPACE)
---
 src/libsync/owncloudpropagator.cpp | 53 ++++++++++++++++++++++++++++++++++++++
 src/libsync/owncloudpropagator.h   | 31 ++++++++++++++++++++++
 src/libsync/propagatedownload.cpp  | 50 +++++++++++++++++++++++++----------
 src/libsync/propagatedownload.h    |  5 +++-
 src/libsync/syncengine.cpp         | 14 +---------
 5 files changed, 125 insertions(+), 28 deletions(-)

diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp
index c89cdb5..c101862 100644
--- a/src/libsync/owncloudpropagator.cpp
+++ b/src/libsync/owncloudpropagator.cpp
@@ -45,6 +45,32 @@
 
 namespace OCC {
 
+qint64 criticalFreeSpaceLimit()
+{
+    qint64 value = 50 * 1000 * 1000LL;
+
+    static bool hasEnv = false;
+    static qint64 env = qgetenv("OWNCLOUD_CRITICAL_FREE_SPACE").toLongLong(&hasEnv);
+    if (hasEnv) {
+        value = env;
+    }
+
+    return qBound(0LL, value, freeSpaceLimit());
+}
+
+qint64 freeSpaceLimit()
+{
+    qint64 value = 250 * 1000 * 1000LL;
+
+    static bool hasEnv = false;
+    static qint64 env = qgetenv("OWNCLOUD_FREE_SPACE").toLongLong(&hasEnv);
+    if (hasEnv) {
+        value = env;
+    }
+
+    return value;
+}
+
 OwncloudPropagator::~OwncloudPropagator()
 {}
 
@@ -532,6 +558,24 @@ AccountPtr OwncloudPropagator::account() const
     return _account;
 }
 
+OwncloudPropagator::DiskSpaceResult OwncloudPropagator::diskSpaceCheck() const
+{
+    const qint64 freeBytes = Utility::freeDiskSpace(_localDir);
+    if (freeBytes < 0) {
+        return DiskSpaceOk;
+    }
+
+    if (freeBytes < criticalFreeSpaceLimit()) {
+        return DiskSpaceCritical;
+    }
+
+    if (freeBytes - _rootJob->committedDiskSpace() < freeSpaceLimit()) {
+        return DiskSpaceFailure;
+    }
+
+    return DiskSpaceOk;
+}
+
 // ================================================================================
 
 PropagatorJob::JobParallelism PropagateDirectory::parallelism()
@@ -660,6 +704,15 @@ void PropagateDirectory::finalize()
     emit finished(_hasError == SyncFileItem::NoStatus ? SyncFileItem::Success : _hasError);
 }
 
+qint64 PropagateDirectory::committedDiskSpace() const
+{
+    qint64 needed = 0;
+    foreach (PropagatorJob* job, _subJobs) {
+        needed += job->committedDiskSpace();
+    }
+    return needed;
+}
+
 CleanupPollsJob::~CleanupPollsJob()
 {}
 
diff --git a/src/libsync/owncloudpropagator.h b/src/libsync/owncloudpropagator.h
index ca22aab..e4f6dca 100644
--- a/src/libsync/owncloudpropagator.h
+++ b/src/libsync/owncloudpropagator.h
@@ -37,6 +37,17 @@ typedef struct ne_prop_result_set_s ne_prop_result_set;
 
 namespace OCC {
 
+/** Free disk space threshold below which syncs will abort and not even start.
+ */
+qint64 criticalFreeSpaceLimit();
+
+/** The client will not intentionally reduce the available free disk space below
+ *  this limit.
+ *
+ * Uploads will still run and downloads that are small enough will continue too.
+ */
+qint64 freeSpaceLimit();
+
 class SyncJournalDb;
 class OwncloudPropagator;
 
@@ -78,6 +89,13 @@ public:
 
     virtual JobParallelism parallelism() { return FullParallelism; }
 
+    /** The space that the running jobs need to complete but don't actually use yet.
+     *
+     * Note that this does *not* include the disk space that's already
+     * in use by running jobs for things like a download-in-progress.
+     */
+    virtual qint64 committedDiskSpace() const { return 0; }
+
 public slots:
     virtual void abort() {}
 
@@ -203,6 +221,8 @@ public:
 
     void finalize();
 
+    qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
+
 private slots:
     bool possiblyRunNextJob(PropagatorJob *next) {
         if (next->_state == NotYetStarted) {
@@ -321,6 +341,17 @@ public:
 
     AccountPtr account() const;
 
+    enum DiskSpaceResult
+    {
+        DiskSpaceOk,
+        DiskSpaceFailure,
+        DiskSpaceCritical
+    };
+
+    /** Checks whether there's enough disk space available to complete
+     *  all jobs that are currently running.
+     */
+    DiskSpaceResult diskSpaceCheck() const;
 
 private slots:
 
diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp
index e1e4ed4..2730ebf 100644
--- a/src/libsync/propagatedownload.cpp
+++ b/src/libsync/propagatedownload.cpp
@@ -346,6 +346,30 @@ void PropagateDownloadFileQNAM::start()
 
     FileSystem::setFileHidden(_tmpFile.fileName(), true);
 
+    _resumeStart = _tmpFile.size();
+    if (_resumeStart > 0) {
+        if (_resumeStart == _item->_size) {
+            qDebug() << "File is already complete, no need to download";
+            _tmpFile.close();
+            downloadFinished();
+            return;
+        }
+    }
+
+    // If there's not enough space to fully download this file, stop.
+    const auto diskSpaceResult = _propagator->diskSpaceCheck();
+    if (diskSpaceResult == OwncloudPropagator::DiskSpaceFailure) {
+        done(SyncFileItem::NormalError,
+             tr("The download would reduce free disk space below %1").arg(
+                 Utility::octetsToString(freeSpaceLimit())));
+        return;
+    } else if (diskSpaceResult == OwncloudPropagator::DiskSpaceCritical) {
+        done(SyncFileItem::FatalError,
+             tr("Free space on disk is less than %1").arg(
+                 Utility::octetsToString(criticalFreeSpaceLimit())));
+        return;
+    }
+
     {
         SyncJournalDb::DownloadInfo pi;
         pi._etag = _item->_etag;
@@ -355,24 +379,13 @@ void PropagateDownloadFileQNAM::start()
         _propagator->_journal->commit("download file start");
     }
 
-
     QMap<QByteArray, QByteArray> headers;
 
-    quint64 startSize = _tmpFile.size();
-    if (startSize > 0) {
-        if (startSize == _item->_size) {
-            qDebug() << "File is already complete, no need to download";
-            _tmpFile.close();
-            downloadFinished();
-            return;
-        }
-    }
-
     if (_item->_directDownloadUrl.isEmpty()) {
         // Normal job, download from oC instance
         _job = new GETFileJob(_propagator->account(),
                             _propagator->_remoteFolder + _item->_file,
-                            &_tmpFile, headers, expectedEtagForResume, startSize);
+                            &_tmpFile, headers, expectedEtagForResume, _resumeStart);
     } else {
         // We were provided a direct URL, use that one
         qDebug() << Q_FUNC_INFO << "directDownloadUrl given for " << _item->_file << _item->_directDownloadUrl;
@@ -384,7 +397,7 @@ void PropagateDownloadFileQNAM::start()
         QUrl url = QUrl::fromUserInput(_item->_directDownloadUrl);
         _job = new GETFileJob(_propagator->account(),
                               url,
-                              &_tmpFile, headers, expectedEtagForResume, startSize);
+                              &_tmpFile, headers, expectedEtagForResume, _resumeStart);
     }
     _job->setBandwidthManager(&_propagator->_bandwidthManager);
     connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotGetFinished()));
@@ -393,6 +406,14 @@ void PropagateDownloadFileQNAM::start()
     _job->start();
 }
 
+qint64 PropagateDownloadFileQNAM::committedDiskSpace() const
+{
+    if (_state == Running) {
+        return qBound(0ULL, _item->_size - _resumeStart - _downloadProgress, _item->_size);
+    }
+    return 0;
+}
+
 const char owncloudCustomSoftErrorStringC[] = "owncloud-custom-soft-error-string";
 void PropagateDownloadFileQNAM::slotGetFinished()
 {
@@ -684,7 +705,8 @@ void PropagateDownloadFileQNAM::downloadFinished()
 void PropagateDownloadFileQNAM::slotDownloadProgress(qint64 received, qint64)
 {
     if (!_job) return;
-    emit progress(*_item, received + _job->resumeStart());
+    _downloadProgress = received;
+    emit progress(*_item, _resumeStart + received);
 }
 
 
diff --git a/src/libsync/propagatedownload.h b/src/libsync/propagatedownload.h
index 85ea82d..e67b8d0 100644
--- a/src/libsync/propagatedownload.h
+++ b/src/libsync/propagatedownload.h
@@ -110,8 +110,9 @@ class PropagateDownloadFileQNAM : public PropagateItemJob {
     Q_OBJECT
 public:
     PropagateDownloadFileQNAM(OwncloudPropagator* propagator,const SyncFileItemPtr& item)
-        : PropagateItemJob(propagator, item) {}
+        : PropagateItemJob(propagator, item), _resumeStart(0), _downloadProgress(0) {}
     void start() Q_DECL_OVERRIDE;
+    qint64 committedDiskSpace() const Q_DECL_OVERRIDE;
 
 private slots:
     void slotGetFinished();
@@ -121,6 +122,8 @@ private slots:
     void slotChecksumFail( const QString& errMsg );
 
 private:
+    quint64 _resumeStart;
+    qint64 _downloadProgress;
     QPointer<GETFileJob> _job;
     QFile _tmpFile;
 };
diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp
index e4bb8ce..3d12eae 100644
--- a/src/libsync/syncengine.cpp
+++ b/src/libsync/syncengine.cpp
@@ -54,18 +54,6 @@ extern "C" const char *csync_instruction_str(enum csync_instructions_e instr);
 
 namespace OCC {
 
-/* The minimum amount of space required to start a sync run */
-static qint64 minFreeSpace()
-{
-    static bool ok = false;
-    static qint64 freeSpace = qgetenv("OWNCLOUD_MIN_FREE_SPACE").toLongLong(&ok);
-    if (ok) {
-        return freeSpace;
-    }
-
-    return 250 * 1000 * 1000LL;
-}
-
 bool SyncEngine::_syncRunning = false;
 
 SyncEngine::SyncEngine(AccountPtr account, CSYNC *ctx, const QString& localPath,
@@ -612,7 +600,7 @@ void SyncEngine::startSync()
     }
 
     // Check free size on disk first.
-    const qint64 minFree = minFreeSpace();
+    const qint64 minFree = criticalFreeSpaceLimit();
     const qint64 freeBytes = Utility::freeDiskSpace(_localPath);
     if (freeBytes >= 0) {
         qDebug() << "There are" << freeBytes << "bytes available at" << _localPath

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git



More information about the Pkg-owncloud-commits mailing list