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 // check if the local path exists
checkLocalPath(); checkLocalPath();
_pollTimer.setSingleShot(true);
int polltime = cfg.remotePollInterval(); int polltime = cfg.remotePollInterval();
qDebug() << "setting remote poll timer interval to" << polltime << "msec"; qDebug() << "setting remote poll timer interval to" << polltime << "msec";
_pollTimer.setInterval( polltime ); _pollTimer.setInterval( polltime );
QObject::connect(&_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout())); QObject::connect(&_pollTimer, SIGNAL(timeout()), this, SLOT(slotPollTimerTimeout()));
_pollTimer.setSingleShot(true);
_pollTimer.start(); _pollTimer.start();
} }
@ -239,9 +237,21 @@ void Folder::slotPollTimerTimeout()
{ {
qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now"; qDebug() << "* Polling" << alias() << "for changes. Ignoring all pending events until now";
_watcher->clearPendingEvents(); _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) void Folder::slotChanged(const QStringList &pathList)
{ {
qDebug() << "** Changed was notified on " << pathList; qDebug() << "** Changed was notified on " << pathList;

View file

@ -172,6 +172,7 @@ private slots:
void slotTransmissionProgress(const Progress::Info& progress); void slotTransmissionProgress(const Progress::Info& progress);
void slotPollTimerTimeout(); void slotPollTimerTimeout();
void etagRetreived(const QString &);
/** /**
* Triggered by a file system watcher on the local sync dir * Triggered by a file system watcher on the local sync dir
@ -212,6 +213,7 @@ protected:
bool _wipeDb; bool _wipeDb;
Progress::Kind _progressKind; Progress::Kind _progressKind;
QTimer _pollTimer; QTimer _pollTimer;
QString _lastEtag;
CSYNC *_csync_ctx; CSYNC *_csync_ctx;

View file

@ -553,4 +553,62 @@ QString ownCloudInfo::webdavUrl(const QString &connection)
return url; 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 } // ns Mirall

View file

@ -157,6 +157,27 @@ private:
qint64 _lastQuotaUsedBytes; qint64 _lastQuotaUsedBytes;
qint64 _lastQuotaTotalBytes; qint64 _lastQuotaTotalBytes;
QString _lastEtag; 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 } // ns Mirall