SyncEngine: Introduce overall errors that are not tied to a file #5746

For now we use them for:
* csync errors: This allows them to appear in the sync issues tab
* insufficient local disk space, as a summary of individual file errors

Insufficient remote space will use them too, as might other issues that
are bigger than a single sync item.
This commit is contained in:
Christian Kamm 2017-06-28 12:45:54 +02:00 committed by ckamm
parent d34dbbdb0b
commit 5ca743dd25
10 changed files with 107 additions and 13 deletions

View file

@ -106,6 +106,7 @@ Folder::Folder(const FolderDefinition &definition,
connect(_engine.data(), SIGNAL(seenLockedFile(QString)), FolderMan::instance(), SLOT(slotSyncOnceFileUnlocks(QString)));
connect(_engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector &)),
SLOT(slotLogPropagationStart()));
connect(_engine.data(), SIGNAL(summaryError(QString)), SLOT(slotSyncError(QString)));
_scheduleSelfTimer.setSingleShot(true);
_scheduleSelfTimer.setInterval(SyncEngine::minimumFileAgeForUpload);
@ -721,10 +722,10 @@ void Folder::setDirtyNetworkLimits()
_engine->setNetworkLimits(uploadLimit, downloadLimit);
}
void Folder::slotSyncError(const QString &err)
void Folder::slotSyncError(const QString &message)
{
_syncResult.appendErrorString(err);
_syncResult.appendErrorString(message);
emit ProgressDispatcher::instance()->syncError(alias(), message);
}
void Folder::slotSyncStarted()

View file

@ -278,11 +278,16 @@ public slots:
private slots:
void slotSyncStarted();
void slotSyncError(const QString &);
void slotCsyncUnavailable();
void slotSyncFinished(bool);
/** Adds a error message that's not tied to a specific item.
*/
void slotSyncError(const QString &message);
void slotCsyncUnavailable();
void slotFolderDiscovered(bool local, QString folderName);
void slotTransmissionProgress(const ProgressInfo &pi);
void slotItemCompleted(const SyncFileItemPtr &);

View file

@ -49,6 +49,8 @@ IssuesWidget::IssuesWidget(QWidget *parent)
this, SLOT(slotProgressInfo(QString, ProgressInfo)));
connect(ProgressDispatcher::instance(), SIGNAL(itemCompleted(QString, SyncFileItemPtr)),
this, SLOT(slotItemCompleted(QString, SyncFileItemPtr)));
connect(ProgressDispatcher::instance(), SIGNAL(syncError(QString, QString)),
this, SLOT(addLine(QString, QString)));
connect(_ui->_treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)), SLOT(slotOpenFile(QTreeWidgetItem *, int)));
connect(_ui->copyIssuesButton, SIGNAL(clicked()), SIGNAL(copyToClipboard()));
@ -132,6 +134,15 @@ void IssuesWidget::cleanItems(const QString &folder)
emit(issueCountUpdated(_ui->_treeWidget->topLevelItemCount()));
}
void IssuesWidget::addItem(QTreeWidgetItem *item)
{
if (!item)
return;
_ui->_treeWidget->insertTopLevelItem(0, item);
item->setHidden(!shouldBeVisible(item, currentAccountFilter(), currentFolderFilter()));
emit issueCountUpdated(_ui->_treeWidget->topLevelItemCount());
}
void IssuesWidget::slotOpenFile(QTreeWidgetItem *item, int)
{
QString folderName = item->data(2, Qt::UserRole).toString();
@ -164,10 +175,7 @@ void IssuesWidget::slotItemCompleted(const QString &folder, const SyncFileItemPt
QTreeWidgetItem *line = ProtocolWidget::createCompletedTreewidgetItem(folder, *item);
if (!line)
return;
_ui->_treeWidget->insertTopLevelItem(0, line);
line->setHidden(!shouldBeVisible(line, currentAccountFilter(), currentFolderFilter()));
emit issueCountUpdated(_ui->_treeWidget->topLevelItemCount());
addItem(line);
}
void IssuesWidget::slotRefreshIssues()
@ -328,4 +336,41 @@ void IssuesWidget::showFolderErrors(const QString &folderAlias)
_ui->showIgnores->setChecked(false);
_ui->showWarnings->setChecked(false);
}
void IssuesWidget::addLine(const QString &folderAlias, const QString &message)
{
SyncFileItem::Status status = SyncFileItem::NormalError;
auto folder = FolderMan::instance()->folder(folderAlias);
if (!folder)
return;
QStringList columns;
QDateTime timestamp = QDateTime::currentDateTime();
const QString timeStr = ProtocolWidget::timeString(timestamp);
const QString longTimeStr = ProtocolWidget::timeString(timestamp, QLocale::LongFormat);
columns << timeStr;
columns << tr("<global error>");
columns << folder->shortGuiLocalPath();
columns << message;
QIcon icon;
if (status == SyncFileItem::NormalError
|| status == SyncFileItem::FatalError) {
icon = Theme::instance()->syncStateIcon(SyncResult::Error);
} else if (Progress::isWarningKind(status)) {
icon = Theme::instance()->syncStateIcon(SyncResult::Problem);
}
QTreeWidgetItem *twitem = new QTreeWidgetItem(columns);
twitem->setData(0, Qt::SizeHintRole, QSize(0, ActivityItemDelegate::rowHeight()));
twitem->setIcon(0, icon);
twitem->setToolTip(0, longTimeStr);
twitem->setToolTip(3, message);
twitem->setData(0, Qt::UserRole, status);
twitem->setData(2, Qt::UserRole, folderAlias);
addItem(twitem);
}
}

