[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