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>
|
|
|
|
#include <QLinkedList>
|
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
|
|
|
/**
|
|
|
|
* The Discovery Phase was once called "update" phase in csync therms.
|
|
|
|
* Its goal is to look at the files in one of the remote and check comared to the db
|
|
|
|
* 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;
|
|
|
|
int code;
|
|
|
|
QLinkedList<csync_vio_file_stat_t*>::iterator iterator;
|
|
|
|
QLinkedList<csync_vio_file_stat_t *> list;
|
2015-01-20 20:49:49 +03:00
|
|
|
};
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
// Run in the main thread, reporting to the DiscoveryJobMainThread object
|
|
|
|
class DiscoverySingleDirectoryJob : public QObject {
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit DiscoverySingleDirectoryJob(AccountPtr account, const QString &path, QObject *parent = 0);
|
|
|
|
void start();
|
|
|
|
void abort();
|
|
|
|
// This is not actually a network job, it is just a job
|
|
|
|
signals:
|
2015-01-23 17:30:00 +03:00
|
|
|
void firstDirectoryPermissions(const QString &);
|
|
|
|
void firstDirectoryEtag(const QString &);
|
2014-12-02 14:25:51 +03:00
|
|
|
void finishedWithResult(QLinkedList<csync_vio_file_stat_t*>);
|
2015-01-23 17:37:36 +03:00
|
|
|
void finishedWithError(int csyncErrnoCode, QString msg);
|
2014-12-02 14:25:51 +03:00
|
|
|
private slots:
|
|
|
|
void directoryListingIteratedSlot(QString,QMap<QString,QString>);
|
|
|
|
void lsJobFinishedWithoutErrorSlot();
|
|
|
|
void lsJobFinishedWithErrorSlot(QNetworkReply*);
|
|
|
|
private:
|
|
|
|
QLinkedList<csync_vio_file_stat_t*> _results;
|
|
|
|
QString _subPath;
|
|
|
|
AccountPtr _account;
|
|
|
|
bool _ignoredFirst;
|
|
|
|
QPointer<LsColJob> _lsColJob;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Lives in main thread. Deleted by the SyncEngine
|
|
|
|
class DiscoveryJob;
|
|
|
|
class DiscoveryMainThread : public QObject {
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
// For non-recursive and recursive
|
|
|
|
// If it is not in this map it needs to be requested
|
|
|
|
QMap<QString, QLinkedList<csync_vio_file_stat_t*> > _directoryContents;
|
|
|
|
|
|
|
|
|
|
|
|
QPointer<DiscoveryJob> _discoveryJob;
|
|
|
|
QPointer<DiscoverySingleDirectoryJob> _singleDirJob;
|
|
|
|
QString _pathPrefix;
|
|
|
|
AccountPtr _account;
|
2015-01-20 20:49:49 +03:00
|
|
|
DiscoveryDirectoryResult *_currentDiscoveryDirectoryResult;
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
DiscoveryMainThread(AccountPtr account) : QObject(), _account(account), _currentDiscoveryDirectoryResult(0) {
|
|
|
|
|
|
|
|
}
|
2015-03-02 16:09:01 +03:00
|
|
|
void deleteCacheEntry(QString path) {
|
|
|
|
//qDebug() << path << _directoryContents.value(path).count();
|
|
|
|
foreach (csync_vio_file_stat_t* stat, _directoryContents.value(path)) {
|
|
|
|
csync_vio_file_stat_destroy(stat);
|
|
|
|
}
|
|
|
|
_directoryContents.remove(path);
|
|
|
|
}
|
|
|
|
|
2014-12-02 14:25:51 +03:00
|
|
|
~DiscoveryMainThread() {
|
2015-03-02 16:09:01 +03:00
|
|
|
// Delete the _contents_ of the list-map explicitly:
|
2015-02-11 14:39:14 +03:00
|
|
|
foreach (const QLinkedList<csync_vio_file_stat_t*> & list, _directoryContents) {
|
|
|
|
foreach (csync_vio_file_stat_t* stat, list) {
|
|
|
|
csync_vio_file_stat_destroy(stat);
|
|
|
|
}
|
|
|
|
}
|
2014-12-02 14:25:51 +03:00
|
|
|
}
|
|
|
|
void abort();
|
|
|
|
|
|
|
|
|
|
|
|
public slots:
|
|
|
|
// From DiscoveryJob:
|
|
|
|
void doOpendirSlot(QString url, DiscoveryDirectoryResult* );
|
2015-03-02 16:09:01 +03:00
|
|
|
void doClosedirSlot(QString path);
|
2014-12-02 14:25:51 +03:00
|
|
|
|
|
|
|
// From Job:
|
|
|
|
void singleDirectoryJobResultSlot(QLinkedList<csync_vio_file_stat_t*>);
|
|
|
|
void singleDirectoryJobFinishedWithErrorSlot(int csyncErrnoCode, QString msg);
|
|
|
|
void singleDirectoryJobFirstDirectoryPermissionsSlot(QString);
|
2015-01-23 17:30:00 +03:00
|
|
|
signals:
|
|
|
|
void rootEtag(QString);
|
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
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Lives in the other thread
|
|
|
|
// Deletes itself in start()
|
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;
|
|
|
|
csync_log_callback _log_callback;
|
|
|
|
int _log_level;
|
|
|
|
void* _log_userdata;
|
|
|
|
QElapsedTimer _lastUpdateProgressCallbackCall;
|
2014-08-11 20:41:42 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* return true if the given path should be synced,
|
|
|
|
* false if the path should be ignored
|
|
|
|
*/
|
2014-10-11 18:23:32 +04:00
|
|
|
bool isInSelectiveSyncBlackList(const QString &path) const;
|
|
|
|
static int isInSelectiveSyncBlackListCallBack(void *, const char *);
|
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);
|
|
|
|
static csync_vio_file_stat_t* remote_vio_readdir_hook (csync_vio_handle_t *dhandle,
|
|
|
|
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:
|
|
|
|
explicit DiscoveryJob(CSYNC *ctx, QObject* parent = 0)
|
|
|
|
: QObject(parent), _csync_ctx(ctx) {
|
|
|
|
// We need to forward the log property as csync uses thread local
|
|
|
|
// and updates run in another thread
|
|
|
|
_log_callback = csync_get_log_callback();
|
|
|
|
_log_level = csync_get_log_level();
|
|
|
|
_log_userdata = csync_get_log_userdata();
|
|
|
|
}
|
2014-08-11 20:41:42 +04:00
|
|
|
|
2014-08-15 14:29:10 +04:00
|
|
|
QStringList _selectiveSyncBlackList;
|
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-03-02 16:09:01 +03:00
|
|
|
// to tell the main thread to invalidate its directory data
|
|
|
|
void doClosedirSignal(QString path);
|
2014-08-11 19:47:16 +04:00
|
|
|
};
|
2014-08-18 16:44:43 +04:00
|
|
|
|
2014-08-18 16:45:48 +04:00
|
|
|
}
|