[Pkg-owncloud-commits] [owncloud-client] 109/498: Confirm feature (The sync engine part)

Sandro Knauß hefee-guest at moszumanska.debian.org
Tue Aug 11 14:48:41 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 7bb2834d8b73deb98725babc23b51f9db574bf50
Author: Olivier Goffart <ogoffart at woboq.com>
Date:   Thu May 21 14:50:30 2015 +0200

    Confirm feature (The sync engine part)
---
 csync/src/csync_private.h      |   8 ++-
 csync/src/csync_update.c       |  13 +++-
 src/libsync/discoveryphase.cpp | 151 ++++++++++++++++++++++++++++++++++-------
 src/libsync/discoveryphase.h   |  20 ++++--
 src/libsync/syncengine.cpp     |   6 ++
 src/libsync/syncengine.h       |   3 +
 6 files changed, 166 insertions(+), 35 deletions(-)

diff --git a/csync/src/csync_private.h b/csync/src/csync_private.h
index 8552bf3..d0ac605 100644
--- a/csync/src/csync_private.h
+++ b/csync/src/csync_private.h
@@ -90,6 +90,11 @@ struct csync_s {
       csync_update_callback update_callback;
       void *update_callback_userdata;
 
+      /* hooks for checking the white list (uses the update_callback_userdata) */
+      int (*checkSelectiveSyncBlackListHook)(void*, const char*);
+      int (*checkSelectiveSyncNewShareHook)(void*, const char*);
+
+
       csync_vio_opendir_hook remote_opendir_hook;
       csync_vio_readdir_hook remote_readdir_hook;
       csync_vio_closedir_hook remote_closedir_hook;
@@ -165,9 +170,6 @@ struct csync_s {
 
   struct csync_owncloud_ctx_s *owncloud_context;
 
-  /* hooks for checking the white list */
-  void *checkSelectiveSyncBlackListData;
-  int (*checkSelectiveSyncBlackListHook)(void*, const char*);
 };
 
 
diff --git a/csync/src/csync_update.c b/csync/src/csync_update.c
index 1c89a87..09932d9 100644
--- a/csync/src/csync_update.c
+++ b/csync/src/csync_update.c
@@ -188,8 +188,8 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
     }
   }
 
-  if (ctx->current == REMOTE_REPLICA && ctx->checkSelectiveSyncBlackListHook) {
-      if (ctx->checkSelectiveSyncBlackListHook(ctx->checkSelectiveSyncBlackListData, path)) {
+  if (ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncBlackListHook) {
+      if (ctx->callbacks.checkSelectiveSyncBlackListHook(ctx->callbacks.update_callback_userdata, path)) {
           return 1;
       }
   }
@@ -398,6 +398,15 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
             } else {
                 /* file not found in statedb */
                 st->instruction = CSYNC_INSTRUCTION_NEW;
+
+                if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewShareHook) {
+                    if (strchr(fs->remotePerm, 'S') != NULL) { /* check that the directory is shared */
+                        if (ctx->callbacks.checkSelectiveSyncNewShareHook(ctx->callbacks.update_callback_userdata, path)) {
+                            SAFE_FREE(st);
+                            return 1;
+                        }
+                    }
+                }
                 goto out;
             }
         }
diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp
index 38aa83c..4cd3020 100644
--- a/src/libsync/discoveryphase.cpp
+++ b/src/libsync/discoveryphase.cpp
@@ -22,6 +22,29 @@
 
 namespace OCC {
 
+
+/* Given a sorted list of paths ending with '/', return weather or not the given path is within one of the paths of the list*/
+static bool findPathInList(const QStringList &list, const QString &path)
+{
+    Q_ASSERT(std::is_sorted(list.begin(), list.end()));
+    QString pathSlash = path + QLatin1Char('/');
+
+    // Since the list is sorted, we can do a binary search.
+    // If the path is a prefix of another item or right after in the lexical order.
+    auto it = std::lower_bound(list.begin(), list.end(), pathSlash);
+
+    if (it != list.end() && *it == pathSlash) {
+        return true;
+    }
+
+    if (it == list.begin()) {
+        return false;
+    }
+    --it;
+    Q_ASSERT(it->endsWith(QLatin1Char('/'))); // Folder::setSelectiveSyncBlackList makes sure of that
+    return pathSlash.startsWith(*it);
+}
+
 bool DiscoveryJob::isInSelectiveSyncBlackList(const QString& path) const
 {
     if (_selectiveSyncBlackList.isEmpty()) {
@@ -29,36 +52,54 @@ bool DiscoveryJob::isInSelectiveSyncBlackList(const QString& path) const
         return false;
     }
 
-    // If one of the item in the black list is a prefix of the path, it means this path need not to
-    // be synced.
-    //
-    // We know the list is sorted (for it is done in DiscoveryJob::start)
-    // So we can do a binary search. If the path is a prefix if another item or right after in the lexical order.
+    // Block if it is in the black list
+    return findPathInList(_selectiveSyncBlackList, path);
 
-    QString pathSlash = path + QLatin1Char('/');
+}
 
-    auto it = std::lower_bound(_selectiveSyncBlackList.begin(), _selectiveSyncBlackList.end(), pathSlash);
+int DiscoveryJob::isInSelectiveSyncBlackListCallback(void *data, const char *path)
+{
+    return static_cast<DiscoveryJob*>(data)->isInSelectiveSyncBlackList(QString::fromUtf8(path));
+}
 
-    if (it != _selectiveSyncBlackList.end() && *it == pathSlash) {
-        return true;
+bool DiscoveryJob::checkSelectiveSyncNewShare(const QString& path)
+{
+    // If this path or the parent is in the white list, then we do not block this file
+    if (findPathInList(_selectiveSyncWhiteList, path)) {
+        return false;
     }
 
-	if (it == _selectiveSyncBlackList.begin()) {
-        return false;
+    // Go in the main thread to do a PROPFIND to know the size of this directory
+    qint64 result = -1;
+
+    {
+        QMutexLocker locker(&_vioMutex);
+        emit doGetSizeSignal(path, &result);
+        _vioWaitCondition.wait(&_vioMutex);
     }
-    --it;
-    Q_ASSERT(it->endsWith(QLatin1Char('/'))); // Folder::setSelectiveSyncBlackList makes sure of that
-    if (pathSlash.startsWith(*it)) {
+
+    auto limit = 100*1000*1000L; // 100 MB; (FIXME, make it cnfigurable)
+    if (true || result > limit) {
+        // we tell the UI there is a new folder
+        emit newSharedFolder(path);
         return true;
+    } else {
+        // it is not too big, but it in the white list and do not block
+        auto p = path;
+        if (!p.endsWith(QLatin1Char('/'))) { p += QLatin1Char('/'); }
+        _selectiveSyncWhiteList.insert(std::upper_bound(_selectiveSyncWhiteList.begin(),
+                                                        _selectiveSyncWhiteList.end(), p), p);
+
+        return false;
     }
-    return false;
 }
 
-int DiscoveryJob::isInSelectiveSyncBlackListCallBack(void *data, const char *path)
+int DiscoveryJob::checkSelectiveSyncNewShareCallback(void *data, const char *path)
 {
-    return static_cast<DiscoveryJob*>(data)->isInSelectiveSyncBlackList(QString::fromUtf8(path));
+    return static_cast<DiscoveryJob*>(data)->checkSelectiveSyncNewShare(QString::fromUtf8(path));
 }
 
+
 void DiscoveryJob::update_job_update_callback (bool local,
                                     const char *dirUrl,
                                     void *userdata)
@@ -318,6 +359,9 @@ void DiscoveryMainThread::setupHooks(DiscoveryJob *discoveryJob, const QString &
     connect(discoveryJob, SIGNAL(doOpendirSignal(QString,DiscoveryDirectoryResult*)),
             this, SLOT(doOpendirSlot(QString,DiscoveryDirectoryResult*)),
             Qt::QueuedConnection);
+    connect(discoveryJob, SIGNAL(doGetSizeSignal(QString,qint64*)),
+            this, SLOT(doGetSizeSlot(QString,qint64*)),
+            Qt::QueuedConnection);
 }
 
 // Coming from owncloud_opendir -> DiscoveryJob::vio_opendir_hook -> doOpendirSignal
@@ -397,6 +441,60 @@ void DiscoveryMainThread::singleDirectoryJobFirstDirectoryPermissionsSlot(QStrin
     }
 }
 
+void DiscoveryMainThread::doGetSizeSlot(const QString& path, qint64* result)
+{
+    QString fullPath = _pathPrefix;
+    if (!_pathPrefix.endsWith('/')) {
+        fullPath += '/';
+    }
+    fullPath += path;
+    // remove trailing slash
+    while (fullPath.endsWith('/')) {
+        fullPath.chop(1);
+    }
+
+    _currentGetSizeResult = result;
+
+    // Schedule the DiscoverySingleDirectoryJob
+    auto propfindJob = new PropfindJob(_account, fullPath, this);
+    propfindJob->setProperties(QList<QByteArray>() << "resourcetype" << "quota-used-bytes");
+    QObject::connect(propfindJob, SIGNAL(finishedWithError()),
+                     this, SLOT(slotGetSizeFinishedWithError()));
+    QObject::connect(propfindJob, SIGNAL(result(QVariantMap)),
+                     this, SLOT(slotGetSizeResult(QVariantMap)));
+    propfindJob->start();
+}
+
+void DiscoveryMainThread::slotGetSizeFinishedWithError()
+{
+    if (! _currentGetSizeResult) {
+        return; // possibly aborted
+    }
+
+    qWarning() << "Error getting the size of the directory";
+    // just let let the discovery job continue then
+    _currentGetSizeResult = 0;
+    QMutexLocker locker(&_discoveryJob->_vioMutex);
+    _discoveryJob->_vioWaitCondition.wakeAll();
+
+}
+
+void DiscoveryMainThread::slotGetSizeResult(const QVariantMap &map)
+{
+    if (! _currentGetSizeResult) {
+        return; // possibly aborted
+    }
+
+    *_currentGetSizeResult = map.value(QLatin1String("quota-used-bytes")).toLongLong();
+    qDebug() << "Size of folder:" << *_currentGetSizeResult;
+    _currentGetSizeResult = 0;
+    QMutexLocker locker(&_discoveryJob->_vioMutex);
+    _discoveryJob->_vioWaitCondition.wakeAll();
+}
+
+
+
+
 // called from SyncEngine
 void DiscoveryMainThread::abort() {
     if (_singleDirJob) {
@@ -414,8 +512,11 @@ void DiscoveryMainThread::abort() {
             _discoveryJob->_vioMutex.unlock();
         }
     }
-
-
+    if (_currentGetSizeResult) {
+        _currentGetSizeResult = 0;
+        QMutexLocker locker(&_discoveryJob->_vioMutex);
+        _discoveryJob->_vioWaitCondition.wakeAll();
+    }
 }
 
 csync_vio_handle_t* DiscoveryJob::remote_vio_opendir_hook (const char *url,
@@ -479,11 +580,10 @@ void DiscoveryJob::remote_vio_closedir_hook (csync_vio_handle_t *dhandle,  void
 
 void DiscoveryJob::start() {
     _selectiveSyncBlackList.sort();
-    _csync_ctx->checkSelectiveSyncBlackListHook = isInSelectiveSyncBlackListCallBack;
-    _csync_ctx->checkSelectiveSyncBlackListData = this;
-
-    _csync_ctx->callbacks.update_callback = update_job_update_callback;
     _csync_ctx->callbacks.update_callback_userdata = this;
+    _csync_ctx->callbacks.update_callback = update_job_update_callback;
+    _csync_ctx->callbacks.checkSelectiveSyncBlackListHook = isInSelectiveSyncBlackListCallback;
+    _csync_ctx->callbacks.checkSelectiveSyncNewShareHook = checkSelectiveSyncNewShareCallback;
 
     _csync_ctx->callbacks.remote_opendir_hook = remote_vio_opendir_hook;
     _csync_ctx->callbacks.remote_readdir_hook = remote_vio_readdir_hook;
@@ -496,9 +596,8 @@ void DiscoveryJob::start() {
     _lastUpdateProgressCallbackCall.invalidate();
     int ret = csync_update(_csync_ctx);
 
-    _csync_ctx->checkSelectiveSyncBlackListHook = 0;
-    _csync_ctx->checkSelectiveSyncBlackListData = 0;
-
+    _csync_ctx->callbacks.checkSelectiveSyncNewShareHook = 0;
+    _csync_ctx->callbacks.checkSelectiveSyncBlackListHook = 0;
     _csync_ctx->callbacks.update_callback = 0;
     _csync_ctx->callbacks.update_callback_userdata = 0;
 
diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h
index 43dd644..2f519ae 100644
--- a/src/libsync/discoveryphase.h
+++ b/src/libsync/discoveryphase.h
@@ -99,9 +99,10 @@ class DiscoveryMainThread : public QObject {
 
     QPointer<DiscoveryJob> _discoveryJob;
     QPointer<DiscoverySingleDirectoryJob> _singleDirJob;
-    QString _pathPrefix;
+    QString _pathPrefix; // remote path
     AccountPtr _account;
     DiscoveryDirectoryResult *_currentDiscoveryDirectoryResult;
+    qint64 *_currentGetSizeResult;
 
 public:
     DiscoveryMainThread(AccountPtr account) : QObject(), _account(account), _currentDiscoveryDirectoryResult(0) {
@@ -113,11 +114,15 @@ public:
 public slots:
     // From DiscoveryJob:
     void doOpendirSlot(QString url, DiscoveryDirectoryResult* );
+    void doGetSizeSlot(const QString &path ,qint64 *result);
 
     // From Job:
     void singleDirectoryJobResultSlot(const QList<FileStatPointer> &);
     void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, QString msg);
     void singleDirectoryJobFirstDirectoryPermissionsSlot(QString);
+
+    void slotGetSizeFinishedWithError();
+    void slotGetSizeResult(const QVariantMap&);
 signals:
     void etagConcatenation(QString);
 public:
@@ -137,11 +142,13 @@ class DiscoveryJob : public QObject {
     QElapsedTimer       _lastUpdateProgressCallbackCall;
 
     /**
-     * return true if the given path should be synced,
-     * false if the path should be ignored
+     * return true if the given path should be ignored,
+     * false if the path should be synced
      */
     bool isInSelectiveSyncBlackList(const QString &path) const;
-    static int isInSelectiveSyncBlackListCallBack(void *, const char *);
+    static int isInSelectiveSyncBlackListCallback(void *, const char *);
+    bool checkSelectiveSyncNewShare(const QString &path);
+    static int checkSelectiveSyncNewShareCallback(void*, const char*);
 
     // Just for progress
     static void update_job_update_callback (bool local,
@@ -170,6 +177,7 @@ public:
     }
 
     QStringList _selectiveSyncBlackList;
+    QStringList _selectiveSyncWhiteList;
     Q_INVOKABLE void start();
 signals:
     void finished(int result);
@@ -177,6 +185,10 @@ signals:
 
     // After the discovery job has been woken up again (_vioWaitCondition)
     void doOpendirSignal(QString url, DiscoveryDirectoryResult*);
+    void doGetSizeSignal(const QString &path, qint64 *result);
+
+    // A new shared folder was discovered and was not synced because of the confirmation feature
+    void newSharedFolder(const QString &folder);
 };
 
 }
diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp
index 1457281..1d294c3 100644
--- a/src/libsync/syncengine.cpp
+++ b/src/libsync/syncengine.cpp
@@ -638,11 +638,17 @@ void SyncEngine::startSync()
 
     DiscoveryJob *discoveryJob = new DiscoveryJob(_csync_ctx);
     discoveryJob->_selectiveSyncBlackList = selectiveSyncBlackList;
+    discoveryJob->_selectiveSyncWhiteList =
+        _journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList);
     discoveryJob->moveToThread(&_thread);
     connect(discoveryJob, SIGNAL(finished(int)), this, SLOT(slotDiscoveryJobFinished(int)));
     connect(discoveryJob, SIGNAL(folderDiscovered(bool,QString)),
             this, SIGNAL(folderDiscovered(bool,QString)));
 
+    connect(discoveryJob, SIGNAL(newSharedFolder(QString)),
+            this, SIGNAL(newSharedFolder(QString)));
+
+
     // This is used for the DiscoveryJob to be able to request the main thread/
     // to read in directory contents.
     qDebug() << Q_FUNC_INFO << _remotePath << _remoteUrl;
diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h
index a60781e..6fdce52 100644
--- a/src/libsync/syncengine.h
+++ b/src/libsync/syncengine.h
@@ -107,6 +107,9 @@ signals:
 
     void aboutToRemoveAllFiles(SyncFileItem::Direction direction, bool *cancel);
 
+    // A new shared folder was discovered and was not synced because of the confirmation feature
+    void newSharedFolder(const QString &folder);
+
 private slots:
     void slotRootEtagReceived(QString);
     void slotJobCompleted(const SyncFileItem& item);

-- 
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