Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log when we begin and end a backup requested on a socket #8535

Merged
merged 1 commit into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/unreleased/8437
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Enhancement: Add initial support for backups triggered by an external tool
We added a socket api function which allows creation of backups.

https://github.com/owncloud/client/pull/8437
https://github.com/owncloud/client/pull/8535
2 changes: 1 addition & 1 deletion src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,7 +1001,7 @@ void Folder::slotEmitFinishedDelayed()
void Folder::slotTransmissionProgress(const ProgressInfo &pi)
{
emit progressInfo(pi);
ProgressDispatcher::instance()->setProgressInfo(alias(), pi);
emit ProgressDispatcher::instance()->progressInfo(alias(), pi);
}

// a item is completed: count the errors and forward to the ProgressDispatcher
Expand Down
14 changes: 7 additions & 7 deletions src/gui/protocolwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,9 @@ void ProtocolItem::setExtraData(QTreeWidgetItem *item, const ExtraData &data)
item->setData(0, Qt::UserRole, QVariant::fromValue(data));
}

ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &item)
ProtocolItem *ProtocolItem::create(const QString &folderName, const SyncFileItem &item)
{
auto f = FolderMan::instance()->folder(folder);
if (!f) {
return nullptr;
}
auto folder = FolderMan::instance()->folder(folderName);

QStringList columns;
QDateTime timestamp = QDateTime::currentDateTime();
Expand All @@ -69,10 +66,13 @@ ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &it

columns << timeStr;
columns << Utility::fileNameForGuiUse(item._originalFile);
columns << f->shortGuiLocalPath();
columns << (folder ? folder->shortGuiLocalPath() : QDir::toNativeSeparators(folderName));

// If the error string is set, it's prefered because it is a useful user message.
QString message = item._errorString;
if (message.isEmpty()) {
message = item._messageString;
}
if (message.isEmpty()) {
message = Progress::asResultString(item);
}
Expand Down Expand Up @@ -103,7 +103,7 @@ ProtocolItem *ProtocolItem::create(const QString &folder, const SyncFileItem &it
ProtocolItem::ExtraData data;
data.timestamp = timestamp;
data.path = item.destination();
data.folderName = folder;
data.folderName = folderName;
data.status = item._status;
data.size = item._size;
data.direction = item._direction;
Expand Down
52 changes: 40 additions & 12 deletions src/gui/socketapi/socketuploadjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,40 @@

#include "accountmanager.h"
#include "common/syncjournaldb.h"
#include "progressdispatcher.h"
#include "syncengine.h"

#include <QDir>
#include <QFileInfo>
#include <QJsonArray>
#include <QRegularExpression>
#include <QTemporaryFile>

using namespace OCC;

namespace {

// create a fake SyncFileItemPtr to display a message in the protocol
void logMessage(const QString &localPath, const QString &message)
{
auto item = SyncFileItemPtr::create();
item->_status = SyncFileItem::Success;
item->_messageString = message;
item->_responseTimeStamp = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8();
Q_EMIT ProgressDispatcher::instance()->itemCompleted(QDir::toNativeSeparators(localPath), item);
}
}

SocketUploadJob::SocketUploadJob(const QSharedPointer<SocketApiJobV2> &job)
: _apiJob(job)
{
connect(job.data(), &SocketApiJobV2::finished, this, &SocketUploadJob::deleteLater);
}


void SocketUploadJob::start()
{
const auto localPath = _apiJob->arguments()[QLatin1String("localPath")].toString();
_localPath = _apiJob->arguments()[QLatin1String("localPath")].toString();
auto remotePath = _apiJob->arguments()[QLatin1String("remotePath")].toString();
if (!remotePath.startsWith(QLatin1Char('/'))) {
remotePath = QLatin1Char('/') + remotePath;
Expand All @@ -45,42 +61,48 @@ void SocketUploadJob::start()
AccountStatePtr account;
account = AccountManager::instance()->account(accname);

logMessage(_localPath, tr("Backup of %1 started").arg(QDir::toNativeSeparators(_localPath)));

if (!account) {
_apiJob->failure(QStringLiteral("Failed to find %1").arg(QString::fromUtf8(QJsonDocument(_apiJob->arguments()[QLatin1String("account")].toObject()).toJson())));
fail(tr("Failed to find %1").arg(QString::fromUtf8(QJsonDocument(_apiJob->arguments()[QLatin1String("account")].toObject()).toJson())));
return;
}

if (!QFileInfo(localPath).isAbsolute()) {
_apiJob->failure(QStringLiteral("Local path must be a an absolute path"));
if (!QFileInfo(_localPath).isAbsolute()) {
fail(tr("Local path must be a an absolute path"));
return;
}
auto tmp = new QTemporaryFile(this);
if (!tmp->open()) {
_apiJob->failure(QStringLiteral("Failed to create temporary database"));
fail(tr("Failed to create temporary database"));
return;
}

auto db = new SyncJournalDb(tmp->fileName(), this);
auto engine = new SyncEngine(account->account(), localPath.endsWith(QLatin1Char('/')) ? localPath : localPath + QLatin1Char('/'), remotePath, db);
auto engine = new SyncEngine(account->account(), _localPath.endsWith(QLatin1Char('/')) ? _localPath : _localPath + QLatin1Char('/'), remotePath, db);
engine->setParent(db);

connect(engine, &OCC::SyncEngine::transmissionProgress, this, [this](const ProgressInfo &info) {
Q_EMIT ProgressDispatcher::instance()->progressInfo(_localPath, info);
});
connect(engine, &OCC::SyncEngine::itemCompleted, this, [this](const OCC::SyncFileItemPtr item) {
_syncedFiles.append(item->_file);
});

connect(engine, &OCC::SyncEngine::finished, this, [this, localPath](bool ok) {
connect(engine, &OCC::SyncEngine::finished, this, [this](bool ok) {
if (ok) {
_apiJob->success({ { "localPath", localPath }, { "syncedFiles", QJsonArray::fromStringList(_syncedFiles) } });
logMessage(_localPath, tr("Backup of %1 succeeded").arg(QDir::toNativeSeparators(_localPath)));
_apiJob->success({ { QStringLiteral("localPath"), _localPath }, { QStringLiteral("syncedFiles"), QJsonArray::fromStringList(_syncedFiles) } });
}
});
connect(engine, &OCC::SyncEngine::syncError, this, [this](const QString &error, ErrorCategory) {
_apiJob->failure(error);
fail(error);
});

auto opt = engine->syncOptions();
opt.setFilePattern(pattern);
if (!opt.fileRegex().isValid()) {
_apiJob->failure(opt.fileRegex().errorString());
fail(opt.fileRegex().errorString());
return;
}
engine->setSyncOptions(opt);
Expand All @@ -92,10 +114,16 @@ void SocketUploadJob::start()
if (reply->error() == QNetworkReply::NoError) {
engine->startSync();
} else if (reply->error() == 202) {
_apiJob->failure(QStringLiteral("Destination %1 already exists").arg(remotePath));
fail(QStringLiteral("Destination %1 already exists").arg(remotePath));
} else {
_apiJob->failure(reply->errorString());
fail(reply->errorString());
}
});
mkdir->start();
}

void SocketUploadJob::fail(const QString &error)
{
logMessage(_localPath, tr("Backup of %1 failed with: %2").arg(QDir::toNativeSeparators(_localPath), error));
_apiJob->failure(error);
}
3 changes: 3 additions & 0 deletions src/gui/socketapi/socketuploadjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class SocketUploadJob : public QObject
void start();

private:
void fail(const QString &error);

QString _localPath;
QSharedPointer<SocketApiJobV2> _apiJob;
QStringList _syncedFiles;
};
Expand Down
12 changes: 0 additions & 12 deletions src/libsync/progressdispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,6 @@ ProgressDispatcher::~ProgressDispatcher()
{
}

void ProgressDispatcher::setProgressInfo(const QString &folder, const ProgressInfo &progress)
{
if (folder.isEmpty())
// The update phase now also has progress
// (progress._currentItems.size() == 0
// && progress._totalFileCount == 0) )
{
return;
}
emit progressInfo(folder, progress);
}

ProgressInfo::ProgressInfo()
{
connect(&_updateEstimatesTimer, &QTimer::timeout, this, &ProgressInfo::updateEstimates);
Expand Down
5 changes: 0 additions & 5 deletions src/libsync/progressdispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,6 @@ enum class ErrorCategory {
class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject
{
Q_OBJECT

friend class Folder; // only allow Folder class to access the setting slots.
public:
static ProgressDispatcher *instance();
~ProgressDispatcher() override;
Expand Down Expand Up @@ -318,9 +316,6 @@ class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject
*/
void folderConflicts(const QString &folder, const QStringList &conflictPaths);

protected:
void setProgressInfo(const QString &folder, const ProgressInfo &progress);

private:
ProgressDispatcher(QObject *parent = nullptr);

Expand Down
1 change: 1 addition & 0 deletions src/libsync/syncfileitem.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ class OWNCLOUDSYNC_EXPORT SyncFileItem
quint16 _httpErrorCode;
RemotePermissions _remotePerm;
QString _errorString; // Contains a string only in case of error
QString _messageString; // Contains a string only in case of hand crafted events
QByteArray _responseTimeStamp;
QByteArray _requestId; // X-Request-Id of the failed request
quint32 _affectedItems; // the number of affected items by the operation on this item.
Expand Down