2014-08-11 19:47:16 +04:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Olivier Goffart <ogoffart@woboq.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <QObject>
|
2014-08-18 16:44:43 +04:00
|
|
|
#include <QElapsedTimer>
|
2014-08-11 20:41:42 +04:00
|
|
|
#include <QStringList>
|
2014-08-11 19:47:16 +04:00
|
|
|
#include <csync.h>
|
2014-12-02 14:25:51 +03:00
|
|
|
#include <QMap>
|
|
|
|
#include "networkjobs.h"
|
|
|
|
#include <QMutex>
|
|
|
|
#include <QWaitCondition>
|
2017-09-05 17:12:32 +03:00
|
|
|
#include <deque>
|
2017-12-05 18:54:02 +03:00
|
|
|
#include "syncoptions.h"
|
2014-08-18 16:45:48 +04:00
|
|
|
|
2014-11-10 00:34:07 +03:00
|
|
|
namespace OCC {
|
2014-08-18 16:45:48 +04:00
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
class Account;
|
|
|
|
|
2014-08-11 19:47:16 +04:00
|
|
|
/**
|
2015-10-05 06:20:09 +03:00
|
|
|
* The Discovery Phase was once called "update" phase in csync terms.
|
|
|
|
* Its goal is to look at the files in one of the remote and check compared to the db
|
2014-08-11 19:47:16 +04:00
|
|
|
* if the files are new, or changed.
|
|
|
|
*/
|
|
|
|
|
2015-01-20 20:49:49 +03:00
|
|
|
struct DiscoveryDirectoryResult
|
|
|
|
{
|
2015-01-22 16:25:24 +03:00
|
|
|
QString path;
|
2014-12-02 14:25:51 +03:00
|
|
|
QString msg;
|
2020-05-28 17:59:24 +03:00
|
|
|
int code = EIO;
|
2017-09-05 17:12:32 +03:00
|
|
|
std::deque<std::unique_ptr<csync_file_stat_t>> list;
|
2015-01-20 20:49:49 +03:00
|
|
|
};
|
2014-12-02 14:25:51 +03:00
|
|
|
|
2015-06-29 19:56:09 +03:00
|
|
|
/**
|
|
|
|
* @brief The DiscoverySingleDirectoryJob class
|
2015-06-26 18:07:47 +03:00
|
|
|
*
|
|
|
|
* Run in the main thread, reporting to the DiscoveryJobMainThread object
|
|
|
|
*
|
2015-06-29 19:56:09 +03:00
|
|
|
* @ingroup libsync
|
2015-06-26 18:07:47 +03:00
|
|
|
*/
|
2014-12-02 14:25:51 +03:00
|
|
|
class DiscoverySingleDirectoryJob : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2018-11-12 20:46:39 +03:00
|
|
|
explicit DiscoverySingleDirectoryJob(const AccountPtr &account, const QString &path, QObject *parent = nullptr);
|
2016-08-02 11:30:49 +03:00
|
|
|
// Specify thgat this is the root and we need to check the data-fingerprint
|
|
|
|
void setIsRootPath() { _isRootPath = true; }
|
2014-12-02 14:25:51 +03:00
|
|
|
void start();
|
|
|
|
void abort();
|
2017-09-05 17:12:32 +03:00
|
|
|
std::deque<std::unique_ptr<csync_file_stat_t>> &&takeResults() { return std::move(_results); }
|
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
// This is not actually a network job, it is just a job
|
|
|
|
signals:
|
2017-09-19 11:53:51 +03:00
|
|
|
void firstDirectoryPermissions(RemotePermissions);
|
2015-03-05 19:49:12 +03:00
|
|
|
void etagConcatenation(const QString &);
|
2015-10-16 12:52:27 +03:00
|
|
|
void etag(const QString &);
|
2017-09-05 17:12:32 +03:00
|
|
|
void finishedWithResult();
|
2015-10-29 17:01:29 +03:00
|
|
|
void finishedWithError(int csyncErrnoCode, const QString &msg);
|
2014-12-02 14:25:51 +03:00
|
|
|
private slots:
|
2015-10-29 17:01:29 +03:00
|
|
|
void directoryListingIteratedSlot(QString, const QMap<QString, QString> &);
|
2014-12-02 14:25:51 +03:00
|
|
|
void lsJobFinishedWithoutErrorSlot();
|
|
|
|
void lsJobFinishedWithErrorSlot(QNetworkReply *);
|
2017-05-17 11:55:42 +03:00
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
private:
|
2017-09-05 17:12:32 +03:00
|
|
|
std::deque<std::unique_ptr<csync_file_stat_t>> _results;
|
2014-12-02 14:25:51 +03:00
|
|
|
QString _subPath;
|
2015-03-05 19:49:12 +03:00
|
|
|
QString _etagConcatenation;
|
2015-10-16 12:52:27 +03:00
|
|
|
QString _firstEtag;
|
2014-12-02 14:25:51 +03:00
|
|
|
AccountPtr _account;
|
2016-08-02 11:30:49 +03:00
|
|
|
// The first result is for the directory itself and need to be ignored.
|
|
|
|
// This flag is true if it was already ignored.
|
2014-12-02 14:25:51 +03:00
|
|
|
bool _ignoredFirst;
|
2016-08-02 11:30:49 +03:00
|
|
|
// Set to true if this is the root path and we need to check the data-fingerprint
|
|
|
|
bool _isRootPath;
|
2017-01-24 15:25:03 +03:00
|
|
|
// If this directory is an external storage (The first item has 'M' in its permission)
|
2017-02-07 21:22:04 +03:00
|
|
|
bool _isExternalStorage;
|
2018-02-28 15:20:39 +03:00
|
|
|
// If set, the discovery will finish with an error
|
|
|
|
QString _error;
|
2014-12-02 14:25:51 +03:00
|
|
|
QPointer<LsColJob> _lsColJob;
|
2016-08-02 11:30:49 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
QByteArray _dataFingerprint;
|
2014-12-02 14:25:51 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// Lives in main thread. Deleted by the SyncEngine
|
|
|
|
class DiscoveryJob;
|
|
|
|
class DiscoveryMainThread : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
QPointer<DiscoveryJob> _discoveryJob;
|
|
|
|
QPointer<DiscoverySingleDirectoryJob> _singleDirJob;
|
2015-05-21 15:50:30 +03:00
|
|
|
QString _pathPrefix; // remote path
|
2014-12-02 14:25:51 +03:00
|
|
|
AccountPtr _account;
|
2015-01-20 20:49:49 +03:00
|
|
|
DiscoveryDirectoryResult *_currentDiscoveryDirectoryResult;
|
2015-05-21 15:50:30 +03:00
|
|
|
qint64 *_currentGetSizeResult;
|
2016-08-02 11:30:49 +03:00
|
|
|
bool _firstFolderProcessed;
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
public:
|
2015-06-12 15:43:18 +03:00
|
|
|
DiscoveryMainThread(AccountPtr account)
|
|
|
|
: QObject()
|
|
|
|
, _account(account)
|
2018-11-12 20:46:39 +03:00
|
|
|
, _currentDiscoveryDirectoryResult(nullptr)
|
|
|
|
, _currentGetSizeResult(nullptr)
|
2016-08-02 11:30:49 +03:00
|
|
|
, _firstFolderProcessed(false)
|
2015-06-12 15:43:18 +03:00
|
|
|
{
|
|
|
|
}
|
2014-12-02 14:25:51 +03:00
|
|
|
void abort();
|
|
|
|
|
2016-08-02 11:30:49 +03:00
|
|
|
QByteArray _dataFingerprint;
|
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
public slots:
|
|
|
|
// From DiscoveryJob:
|
2015-10-29 17:01:29 +03:00
|
|
|
void doOpendirSlot(const QString &url, DiscoveryDirectoryResult *);
|
2015-05-21 15:50:30 +03:00
|
|
|
void doGetSizeSlot(const QString &path, qint64 *result);
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
// From Job:
|
2017-09-05 17:12:32 +03:00
|
|
|
void singleDirectoryJobResultSlot();
|
2015-10-29 17:01:29 +03:00
|
|
|
void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, const QString &msg);
|
2017-09-19 11:53:51 +03:00
|
|
|
void singleDirectoryJobFirstDirectoryPermissionsSlot(RemotePermissions);
|
2015-05-21 15:50:30 +03:00
|
|
|
|
|
|
|
void slotGetSizeFinishedWithError();
|
|
|
|
void slotGetSizeResult(const QVariantMap &);
|
2015-01-23 17:30:00 +03:00
|
|
|
signals:
|
2015-10-16 12:52:27 +03:00
|
|
|
void etag(const QString &);
|
|
|
|
void etagConcatenation(const QString &);
|
2017-05-17 11:55:42 +03:00
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
public:
|
2015-01-20 20:49:49 +03:00
|
|
|
void setupHooks(DiscoveryJob *discoveryJob, const QString &pathPrefix);
|
2014-12-02 14:25:51 +03:00
|
|
|
};
|
|
|
|
|
2015-06-29 19:56:09 +03:00
|
|
|
/**
|
|
|
|
* @brief The DiscoveryJob class
|
2015-06-26 18:07:47 +03:00
|
|
|
*
|
|
|
|
* Lives in the other thread, deletes itself in !start()
|
|
|
|
*
|
2015-06-29 19:56:09 +03:00
|
|
|
* @ingroup libsync
|
2015-06-26 18:07:47 +03:00
|
|
|
*/
|
2014-08-11 19:47:16 +04:00
|
|
|
class DiscoveryJob : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
2014-12-02 14:25:51 +03:00
|
|
|
friend class DiscoveryMainThread;
|
2015-02-24 12:58:51 +03:00
|
|
|
CSYNC *_csync_ctx;
|
|
|
|
QElapsedTimer _lastUpdateProgressCallbackCall;
|
2014-08-11 20:41:42 +04:00
|
|
|
|
|
|
|
/**
|
2015-05-21 15:50:30 +03:00
|
|
|
* return true if the given path should be ignored,
|
|
|
|
* false if the path should be synced
|
2014-08-11 20:41:42 +04:00
|
|
|
*/
|
2017-08-23 20:16:12 +03:00
|
|
|
bool isInSelectiveSyncBlackList(const QByteArray &path) const;
|
|
|
|
static int isInSelectiveSyncBlackListCallback(void *, const QByteArray &);
|
2017-09-19 11:53:51 +03:00
|
|
|
bool checkSelectiveSyncNewFolder(const QString &path, RemotePermissions rp);
|
|
|
|
static int checkSelectiveSyncNewFolderCallback(void *data, const QByteArray &path, RemotePermissions rm);
|
2014-08-11 20:41:42 +04:00
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
// Just for progress
|
2014-08-18 16:44:43 +04:00
|
|
|
static void update_job_update_callback(bool local,
|
|
|
|
const char *dirname,
|
|
|
|
void *userdata);
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
// For using QNAM to get the directory listings
|
|
|
|
static csync_vio_handle_t *remote_vio_opendir_hook(const char *url,
|
|
|
|
void *userdata);
|
2017-09-05 17:12:32 +03:00
|
|
|
static std::unique_ptr<csync_file_stat_t> remote_vio_readdir_hook(csync_vio_handle_t *dhandle,
|
2014-12-02 14:25:51 +03:00
|
|
|
void *userdata);
|
|
|
|
static void remote_vio_closedir_hook(csync_vio_handle_t *dhandle,
|
|
|
|
void *userdata);
|
|
|
|
QMutex _vioMutex;
|
|
|
|
QWaitCondition _vioWaitCondition;
|
|
|
|
|
|
|
|
|
2014-08-11 19:47:16 +04:00
|
|
|
public:
|
2018-11-12 20:46:39 +03:00
|
|
|
explicit DiscoveryJob(CSYNC *ctx, QObject *parent = nullptr)
|
2017-01-24 12:16:10 +03:00
|
|
|
: QObject(parent)
|
|
|
|
, _csync_ctx(ctx)
|
|
|
|
{
|
2014-08-11 19:47:16 +04:00
|
|
|
}
|
2014-08-15 14:29:10 +04:00
|
|
|
QStringList _selectiveSyncBlackList;
|
2015-05-21 15:50:30 +03:00
|
|
|
QStringList _selectiveSyncWhiteList;
|
2017-01-24 12:16:10 +03:00
|
|
|
SyncOptions _syncOptions;
|
2014-08-11 20:41:42 +04:00
|
|
|
Q_INVOKABLE void start();
|
2014-08-11 19:47:16 +04:00
|
|
|
signals:
|
|
|
|
void finished(int result);
|
2014-08-18 16:44:43 +04:00
|
|
|
void folderDiscovered(bool local, QString folderUrl);
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
// After the discovery job has been woken up again (_vioWaitCondition)
|
|
|
|
void doOpendirSignal(QString url, DiscoveryDirectoryResult *);
|
2015-05-21 15:50:30 +03:00
|
|
|
void doGetSizeSignal(const QString &path, qint64 *result);
|
|
|
|
|
2015-07-27 10:54:20 +03:00
|
|
|
// A new folder was discovered and was not synced because of the confirmation feature
|
2017-01-26 11:03:01 +03:00
|
|
|
void newBigFolder(const QString &folder, bool isExternal);
|
2014-08-11 19:47:16 +04:00
|
|
|
};
|
2014-08-18 16:45:48 +04:00
|
|
|
}
|