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
This commit is contained in:
Olivier Goffart 2013-08-05 19:53:58 +02:00
parent 07d9d3770b
commit 5d24599546
4 changed files with 94 additions and 3 deletions

View file

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

View file

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

View file

@ -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("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
" <d:prop>\n"
" <d:getetag/>"
" </d:prop>\n"
"</d:propfind>\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

View file

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