View file

@ -50,6 +50,7 @@ public:
void showFolderErrors(const QString &folderAlias);
public slots:
void addLine(const QString &folderAlias, const QString &message);
void slotProgressInfo(const QString &folder, const ProgressInfo &progress);
void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
void slotOpenFile(QTreeWidgetItem *item, int);
@ -75,6 +76,7 @@ private:
bool shouldBeVisible(QTreeWidgetItem *item, AccountState *filterAccount,
const QString &filterFolderAlias) const;
void cleanItems(const QString &folder);
void addItem(QTreeWidgetItem *item);
Ui::IssuesWidget *_ui;
};

View file

@ -238,6 +238,7 @@ void PropagateItemJob::done(SyncFileItem::Status statusArg, const QString &error
_item->_status = SyncFileItem::SoftError;
}
// Blacklist handling
switch (_item->_status) {
case SyncFileItem::SoftError:
case SyncFileItem::FatalError:

View file

@ -417,7 +417,6 @@ public:
*/
DiskSpaceResult diskSpaceCheck() const;
private slots:
/** Emit the finished signal and make sure it is only emitted once */
@ -445,6 +444,8 @@ signals:
*/
void touchedFile(const QString &fileName);
void insufficientLocalStorage();
private:
AccountPtr _account;
QScopedPointer<PropagateDirectory> _rootJob;

View file

@ -249,6 +249,11 @@ signals:
*/
void itemCompleted(const QString &folder, const SyncFileItemPtr &item);
/**
* @brief A new folder-wide sync error was seen.
*/
void syncError(const QString &folder, const QString &message);
protected:
void setProgressInfo(const QString &folder, const ProgressInfo &progress);

View file

@ -427,9 +427,12 @@ void PropagateDownloadFile::startDownload()
const auto diskSpaceResult = propagator()->diskSpaceCheck();
if (diskSpaceResult != OwncloudPropagator::DiskSpaceOk) {
if (diskSpaceResult == OwncloudPropagator::DiskSpaceFailure) {
_item->_errorMayBeBlacklisted = true;
done(SyncFileItem::NormalError,
tr("The download would reduce free disk space below %1").arg(Utility::octetsToString(freeSpaceLimit())));
// Using BlacklistedError here will make the error not pop up in the account
// tab: instead we'll generate a general "disk space low" message and show
// these detail errors only in the error view.
done(SyncFileItem::BlacklistedError,
tr("The download would reduce free local disk space below the limit"));
emit propagator()->insufficientLocalStorage();
} else if (diskSpaceResult == OwncloudPropagator::DiskSpaceCritical) {
done(SyncFileItem::FatalError,
tr("Free space on disk is less than %1").arg(Utility::octetsToString(criticalFreeSpaceLimit())));

View file

@ -24,6 +24,7 @@
#include "csync_private.h"
#include "filesystem.h"
#include "propagateremotedelete.h"
#include "propagatedownload.h"
#include "asserts.h"
#ifdef Q_OS_WIN
@ -1025,6 +1026,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
connect(_propagator.data(), SIGNAL(finished(bool)), this, SLOT(slotFinished(bool)), Qt::QueuedConnection);
connect(_propagator.data(), SIGNAL(seenLockedFile(QString)), SIGNAL(seenLockedFile(QString)));
connect(_propagator.data(), SIGNAL(touchedFile(QString)), SLOT(slotAddTouchedFile(QString)));
connect(_propagator.data(), SIGNAL(insufficientLocalStorage()), SLOT(slotInsufficientLocalStorage()));
// apply the network limits to the propagator
setNetworkLimits(_uploadLimit, _downloadLimit);
@ -1135,6 +1137,7 @@ void SyncEngine::finalize(bool success)
_seenFiles.clear();
_temporarilyUnavailablePaths.clear();
_renamedFolders.clear();
_uniqueErrors.clear();
_clearTouchedFilesTimer.start();
}
@ -1523,4 +1526,21 @@ void SyncEngine::abort()
}
}
void SyncEngine::slotSummaryError(const QString &message)
{
if (_uniqueErrors.contains(message))
return;
_uniqueErrors.insert(message);
emit summaryError(message);
}
void SyncEngine::slotInsufficientLocalStorage()
{
slotSummaryError(
tr("Disk space is low: Downloads that would reduce free space "
"below %1 were skipped.")
.arg(Utility::octetsToString(freeSpaceLimit())));
}
} // namespace OCC

View file

@ -121,6 +121,9 @@ signals:
void transmissionProgress(const ProgressInfo &progress);
/// We've produced a new summary error.
void summaryError(const QString &message);
void finished(bool success);
void started();
@ -160,6 +163,11 @@ private slots:
/** Wipes the _touchedFiles hash */
void slotClearTouchedFiles();
/** Emit a summary error, unless it was seen before */
void slotSummaryError(const QString &message);
void slotInsufficientLocalStorage();
private:
void handleSyncError(CSYNC *ctx, const char *state);
@ -267,6 +275,9 @@ private:
/** For clearing the _touchedFiles variable after sync finished */
QTimer _clearTouchedFilesTimer;
/** List of unique errors that occurred in a sync run. */
QSet<QString> _uniqueErrors;
};
}