Parallel DELETE

This commit is contained in:
Olivier Goffart 2014-11-11 13:19:29 +01:00
parent 506ba022f1
commit 134650eb44
9 changed files with 162 additions and 40 deletions

View file

@ -51,6 +51,7 @@ set(libsync_SRCS
propagator_legacy.cpp propagator_legacy.cpp
propagatedownload.cpp propagatedownload.cpp
propagateupload.cpp propagateupload.cpp
propagateremotedelete.cpp
quotainfo.cpp quotainfo.cpp
syncengine.cpp syncengine.cpp
syncfilestatus.cpp syncfilestatus.cpp

View file

@ -44,6 +44,7 @@ bool AbstractNetworkJob::preOc7WasDetected = false;
AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QObject *parent) AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QObject *parent)
: QObject(parent) : QObject(parent)
, _duration(0) , _duration(0)
, _timedout(false)
, _ignoreCredentialFailure(false) , _ignoreCredentialFailure(false)
, _reply(0) , _reply(0)
, _account(account) , _account(account)
@ -216,6 +217,7 @@ void AbstractNetworkJob::start()
void AbstractNetworkJob::slotTimeout() void AbstractNetworkJob::slotTimeout()
{ {
_timedout = true;
qDebug() << this << "Timeout"; qDebug() << this << "Timeout";
if (reply()) { if (reply()) {
reply()->abort(); reply()->abort();

View file

@ -93,10 +93,12 @@ protected:
QString _responseTimestamp; QString _responseTimestamp;
QElapsedTimer _durationTimer; QElapsedTimer _durationTimer;
quint64 _duration; quint64 _duration;
bool _timedout; // set to true when the timeout slot is recieved
// Timeout workarounds (Because of PHP session locking) // Timeout workarounds (Because of PHP session locking)
static bool preOc7WasDetected; static bool preOc7WasDetected;
private slots: private slots:
void slotFinished(); void slotFinished();
virtual void slotTimeout(); virtual void slotTimeout();

View file

@ -18,6 +18,7 @@
#include "syncjournalfilerecord.h" #include "syncjournalfilerecord.h"
#include "propagatedownload.h" #include "propagatedownload.h"
#include "propagateupload.h" #include "propagateupload.h"
#include "propagateremotedelete.h"
#include "propagatorjobs.h" #include "propagatorjobs.h"
#include "propagator_legacy.h" #include "propagator_legacy.h"
#include "mirallconfigfile.h" #include "mirallconfigfile.h"
@ -197,7 +198,7 @@ PropagateItemJob* OwncloudPropagator::createJob(const SyncFileItem& item) {
switch(item._instruction) { switch(item._instruction) {
case CSYNC_INSTRUCTION_REMOVE: case CSYNC_INSTRUCTION_REMOVE:
if (item._direction == SyncFileItem::Down) return new PropagateLocalRemove(this, item); if (item._direction == SyncFileItem::Down) return new PropagateLocalRemove(this, item);
else return new PropagateRemoteRemove(this, item); else return new PropagateRemoteDelete(this, item);
case CSYNC_INSTRUCTION_NEW: case CSYNC_INSTRUCTION_NEW:
if (item._isDirectory) { if (item._isDirectory) {
if (item._direction == SyncFileItem::Down) return new PropagateLocalMkdir(this, item); if (item._direction == SyncFileItem::Down) return new PropagateLocalMkdir(this, item);

View file

@ -395,7 +395,6 @@ void PropagateDownloadFileQNAM::slotGetFinished()
_propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo()); _propagator->_journal->setDownloadInfo(_item._file, SyncJournalDb::DownloadInfo());
} }
_propagator->_activeJobs--;
SyncFileItem::Status status = job->errorStatus(); SyncFileItem::Status status = job->errorStatus();
if (status == SyncFileItem::NoStatus) { if (status == SyncFileItem::NoStatus) {
status = classifyError(err, _item._httpErrorCode); status = classifyError(err, _item._httpErrorCode);

View file

@ -0,0 +1,106 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.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.
*/
#include "propagateremotedelete.h"
#include "owncloudpropagator_p.h"
#include "account.h"
namespace Mirall {
DeleteJob::DeleteJob(Account* account, const QString& path, QObject* parent)
: AbstractNetworkJob(account, path, parent)
{ }
void DeleteJob::start()
{
QNetworkRequest req;
setReply(davRequest("DELETE", path(), req));
setupConnections(reply());
if( reply()->error() != QNetworkReply::NoError ) {
qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString();
}
AbstractNetworkJob::start();
}
QString DeleteJob::errorString()
{
return _timedout ? tr("Connection timed out") : reply()->errorString();
}
bool DeleteJob::finished()
{
emit finishedSignal();
return true;
}
void PropagateRemoteDelete::start()
{
if (_propagator->_abortRequested.fetchAndAddRelaxed(0))
return;
qDebug() << Q_FUNC_INFO << _item._file;
_job = new DeleteJob(AccountManager::instance()->account(),
_propagator->_remoteFolder + _item._file,
this);
connect(_job, SIGNAL(finishedSignal()), this, SLOT(slotDeleteJobFinished()));
_propagator->_activeJobs ++;
_job->start();
emitReady();
}
void PropagateRemoteDelete::abort()
{
if (_job && _job->reply())
_job->reply()->abort();
}
void PropagateRemoteDelete::slotDeleteJobFinished()
{
_propagator->_activeJobs--;
Q_ASSERT(_job);
qDebug() << Q_FUNC_INFO << _job->reply()->request().url() << "FINISHED WITH STATUS"
<< _job->reply()->error()
<< (_job->reply()->error() == QNetworkReply::NoError ? QLatin1String("") : _job->reply()->errorString());
QNetworkReply::NetworkError err = _job->reply()->error();
if (err != QNetworkReply::NoError) {
_item._httpErrorCode = _job->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if( checkForProblemsWithShared(_item._httpErrorCode,
tr("The file has been removed from a read only share. It was restored.")) ) {
return;
}
SyncFileItem::Status status = classifyError(err, _item._httpErrorCode);
done(status, _job->errorString());
return;
}
_item._requestDuration = _job->duration();
_item._responseTimeStamp = _job->responseTimestamp();
_propagator->_journal->deleteFileRecord(_item._originalFile, _item._isDirectory);
_propagator->_journal->commit("Remote Remove");
done(SyncFileItem::Success);
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.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 "owncloudpropagator.h"
#include "networkjobs.h"
namespace Mirall {
class DeleteJob : public AbstractNetworkJob {
Q_OBJECT
public:
explicit DeleteJob(Account* account, const QString& path, QObject* parent = 0);
void start() Q_DECL_OVERRIDE;
bool finished() Q_DECL_OVERRIDE;
QString errorString();
bool timedOut() { return _timedout; }
signals:
void finishedSignal();
};
class PropagateRemoteDelete : public PropagateItemJob {
Q_OBJECT
QPointer<DeleteJob> _job;
public:
PropagateRemoteDelete (OwncloudPropagator* propagator,const SyncFileItem& item)
: PropagateItemJob(propagator, item) {}
void start() Q_DECL_OVERRIDE;
void abort() Q_DECL_OVERRIDE;
private slots:
void slotDeleteJobFinished();
};
}

View file

@ -135,38 +135,6 @@ void PropagateLocalMkdir::start()
done(SyncFileItem::Success); done(SyncFileItem::Success);
} }
void PropagateRemoteRemove::start()
{
if (_propagator->_abortRequested.fetchAndAddRelaxed(0))
return;
QScopedPointer<char, QScopedPointerPodDeleter> uri(
ne_path_escape((_propagator->_remoteDir + _item._file).toUtf8()));
emit progress(_item, 0);
qDebug() << "** DELETE " << uri.data();
int rc = ne_delete(_propagator->_session, uri.data());
QString errorString = QString::fromUtf8(ne_get_error(_propagator->_session));
int httpStatusCode = errorString.mid(0, errorString.indexOf(QChar(' '))).toInt();
if( checkForProblemsWithShared(httpStatusCode,
tr("The file has been removed from a read only share. It was restored.")) ) {
return;
}
/* Ignore the error 404, it means it is already deleted */
if (updateErrorFromSession(rc, 0, 404)) {
return;
}
// Wed, 15 Nov 1995 06:25:24 GMT
QDateTime dt = QDateTime::currentDateTimeUtc();
_item._responseTimeStamp = dt.toString("hh:mm:ss");
_propagator->_journal->deleteFileRecord(_item._originalFile, _item._isDirectory);
_propagator->_journal->commit("Remote Remove");
done(SyncFileItem::Success);
}
/* The list of properties that is fetched in PropFind after a MKCOL */ /* The list of properties that is fetched in PropFind after a MKCOL */
static const ne_propname ls_props[] = { static const ne_propname ls_props[] = {
{ "DAV:", "getetag"}, { "DAV:", "getetag"},

View file

@ -83,12 +83,6 @@ public:
void start() Q_DECL_OVERRIDE; void start() Q_DECL_OVERRIDE;
}; };
class PropagateRemoteRemove : public PropagateNeonJob {
Q_OBJECT
public:
PropagateRemoteRemove (OwncloudPropagator* propagator,const SyncFileItem& item) : PropagateNeonJob(propagator, item) {}
void start() Q_DECL_OVERRIDE;
};
class PropagateRemoteMkdir : public PropagateNeonJob { class PropagateRemoteMkdir : public PropagateNeonJob {
Q_OBJECT Q_OBJECT
public: public: