From 5d24599546713428c6494a09ffdeab26f4bb5fc1 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 5 Aug 2013 19:53:58 +0200 Subject: [PATCH] Fetch the etag of the folder to see if it has changed before syncing Notice that this does not work for the toplevel directory yet, as owncloud does not change the etag of the root folder --- src/mirall/folder.cpp | 16 ++++++++-- src/mirall/folder.h | 2 ++ src/mirall/owncloudinfo.cpp | 58 +++++++++++++++++++++++++++++++++++++ src/mirall/owncloudinfo.h | 21 ++++++++++++++ 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/src/mirall/folder.cpp b/src/mirall/folder.cpp index c7dadd2fe..3e693f25b 100644 --- a/src/mirall/folder.cpp +++ b/src/mirall/folder.cpp @@ -76,12 +76,10 @@ Folder::Folder(const QString &alias, const QString &path, const QString& secondP // check if the local path exists checkLocalPath(); - _pollTimer.setSingleShot(true); int polltime = cfg.remotePollInterval(); qDebug() << "setting remote poll timer interval to" << polltime << "msec"; _pollTimer.setInterval( polltime ); QObject::connect(&_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout())); - _pollTimer.setSingleShot(true); _pollTimer.start(); } @@ -239,9 +237,21 @@ void Folder::slotPollTimerTimeout() { qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now"; _watcher->clearPendingEvents(); - evaluateSync(QStringList()); + + QObject::connect(new RequestEtagJob(secondPath(), this), SIGNAL(etagRetreived(QString)), + this, SLOT(etagRetreived(QString))); } +void Folder::etagRetreived(const QString& etag) +{ + qDebug() << "* Compare etag " << etag << " with previous etag " << _lastEtag; + if (_lastEtag != etag) { + _lastEtag = etag; + evaluateSync(QStringList()); + } +} + + void Folder::slotChanged(const QStringList &pathList) { qDebug() << "** Changed was notified on " << pathList; diff --git a/src/mirall/folder.h b/src/mirall/folder.h index 1ac4fefac..3c484e484 100644 --- a/src/mirall/folder.h +++ b/src/mirall/folder.h @@ -172,6 +172,7 @@ private slots: void slotTransmissionProgress(const Progress::Info& progress); void slotPollTimerTimeout(); + void etagRetreived(const QString &); /** * Triggered by a file system watcher on the local sync dir @@ -212,6 +213,7 @@ protected: bool _wipeDb; Progress::Kind _progressKind; QTimer _pollTimer; + QString _lastEtag; CSYNC *_csync_ctx; diff --git a/src/mirall/owncloudinfo.cpp b/src/mirall/owncloudinfo.cpp index 296598e83..c2464929c 100644 --- a/src/mirall/owncloudinfo.cpp +++ b/src/mirall/owncloudinfo.cpp @@ -553,4 +553,62 @@ QString ownCloudInfo::webdavUrl(const QString &connection) return url; } +RequestEtagJob::RequestEtagJob(const QString& dir, QObject* parent) + : QObject(parent) +{ + QNetworkRequest req; + req.setUrl( QUrl( ownCloudInfo::instance()->webdavUrl(ownCloudInfo::instance()->_connection) + dir ) ); + req.setRawHeader("Depth", "0"); + QByteArray xml("\n" + "\n" + " \n" + " " + " \n" + "\n"); + QBuffer *buf = new QBuffer; + buf->setData(xml); + buf->open(QIODevice::ReadOnly); + _reply = ownCloudInfo::instance()->davRequest("PROPFIND", req, buf); + buf->setParent(_reply); + + if( _reply->error() != QNetworkReply::NoError ) { + qDebug() << "getting etag: request network error: " << _reply->errorString(); + } + + connect( _reply, SIGNAL( finished()), SLOT(slotFinished()) ); + connect( _reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(slotError())); +} + +void RequestEtagJob::slotFinished() +{ + bool ok = false; + if (_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) { + // Parse DAV response + QXmlStreamReader reader(_reply); + reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:")); + QString etag; + while (!reader.atEnd()) { + QXmlStreamReader::TokenType type = reader.readNext(); + if (type == QXmlStreamReader::StartElement && + reader.namespaceUri() == QLatin1String("DAV:")) { + QString name = reader.name().toString(); + if (name == QLatin1String("getetag")) { + etag = reader.readElementText(); + } + } + } + emit etagRetreived(etag); + } + _reply->deleteLater(); + deleteLater(); +} + +void RequestEtagJob::slotError() +{ + qDebug() << "RequestEtagJob Error: " << _reply->errorString(); + _reply->deleteLater(); + deleteLater(); +} + } // ns Mirall diff --git a/src/mirall/owncloudinfo.h b/src/mirall/owncloudinfo.h index be11e7177..6e0387231 100644 --- a/src/mirall/owncloudinfo.h +++ b/src/mirall/owncloudinfo.h @@ -157,6 +157,27 @@ private: qint64 _lastQuotaUsedBytes; qint64 _lastQuotaTotalBytes; QString _lastEtag; + + friend class RequestEtagJob; +}; + + + + +class RequestEtagJob : public QObject { + Q_OBJECT + + QNetworkReply *_reply; + +public: + explicit RequestEtagJob(const QString &dir , QObject* parent = 0); + +private slots: + void slotFinished(); + void slotError(); + +signals: + void etagRetreived(const QString &etag); }; } // ns Mirall