Avoid potentially losing events
I have observed that Syncthing Tray can get stuck thinking a remote device still needs data. Likely the update got lost. The code contains certain conditions in which folder completion events and requesting completion are supressed. Those conditions are based on timestamps. That is not ideal as the accuracy is only one second (so different timestamps might be considered equal as they are rounded to be the same). Additionally, it makes no sense to assume a timestamp upon receiving a response as the information might be older than the time it was received. This change avoids those conditions. It rather uses the event ID to decide what event/reply is newer. This change also uses quint64 instead of int for event IDs to avoid running into an overflow (or rather conversion error) when deserializing the ID which might be bigger than int. (Not sure how big the ID can become; this is to be on the safe side.)
This commit is contained in:
parent
ecfb346344
commit
843f164df1
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
using SyncthingEventId = quint64;
|
||||||
|
|
||||||
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingCompletion {
|
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingCompletion {
|
||||||
CppUtilities::DateTime lastUpdate;
|
CppUtilities::DateTime lastUpdate;
|
||||||
double percentage = 0;
|
double percentage = 0;
|
||||||
|
@ -23,7 +25,7 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingCompletion {
|
||||||
constexpr Needed &operator+=(const Needed &other);
|
constexpr Needed &operator+=(const Needed &other);
|
||||||
constexpr Needed &operator-=(const Needed &other);
|
constexpr Needed &operator-=(const Needed &other);
|
||||||
} needed;
|
} needed;
|
||||||
bool requested = false;
|
SyncthingEventId requestedForEventId = 0;
|
||||||
constexpr SyncthingCompletion &operator+=(const SyncthingCompletion &other);
|
constexpr SyncthingCompletion &operator+=(const SyncthingCompletion &other);
|
||||||
constexpr SyncthingCompletion &operator-=(const SyncthingCompletion &other);
|
constexpr SyncthingCompletion &operator-=(const SyncthingCompletion &other);
|
||||||
void recomputePercentage();
|
void recomputePercentage();
|
||||||
|
|
|
@ -441,7 +441,9 @@ void SyncthingConnection::continueReconnecting()
|
||||||
m_hasDiskEvents = false;
|
m_hasDiskEvents = false;
|
||||||
m_dirs.clear();
|
m_dirs.clear();
|
||||||
m_devs.clear();
|
m_devs.clear();
|
||||||
m_lastConnectionsUpdate = DateTime();
|
m_lastConnectionsUpdateEvent = 0;
|
||||||
|
m_lastConnectionsUpdateTime = DateTime();
|
||||||
|
m_lastFileEvent = 0;
|
||||||
m_lastFileTime = DateTime();
|
m_lastFileTime = DateTime();
|
||||||
m_lastErrorTime = DateTime();
|
m_lastErrorTime = DateTime();
|
||||||
m_startTime = DateTime();
|
m_startTime = DateTime();
|
||||||
|
|
|
@ -295,25 +295,27 @@ private Q_SLOTS:
|
||||||
void readErrors();
|
void readErrors();
|
||||||
void readClearingErrors();
|
void readClearingErrors();
|
||||||
void readEvents();
|
void readEvents();
|
||||||
void readEventsFromJsonArray(const QJsonArray &events, int &idVariable);
|
void readEventsFromJsonArray(const QJsonArray &events, quint64 &idVariable);
|
||||||
void readStartingEvent(const QJsonObject &eventData);
|
void readStartingEvent(const QJsonObject &eventData);
|
||||||
void readStatusChangedEvent(CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
void readStatusChangedEvent(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
||||||
void readDownloadProgressEvent(CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
void readDownloadProgressEvent(const QJsonObject &eventData);
|
||||||
void readDirEvent(CppUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
|
void readDirEvent(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
|
||||||
void readDeviceEvent(CppUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
|
void readDeviceEvent(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QString &eventType, const QJsonObject &eventData);
|
||||||
void readItemStarted(CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
void readItemStarted(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
||||||
void readItemFinished(CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
void readItemFinished(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
||||||
void readFolderErrors(CppUtilities::DateTime eventTime, const QJsonObject &eventData, Data::SyncthingDir &dirInfo, int index);
|
void readFolderErrors(
|
||||||
void readFolderCompletion(
|
SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData, Data::SyncthingDir &dirInfo, int index);
|
||||||
CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
void readFolderCompletion(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &dirId,
|
||||||
void readFolderCompletion(CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &devId, Data::SyncthingDev *devInfo,
|
Data::SyncthingDir *dirInfo, int dirIndex);
|
||||||
int devIndex, const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
void readFolderCompletion(SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &devId,
|
||||||
void readLocalFolderCompletion(CppUtilities::DateTime eventTime, const QJsonObject &eventData, Data::SyncthingDir &dirInfo, int index);
|
Data::SyncthingDev *devInfo, int devIndex, const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
||||||
|
void readLocalFolderCompletion(
|
||||||
|
SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &eventData, Data::SyncthingDir &dirInfo, int index);
|
||||||
void readRemoteFolderCompletion(CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &devId, Data::SyncthingDev *devInfo,
|
void readRemoteFolderCompletion(CppUtilities::DateTime eventTime, const QJsonObject &eventData, const QString &devId, Data::SyncthingDev *devInfo,
|
||||||
int devIndex, const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
int devIndex, const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
||||||
void readRemoteFolderCompletion(const Data::SyncthingCompletion &completion, const QString &devId, Data::SyncthingDev *devInfo, int devIndex,
|
void readRemoteFolderCompletion(const Data::SyncthingCompletion &completion, const QString &devId, Data::SyncthingDev *devInfo, int devIndex,
|
||||||
const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
const QString &dirId, Data::SyncthingDir *dirInfo, int dirIndex);
|
||||||
void readRemoteIndexUpdated(CppUtilities::DateTime eventTime, const QJsonObject &eventData);
|
void readRemoteIndexUpdated(SyncthingEventId eventId, const QJsonObject &eventData);
|
||||||
void readPostConfig();
|
void readPostConfig();
|
||||||
void readRescan();
|
void readRescan();
|
||||||
void readDevPauseResume();
|
void readDevPauseResume();
|
||||||
|
@ -322,7 +324,8 @@ private Q_SLOTS:
|
||||||
void readShutdown();
|
void readShutdown();
|
||||||
void readDirStatus();
|
void readDirStatus();
|
||||||
void readDirPullErrors();
|
void readDirPullErrors();
|
||||||
void readDirSummary(CppUtilities::DateTime eventTime, const QJsonObject &summary, Data::SyncthingDir &dirInfo, int index);
|
void readDirSummary(
|
||||||
|
SyncthingEventId eventId, CppUtilities::DateTime eventTime, const QJsonObject &summary, Data::SyncthingDir &dirInfo, int index);
|
||||||
void readDirRejected(CppUtilities::DateTime eventTime, const QString &dirId, const QJsonObject &eventData);
|
void readDirRejected(CppUtilities::DateTime eventTime, const QString &dirId, const QJsonObject &eventData);
|
||||||
void readDevRejected(CppUtilities::DateTime eventTime, const QString &devId, const QJsonObject &eventData);
|
void readDevRejected(CppUtilities::DateTime eventTime, const QString &devId, const QJsonObject &eventData);
|
||||||
void readCompletion();
|
void readCompletion();
|
||||||
|
@ -388,8 +391,8 @@ private:
|
||||||
bool m_connectionAborted;
|
bool m_connectionAborted;
|
||||||
bool m_abortingToReconnect;
|
bool m_abortingToReconnect;
|
||||||
bool m_requestCompletion;
|
bool m_requestCompletion;
|
||||||
int m_lastEventId;
|
SyncthingEventId m_lastEventId;
|
||||||
int m_lastDiskEventId;
|
SyncthingEventId m_lastDiskEventId;
|
||||||
QTimer m_trafficPollTimer;
|
QTimer m_trafficPollTimer;
|
||||||
QTimer m_devStatsPollTimer;
|
QTimer m_devStatsPollTimer;
|
||||||
QTimer m_errorsPollTimer;
|
QTimer m_errorsPollTimer;
|
||||||
|
@ -421,7 +424,9 @@ private:
|
||||||
bool m_hasDiskEvents;
|
bool m_hasDiskEvents;
|
||||||
std::vector<SyncthingDir> m_dirs;
|
std::vector<SyncthingDir> m_dirs;
|
||||||
std::vector<SyncthingDev> m_devs;
|
std::vector<SyncthingDev> m_devs;
|
||||||
CppUtilities::DateTime m_lastConnectionsUpdate;
|
SyncthingEventId m_lastConnectionsUpdateEvent;
|
||||||
|
CppUtilities::DateTime m_lastConnectionsUpdateTime;
|
||||||
|
SyncthingEventId m_lastFileEvent = 0;
|
||||||
CppUtilities::DateTime m_lastFileTime;
|
CppUtilities::DateTime m_lastFileTime;
|
||||||
CppUtilities::DateTime m_lastErrorTime;
|
CppUtilities::DateTime m_lastErrorTime;
|
||||||
CppUtilities::DateTime m_startTime;
|
CppUtilities::DateTime m_startTime;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -808,8 +809,9 @@ void SyncthingConnection::requestConnections()
|
||||||
if (m_connectionsReply) {
|
if (m_connectionsReply) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QObject::connect(m_connectionsReply = requestData(QStringLiteral("system/connections"), QUrlQuery()), &QNetworkReply::finished, this,
|
m_connectionsReply = requestData(QStringLiteral("system/connections"), QUrlQuery());
|
||||||
&SyncthingConnection::readConnections);
|
m_connectionsReply->setProperty("lastEventId", m_lastEventId);
|
||||||
|
QObject::connect(m_connectionsReply, &QNetworkReply::finished, this, &SyncthingConnection::readConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -841,7 +843,7 @@ void SyncthingConnection::readConnections()
|
||||||
const std::uint64_t totalOutgoingTraffic = totalOutgoingTrafficValue.isDouble() ? jsonValueToInt(totalOutgoingTrafficValue) : unknownTraffic;
|
const std::uint64_t totalOutgoingTraffic = totalOutgoingTrafficValue.isDouble() ? jsonValueToInt(totalOutgoingTrafficValue) : unknownTraffic;
|
||||||
double transferTime = 0.0;
|
double transferTime = 0.0;
|
||||||
const bool hasDelta
|
const bool hasDelta
|
||||||
= !m_lastConnectionsUpdate.isNull() && ((transferTime = (DateTime::gmtNow() - m_lastConnectionsUpdate).totalSeconds()) != 0.0);
|
= !m_lastConnectionsUpdateTime.isNull() && ((transferTime = (DateTime::gmtNow() - m_lastConnectionsUpdateTime).totalSeconds()) != 0.0);
|
||||||
m_totalIncomingRate = (hasDelta && totalIncomingTraffic != unknownTraffic && m_totalIncomingTraffic != unknownTraffic)
|
m_totalIncomingRate = (hasDelta && totalIncomingTraffic != unknownTraffic && m_totalIncomingTraffic != unknownTraffic)
|
||||||
? static_cast<double>(totalIncomingTraffic - m_totalIncomingTraffic) * 0.008 / transferTime
|
? static_cast<double>(totalIncomingTraffic - m_totalIncomingTraffic) * 0.008 / transferTime
|
||||||
: 0.0;
|
: 0.0;
|
||||||
|
@ -886,7 +888,8 @@ void SyncthingConnection::readConnections()
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastConnectionsUpdate = DateTime::gmtNow();
|
m_lastConnectionsUpdateEvent = reply->property("lastEventId").toULongLong();
|
||||||
|
m_lastConnectionsUpdateTime = DateTime::gmtNow();
|
||||||
|
|
||||||
// since there seems no event for this data, keep polling
|
// since there seems no event for this data, keep polling
|
||||||
if (m_keepPolling) {
|
if (m_keepPolling) {
|
||||||
|
@ -980,8 +983,9 @@ void SyncthingConnection::requestDirStatistics()
|
||||||
if (m_dirStatsReply) {
|
if (m_dirStatsReply) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QObject::connect(m_dirStatsReply = requestData(QStringLiteral("stats/folder"), QUrlQuery()), &QNetworkReply::finished, this,
|
m_dirStatsReply = requestData(QStringLiteral("stats/folder"), QUrlQuery());
|
||||||
&SyncthingConnection::readDirStatistics);
|
m_dirStatsReply->setProperty("lastEventId", m_lastEventId);
|
||||||
|
QObject::connect(m_dirStatsReply, &QNetworkReply::finished, this, &SyncthingConnection::readDirStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1012,20 +1016,23 @@ void SyncthingConnection::readDirStatistics()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dirModified = false;
|
auto dirModified = false;
|
||||||
|
const auto eventId = reply->property("lastEventId").toULongLong();
|
||||||
const auto lastScan = dirObj.value(QLatin1String("lastScan")).toString().toUtf8();
|
const auto lastScan = dirObj.value(QLatin1String("lastScan")).toString().toUtf8();
|
||||||
if (!lastScan.isEmpty()) {
|
if (!lastScan.isEmpty()) {
|
||||||
dirModified = true;
|
dirModified = true;
|
||||||
dirInfo.lastScanTime = parseTimeStamp(dirObj.value(QLatin1String("lastScan")), QStringLiteral("last scan"));
|
dirInfo.lastScanTime = parseTimeStamp(dirObj.value(QLatin1String("lastScan")), QStringLiteral("last scan"));
|
||||||
}
|
}
|
||||||
const QJsonObject lastFileObj(dirObj.value(QLatin1String("lastFile")).toObject());
|
const auto lastFileObj = dirObj.value(QLatin1String("lastFile")).toObject();
|
||||||
if (!lastFileObj.isEmpty()) {
|
if (!lastFileObj.isEmpty()) {
|
||||||
|
dirInfo.lastFileEvent = eventId;
|
||||||
dirInfo.lastFileName = lastFileObj.value(QLatin1String("filename")).toString();
|
dirInfo.lastFileName = lastFileObj.value(QLatin1String("filename")).toString();
|
||||||
dirModified = true;
|
dirModified = true;
|
||||||
if (!dirInfo.lastFileName.isEmpty()) {
|
if (!dirInfo.lastFileName.isEmpty()) {
|
||||||
dirInfo.lastFileDeleted = lastFileObj.value(QLatin1String("deleted")).toBool(false);
|
dirInfo.lastFileDeleted = lastFileObj.value(QLatin1String("deleted")).toBool(false);
|
||||||
dirInfo.lastFileTime = parseTimeStamp(lastFileObj.value(QLatin1String("at")), QStringLiteral("dir statistics"));
|
dirInfo.lastFileTime = parseTimeStamp(lastFileObj.value(QLatin1String("at")), QStringLiteral("dir statistics"));
|
||||||
if (!dirInfo.lastFileTime.isNull() && dirInfo.lastFileTime > m_lastFileTime) {
|
if (!dirInfo.lastFileTime.isNull() && eventId >= m_lastFileEvent) {
|
||||||
|
m_lastFileEvent = eventId;
|
||||||
m_lastFileTime = dirInfo.lastFileTime;
|
m_lastFileTime = dirInfo.lastFileTime;
|
||||||
m_lastFileName = dirInfo.lastFileName;
|
m_lastFileName = dirInfo.lastFileName;
|
||||||
m_lastFileDeleted = dirInfo.lastFileDeleted;
|
m_lastFileDeleted = dirInfo.lastFileDeleted;
|
||||||
|
@ -1060,6 +1067,7 @@ void SyncthingConnection::requestDirStatus(const QString &dirId)
|
||||||
query.addQueryItem(QStringLiteral("folder"), dirId);
|
query.addQueryItem(QStringLiteral("folder"), dirId);
|
||||||
auto *const reply = requestData(QStringLiteral("db/status"), query);
|
auto *const reply = requestData(QStringLiteral("db/status"), query);
|
||||||
reply->setProperty("dirId", dirId);
|
reply->setProperty("dirId", dirId);
|
||||||
|
reply->setProperty("lastEventId", m_lastEventId);
|
||||||
m_otherReplies << reply;
|
m_otherReplies << reply;
|
||||||
QObject::connect(reply, &QNetworkReply::finished, this, &SyncthingConnection::readDirStatus, Qt::QueuedConnection);
|
QObject::connect(reply, &QNetworkReply::finished, this, &SyncthingConnection::readDirStatus, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
@ -1078,7 +1086,7 @@ void SyncthingConnection::readDirStatus()
|
||||||
case QNetworkReply::NoError: {
|
case QNetworkReply::NoError: {
|
||||||
// determine relevant dir
|
// determine relevant dir
|
||||||
int index;
|
int index;
|
||||||
const QString dirId(reply->property("dirId").toString());
|
const auto dirId = reply->property("dirId").toString();
|
||||||
SyncthingDir *const dir = findDirInfo(dirId, index);
|
SyncthingDir *const dir = findDirInfo(dirId, index);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
// discard status for unknown dirs
|
// discard status for unknown dirs
|
||||||
|
@ -1093,7 +1101,7 @@ void SyncthingConnection::readDirStatus()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
readDirSummary(DateTime::now(), replyDoc.object(), *dir, index);
|
readDirSummary(reply->property("lastEventId").toULongLong(), DateTime::now(), replyDoc.object(), *dir, index);
|
||||||
|
|
||||||
if (m_keepPolling) {
|
if (m_keepPolling) {
|
||||||
concludeConnection();
|
concludeConnection();
|
||||||
|
@ -1123,6 +1131,7 @@ void SyncthingConnection::requestDirPullErrors(const QString &dirId, int page, i
|
||||||
}
|
}
|
||||||
auto *const reply = requestData(folderErrorsPath(), query);
|
auto *const reply = requestData(folderErrorsPath(), query);
|
||||||
reply->setProperty("dirId", dirId);
|
reply->setProperty("dirId", dirId);
|
||||||
|
reply->setProperty("lastEventId", m_lastEventId);
|
||||||
QObject::connect(reply, &QNetworkReply::finished, this, &SyncthingConnection::readDirPullErrors);
|
QObject::connect(reply, &QNetworkReply::finished, this, &SyncthingConnection::readDirPullErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1164,7 @@ void SyncthingConnection::readDirPullErrors()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
readFolderErrors(DateTime::now(), replyDoc.object(), *dir, index);
|
readFolderErrors(reply->property("lastEventId").toULongLong(), DateTime::now(), replyDoc.object(), *dir, index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QNetworkReply::OperationCanceledError:
|
case QNetworkReply::OperationCanceledError:
|
||||||
|
@ -1184,10 +1193,10 @@ void SyncthingConnection::requestCompletion(const QString &devId, const QString
|
||||||
static void ensureCompletionNotConsideredRequested(const QString &devId, SyncthingDev *devInfo, const QString &dirId, SyncthingDir *dirInfo)
|
static void ensureCompletionNotConsideredRequested(const QString &devId, SyncthingDev *devInfo, const QString &dirId, SyncthingDir *dirInfo)
|
||||||
{
|
{
|
||||||
if (devInfo) {
|
if (devInfo) {
|
||||||
devInfo->completionByDir[dirId].requested = false;
|
devInfo->completionByDir[dirId].requestedForEventId = 0;
|
||||||
}
|
}
|
||||||
if (dirInfo) {
|
if (dirInfo) {
|
||||||
dirInfo->completionByDevice[devId].requested = false;
|
dirInfo->completionByDevice[devId].requestedForEventId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
@ -1543,9 +1552,9 @@ void SyncthingConnection::readPostConfig()
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads data from requestDirStatus() and FolderSummary-event and stores them to \a dir.
|
* \brief Reads data from requestDirStatus() and FolderSummary-event and stores them to \a dir.
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readDirSummary(DateTime eventTime, const QJsonObject &summary, SyncthingDir &dir, int index)
|
void SyncthingConnection::readDirSummary(SyncthingEventId eventId, DateTime eventTime, const QJsonObject &summary, SyncthingDir &dir, int index)
|
||||||
{
|
{
|
||||||
if (summary.isEmpty() || dir.lastStatisticsUpdate > eventTime) {
|
if (summary.isEmpty() || dir.lastStatisticsUpdateEvent > eventId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1553,7 +1562,7 @@ void SyncthingConnection::readDirSummary(DateTime eventTime, const QJsonObject &
|
||||||
auto &globalStats(dir.globalStats);
|
auto &globalStats(dir.globalStats);
|
||||||
auto &localStats(dir.localStats);
|
auto &localStats(dir.localStats);
|
||||||
auto &neededStats(dir.neededStats);
|
auto &neededStats(dir.neededStats);
|
||||||
const auto previouslyUpdated(!dir.lastStatisticsUpdate.isNull());
|
const auto previouslyUpdated(!dir.lastStatisticsUpdateTime.isNull());
|
||||||
const auto previouslyGlobal(globalStats);
|
const auto previouslyGlobal(globalStats);
|
||||||
const auto previouslyNeeded(neededStats);
|
const auto previouslyNeeded(neededStats);
|
||||||
|
|
||||||
|
@ -1577,17 +1586,19 @@ void SyncthingConnection::readDirSummary(DateTime eventTime, const QJsonObject &
|
||||||
m_dirStatsAltered = true;
|
m_dirStatsAltered = true;
|
||||||
|
|
||||||
dir.ignorePatterns = summary.value(QLatin1String("ignorePatterns")).toBool();
|
dir.ignorePatterns = summary.value(QLatin1String("ignorePatterns")).toBool();
|
||||||
dir.lastStatisticsUpdate = eventTime;
|
dir.lastStatisticsUpdateEvent = eventId;
|
||||||
|
dir.lastStatisticsUpdateTime = eventTime;
|
||||||
|
|
||||||
// update status
|
// update status
|
||||||
const auto lastStatusUpdate = parseTimeStamp(summary.value(QLatin1String("stateChanged")), QStringLiteral("state changed"), dir.lastStatusUpdate);
|
const auto lastStatusUpdate
|
||||||
|
= parseTimeStamp(summary.value(QLatin1String("stateChanged")), QStringLiteral("state changed"), dir.lastStatusUpdateTime);
|
||||||
if (dir.pullErrorCount) {
|
if (dir.pullErrorCount) {
|
||||||
// consider the directory still as out-of-sync if there are still pull errors
|
// consider the directory still as out-of-sync if there are still pull errors
|
||||||
// note: Syncthing can report an "idle" status despite pull errors.
|
// note: Syncthing can report an "idle" status despite pull errors.
|
||||||
dir.status = SyncthingDirStatus::OutOfSync;
|
dir.status = SyncthingDirStatus::OutOfSync;
|
||||||
dir.lastStatusUpdate = std::max(dir.lastStatusUpdate, lastStatusUpdate);
|
dir.lastStatusUpdateTime = std::max(dir.lastStatusUpdateTime, lastStatusUpdate);
|
||||||
} else if (const auto state = summary.value(QLatin1String("state")).toString(); !state.isEmpty()) {
|
} else if (const auto state = summary.value(QLatin1String("state")).toString(); !state.isEmpty()) {
|
||||||
dir.assignStatus(state, lastStatusUpdate);
|
dir.assignStatus(state, eventId, lastStatusUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir.completionPercentage = globalStats.bytes ? static_cast<int>((globalStats.bytes - neededStats.bytes) * 100 / globalStats.bytes) : 100;
|
dir.completionPercentage = globalStats.bytes ? static_cast<int>((globalStats.bytes - neededStats.bytes) * 100 / globalStats.bytes) : 100;
|
||||||
|
@ -1746,32 +1757,34 @@ void SyncthingConnection::readEvents()
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readEventsFromJsonArray(const QJsonArray &events, int &idVariable)
|
void SyncthingConnection::readEventsFromJsonArray(const QJsonArray &events, quint64 &idVariable)
|
||||||
{
|
{
|
||||||
for (const auto &eventVal : events) {
|
for (const auto &eventVal : events) {
|
||||||
const auto event = eventVal.toObject();
|
const auto event = eventVal.toObject();
|
||||||
const auto eventTime = parseTimeStamp(event.value(QLatin1String("time")), QStringLiteral("event time"));
|
const auto eventTime = parseTimeStamp(event.value(QLatin1String("time")), QStringLiteral("event time"));
|
||||||
const auto eventType = event.value(QLatin1String("type")).toString();
|
const auto eventType = event.value(QLatin1String("type")).toString();
|
||||||
const auto eventData = event.value(QLatin1String("data")).toObject();
|
const auto eventData = event.value(QLatin1String("data")).toObject();
|
||||||
|
const auto eventIdValue = event.value(QLatin1String("id"));
|
||||||
idVariable = event.value(QLatin1String("id")).toInt(idVariable);
|
const auto eventId = static_cast<quint64>(std::max(eventIdValue.toDouble(), 0.0));
|
||||||
|
if (eventIdValue.isDouble()) {
|
||||||
|
idVariable = eventId;
|
||||||
|
}
|
||||||
if (eventType == QLatin1String("Starting")) {
|
if (eventType == QLatin1String("Starting")) {
|
||||||
readStartingEvent(eventData);
|
readStartingEvent(eventData);
|
||||||
} else if (eventType == QLatin1String("StateChanged")) {
|
} else if (eventType == QLatin1String("StateChanged")) {
|
||||||
readStatusChangedEvent(eventTime, eventData);
|
readStatusChangedEvent(eventId, eventTime, eventData);
|
||||||
} else if (eventType == QLatin1String("DownloadProgress")) {
|
} else if (eventType == QLatin1String("DownloadProgress")) {
|
||||||
readDownloadProgressEvent(eventTime, eventData);
|
readDownloadProgressEvent(eventData);
|
||||||
} else if (eventType.startsWith(QLatin1String("Folder"))) {
|
} else if (eventType.startsWith(QLatin1String("Folder"))) {
|
||||||
readDirEvent(eventTime, eventType, eventData);
|
readDirEvent(eventId, eventTime, eventType, eventData);
|
||||||
} else if (eventType.startsWith(QLatin1String("Device"))) {
|
} else if (eventType.startsWith(QLatin1String("Device"))) {
|
||||||
readDeviceEvent(eventTime, eventType, eventData);
|
readDeviceEvent(eventId, eventTime, eventType, eventData);
|
||||||
} else if (eventType == QLatin1String("ItemStarted")) {
|
} else if (eventType == QLatin1String("ItemStarted")) {
|
||||||
readItemStarted(eventTime, eventData);
|
readItemStarted(eventId, eventTime, eventData);
|
||||||
} else if (eventType == QLatin1String("ItemFinished")) {
|
} else if (eventType == QLatin1String("ItemFinished")) {
|
||||||
readItemFinished(eventTime, eventData);
|
readItemFinished(eventId, eventTime, eventData);
|
||||||
} else if (eventType == QLatin1String("RemoteIndexUpdated")) {
|
} else if (eventType == QLatin1String("RemoteIndexUpdated")) {
|
||||||
readRemoteIndexUpdated(eventTime, eventData);
|
readRemoteIndexUpdated(eventId, eventData);
|
||||||
} else if (eventType == QLatin1String("ConfigSaved")) {
|
} else if (eventType == QLatin1String("ConfigSaved")) {
|
||||||
requestConfig(); // just consider current config as invalidated
|
requestConfig(); // just consider current config as invalidated
|
||||||
} else if (eventType.endsWith(QLatin1String("ChangeDetected"))) {
|
} else if (eventType.endsWith(QLatin1String("ChangeDetected"))) {
|
||||||
|
@ -1796,7 +1809,7 @@ void SyncthingConnection::readStartingEvent(const QJsonObject &eventData)
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJsonObject &eventData)
|
void SyncthingConnection::readStatusChangedEvent(SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
const QString dir(eventData.value(QLatin1String("folder")).toString());
|
const QString dir(eventData.value(QLatin1String("folder")).toString());
|
||||||
if (dir.isEmpty()) {
|
if (dir.isEmpty()) {
|
||||||
|
@ -1815,7 +1828,7 @@ void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJson
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign new status
|
// assign new status
|
||||||
bool statusChanged = dirInfo->assignStatus(eventData.value(QLatin1String("to")).toString(), eventTime);
|
bool statusChanged = dirInfo->assignStatus(eventData.value(QLatin1String("to")).toString(), eventId, eventTime);
|
||||||
if (dirInfo->status == SyncthingDirStatus::OutOfSync) {
|
if (dirInfo->status == SyncthingDirStatus::OutOfSync) {
|
||||||
const QString errorMessage(eventData.value(QLatin1String("error")).toString());
|
const QString errorMessage(eventData.value(QLatin1String("error")).toString());
|
||||||
if (!errorMessage.isEmpty()) {
|
if (!errorMessage.isEmpty()) {
|
||||||
|
@ -1837,9 +1850,8 @@ void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJson
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readDownloadProgressEvent(DateTime eventTime, const QJsonObject &eventData)
|
void SyncthingConnection::readDownloadProgressEvent(const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
CPP_UTILITIES_UNUSED(eventTime)
|
|
||||||
for (SyncthingDir &dirInfo : m_dirs) {
|
for (SyncthingDir &dirInfo : m_dirs) {
|
||||||
// disappearing implies that the download has been finished so just wipe old entries
|
// disappearing implies that the download has been finished so just wipe old entries
|
||||||
dirInfo.downloadingItems.clear();
|
dirInfo.downloadingItems.clear();
|
||||||
|
@ -1877,7 +1889,7 @@ void SyncthingConnection::readDownloadProgressEvent(DateTime eventTime, const QJ
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readDirEvent(DateTime eventTime, const QString &eventType, const QJsonObject &eventData)
|
void SyncthingConnection::readDirEvent(SyncthingEventId eventId, DateTime eventTime, const QString &eventType, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
// read dir ID
|
// read dir ID
|
||||||
const auto dirId([&eventData] {
|
const auto dirId([&eventData] {
|
||||||
|
@ -1890,7 +1902,7 @@ void SyncthingConnection::readDirEvent(DateTime eventTime, const QString &eventT
|
||||||
if (dirId.isEmpty()) {
|
if (dirId.isEmpty()) {
|
||||||
// handle events which don't necessarily require a corresponding dir info
|
// handle events which don't necessarily require a corresponding dir info
|
||||||
if (eventType == QLatin1String("FolderCompletion")) {
|
if (eventType == QLatin1String("FolderCompletion")) {
|
||||||
readFolderCompletion(eventTime, eventData, dirId, nullptr, -1);
|
readFolderCompletion(eventId, eventTime, eventData, dirId, nullptr, -1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1910,11 +1922,11 @@ void SyncthingConnection::readDirEvent(DateTime eventTime, const QString &eventT
|
||||||
|
|
||||||
// distinguish specific events
|
// distinguish specific events
|
||||||
if (eventType == QLatin1String("FolderErrors")) {
|
if (eventType == QLatin1String("FolderErrors")) {
|
||||||
readFolderErrors(eventTime, eventData, *dirInfo, index);
|
readFolderErrors(eventId, eventTime, eventData, *dirInfo, index);
|
||||||
} else if (eventType == QLatin1String("FolderSummary")) {
|
} else if (eventType == QLatin1String("FolderSummary")) {
|
||||||
readDirSummary(eventTime, eventData.value(QLatin1String("summary")).toObject(), *dirInfo, index);
|
readDirSummary(eventId, eventTime, eventData.value(QLatin1String("summary")).toObject(), *dirInfo, index);
|
||||||
} else if (eventType == QLatin1String("FolderCompletion") && dirInfo->lastStatisticsUpdate < eventTime) {
|
} else if (eventType == QLatin1String("FolderCompletion") && dirInfo->lastStatisticsUpdateEvent <= eventId) {
|
||||||
readFolderCompletion(eventTime, eventData, dirId, dirInfo, index);
|
readFolderCompletion(eventId, eventTime, eventData, dirId, dirInfo, index);
|
||||||
} else if (eventType == QLatin1String("FolderScanProgress")) {
|
} else if (eventType == QLatin1String("FolderScanProgress")) {
|
||||||
const double current = eventData.value(QLatin1String("current")).toDouble(0);
|
const double current = eventData.value(QLatin1String("current")).toDouble(0);
|
||||||
const double total = eventData.value(QLatin1String("total")).toDouble(0);
|
const double total = eventData.value(QLatin1String("total")).toDouble(0);
|
||||||
|
@ -1922,7 +1934,7 @@ void SyncthingConnection::readDirEvent(DateTime eventTime, const QString &eventT
|
||||||
if (current > 0 && total > 0) {
|
if (current > 0 && total > 0) {
|
||||||
dirInfo->scanningPercentage = static_cast<int>(current * 100 / total);
|
dirInfo->scanningPercentage = static_cast<int>(current * 100 / total);
|
||||||
dirInfo->scanningRate = rate;
|
dirInfo->scanningRate = rate;
|
||||||
dirInfo->assignStatus(SyncthingDirStatus::Scanning, eventTime); // ensure state is scanning
|
dirInfo->assignStatus(SyncthingDirStatus::Scanning, eventId, eventTime); // ensure state is scanning
|
||||||
emit dirStatusChanged(*dirInfo, index);
|
emit dirStatusChanged(*dirInfo, index);
|
||||||
}
|
}
|
||||||
} else if (eventType == QLatin1String("FolderPaused")) {
|
} else if (eventType == QLatin1String("FolderPaused")) {
|
||||||
|
@ -1941,10 +1953,10 @@ void SyncthingConnection::readDirEvent(DateTime eventTime, const QString &eventT
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readDeviceEvent(DateTime eventTime, const QString &eventType, const QJsonObject &eventData)
|
void SyncthingConnection::readDeviceEvent(SyncthingEventId eventId, DateTime eventTime, const QString &eventType, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
// ignore device events happened before the last connections update
|
// ignore device events happened before the last connections update
|
||||||
if (eventTime.isNull() && m_lastConnectionsUpdate.isNull() && eventTime < m_lastConnectionsUpdate) {
|
if (eventId < m_lastConnectionsUpdateEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const QString dev(eventData.value(QLatin1String("device")).toString());
|
const QString dev(eventData.value(QLatin1String("device")).toString());
|
||||||
|
@ -2004,8 +2016,9 @@ void SyncthingConnection::readDeviceEvent(DateTime eventTime, const QString &eve
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
* \todo Implement this.
|
* \todo Implement this.
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readItemStarted(DateTime eventTime, const QJsonObject &eventData)
|
void SyncthingConnection::readItemStarted(SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
|
CPP_UTILITIES_UNUSED(eventId)
|
||||||
CPP_UTILITIES_UNUSED(eventTime)
|
CPP_UTILITIES_UNUSED(eventTime)
|
||||||
CPP_UTILITIES_UNUSED(eventData)
|
CPP_UTILITIES_UNUSED(eventData)
|
||||||
}
|
}
|
||||||
|
@ -2013,7 +2026,7 @@ void SyncthingConnection::readItemStarted(DateTime eventTime, const QJsonObject
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readItemFinished(DateTime eventTime, const QJsonObject &eventData)
|
void SyncthingConnection::readItemFinished(SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
auto *const dirInfo = findDirInfo(QLatin1String("folder"), eventData, &index);
|
auto *const dirInfo = findDirInfo(QLatin1String("folder"), eventData, &index);
|
||||||
|
@ -2046,11 +2059,13 @@ void SyncthingConnection::readItemFinished(DateTime eventTime, const QJsonObject
|
||||||
}
|
}
|
||||||
|
|
||||||
// update last file
|
// update last file
|
||||||
if (dirInfo->lastFileTime.isNull() || eventTime < dirInfo->lastFileTime) {
|
if (dirInfo->lastFileTime.isNull() || eventId >= dirInfo->lastFileEvent) {
|
||||||
|
dirInfo->lastFileEvent = eventId;
|
||||||
dirInfo->lastFileTime = eventTime;
|
dirInfo->lastFileTime = eventTime;
|
||||||
dirInfo->lastFileName = item;
|
dirInfo->lastFileName = item;
|
||||||
dirInfo->lastFileDeleted = (eventData.value(QLatin1String("action")) != QLatin1String("delete"));
|
dirInfo->lastFileDeleted = (eventData.value(QLatin1String("action")) != QLatin1String("delete"));
|
||||||
if (eventTime > m_lastFileTime) {
|
if (eventId >= m_lastFileEvent) {
|
||||||
|
m_lastFileEvent = eventId;
|
||||||
m_lastFileTime = dirInfo->lastFileTime;
|
m_lastFileTime = dirInfo->lastFileTime;
|
||||||
m_lastFileName = dirInfo->lastFileName;
|
m_lastFileName = dirInfo->lastFileName;
|
||||||
m_lastFileDeleted = dirInfo->lastFileDeleted;
|
m_lastFileDeleted = dirInfo->lastFileDeleted;
|
||||||
|
@ -2062,10 +2077,11 @@ void SyncthingConnection::readItemFinished(DateTime eventTime, const QJsonObject
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents() and requestDirPullErrors().
|
* \brief Reads results of requestEvents() and requestDirPullErrors().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readFolderErrors(DateTime eventTime, const QJsonObject &eventData, SyncthingDir &dirInfo, int index)
|
void SyncthingConnection::readFolderErrors(
|
||||||
|
SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData, SyncthingDir &dirInfo, int index)
|
||||||
{
|
{
|
||||||
// ignore errors occurred before the last time the directory was in "sync" state (Syncthing re-emits recurring errors)
|
// ignore errors occurred before the last time the directory was in "sync" state (Syncthing re-emits recurring errors)
|
||||||
if (dirInfo.lastSyncStarted > eventTime) {
|
if (dirInfo.lastSyncStartedEvent > eventId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2090,7 +2106,7 @@ void SyncthingConnection::readFolderErrors(DateTime eventTime, const QJsonObject
|
||||||
|
|
||||||
// ensure the directory is considered out-of-sync
|
// ensure the directory is considered out-of-sync
|
||||||
if (dirInfo.pullErrorCount) {
|
if (dirInfo.pullErrorCount) {
|
||||||
dirInfo.assignStatus(SyncthingDirStatus::OutOfSync, eventTime);
|
dirInfo.assignStatus(SyncthingDirStatus::OutOfSync, eventId, eventTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dirStatusChanged(dirInfo, index);
|
emit dirStatusChanged(dirInfo, index);
|
||||||
|
@ -2100,44 +2116,46 @@ void SyncthingConnection::readFolderErrors(DateTime eventTime, const QJsonObject
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readFolderCompletion(
|
void SyncthingConnection::readFolderCompletion(
|
||||||
DateTime eventTime, const QJsonObject &eventData, const QString &dirId, SyncthingDir *dirInfo, int dirIndex)
|
SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData, const QString &dirId, SyncthingDir *dirInfo, int dirIndex)
|
||||||
{
|
{
|
||||||
const auto devId = eventData.value(QLatin1String("device")).toString();
|
const auto devId = eventData.value(QLatin1String("device")).toString();
|
||||||
int devIndex;
|
int devIndex;
|
||||||
auto *const devInfo = findDevInfo(devId, devIndex);
|
auto *const devInfo = findDevInfo(devId, devIndex);
|
||||||
readFolderCompletion(eventTime, eventData, devId, devInfo, devIndex, dirId, dirInfo, dirIndex);
|
readFolderCompletion(eventId, eventTime, eventData, devId, devInfo, devIndex, dirId, dirInfo, dirIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readFolderCompletion(DateTime eventTime, const QJsonObject &eventData, const QString &devId, SyncthingDev *devInfo,
|
void SyncthingConnection::readFolderCompletion(SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData, const QString &devId,
|
||||||
int devIndex, const QString &dirId, SyncthingDir *dirInfo, int dirIndex)
|
SyncthingDev *devInfo, int devIndex, const QString &dirId, SyncthingDir *dirInfo, int dirIndex)
|
||||||
{
|
{
|
||||||
if (devInfo && !devId.isEmpty() && devId != myId()) {
|
if (devInfo && !devId.isEmpty() && devId != myId()) {
|
||||||
readRemoteFolderCompletion(eventTime, eventData, devId, devInfo, devIndex, dirId, dirInfo, dirIndex);
|
readRemoteFolderCompletion(eventTime, eventData, devId, devInfo, devIndex, dirId, dirInfo, dirIndex);
|
||||||
} else if (dirInfo) {
|
} else if (dirInfo) {
|
||||||
readLocalFolderCompletion(eventTime, eventData, *dirInfo, dirIndex);
|
readLocalFolderCompletion(eventId, eventTime, eventData, *dirInfo, dirIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readLocalFolderCompletion(DateTime eventTime, const QJsonObject &eventData, SyncthingDir &dirInfo, int index)
|
void SyncthingConnection::readLocalFolderCompletion(
|
||||||
|
SyncthingEventId eventId, DateTime eventTime, const QJsonObject &eventData, SyncthingDir &dirInfo, int index)
|
||||||
{
|
{
|
||||||
auto &neededStats(dirInfo.neededStats);
|
auto &neededStats(dirInfo.neededStats);
|
||||||
auto &globalStats(dirInfo.globalStats);
|
auto &globalStats(dirInfo.globalStats);
|
||||||
// backup previous statistics -> if there's no difference after all, don't emit completed event
|
// backup previous statistics -> if there's no difference after all, don't emit completed event
|
||||||
const auto previouslyUpdated(!dirInfo.lastStatisticsUpdate.isNull());
|
const auto previouslyUpdated = !dirInfo.lastStatisticsUpdateTime.isNull();
|
||||||
const auto previouslyNeeded(neededStats);
|
const auto previouslyNeeded = neededStats;
|
||||||
const auto previouslyGlobal(globalStats);
|
const auto previouslyGlobal = globalStats;
|
||||||
// read values from event data
|
// read values from event data
|
||||||
globalStats.bytes = jsonValueToInt(eventData.value(QLatin1String("globalBytes")), static_cast<double>(globalStats.bytes));
|
globalStats.bytes = jsonValueToInt(eventData.value(QLatin1String("globalBytes")), static_cast<double>(globalStats.bytes));
|
||||||
neededStats.bytes = jsonValueToInt(eventData.value(QLatin1String("needBytes")), static_cast<double>(neededStats.bytes));
|
neededStats.bytes = jsonValueToInt(eventData.value(QLatin1String("needBytes")), static_cast<double>(neededStats.bytes));
|
||||||
neededStats.deletes = jsonValueToInt(eventData.value(QLatin1String("needDeletes")), static_cast<double>(neededStats.deletes));
|
neededStats.deletes = jsonValueToInt(eventData.value(QLatin1String("needDeletes")), static_cast<double>(neededStats.deletes));
|
||||||
neededStats.deletes = jsonValueToInt(eventData.value(QLatin1String("needItems")), static_cast<double>(neededStats.files));
|
neededStats.deletes = jsonValueToInt(eventData.value(QLatin1String("needItems")), static_cast<double>(neededStats.files));
|
||||||
dirInfo.lastStatisticsUpdate = eventTime;
|
dirInfo.lastStatisticsUpdateEvent = eventId;
|
||||||
|
dirInfo.lastStatisticsUpdateTime = eventTime;
|
||||||
dirInfo.completionPercentage = globalStats.bytes ? static_cast<int>((globalStats.bytes - neededStats.bytes) * 100 / globalStats.bytes) : 100;
|
dirInfo.completionPercentage = globalStats.bytes ? static_cast<int>((globalStats.bytes - neededStats.bytes) * 100 / globalStats.bytes) : 100;
|
||||||
emit dirStatusChanged(dirInfo, index);
|
emit dirStatusChanged(dirInfo, index);
|
||||||
if (neededStats.isNull() && previouslyUpdated && (neededStats != previouslyNeeded || globalStats != previouslyGlobal)
|
if (neededStats.isNull() && previouslyUpdated && (neededStats != previouslyNeeded || globalStats != previouslyGlobal)
|
||||||
|
@ -2154,7 +2172,7 @@ void SyncthingConnection::readRemoteFolderCompletion(DateTime eventTime, const Q
|
||||||
{
|
{
|
||||||
// make new completion
|
// make new completion
|
||||||
auto completion = SyncthingCompletion();
|
auto completion = SyncthingCompletion();
|
||||||
auto &needed(completion.needed);
|
auto &needed = completion.needed;
|
||||||
completion.lastUpdate = eventTime;
|
completion.lastUpdate = eventTime;
|
||||||
completion.percentage = eventData.value(QLatin1String("completion")).toDouble();
|
completion.percentage = eventData.value(QLatin1String("completion")).toDouble();
|
||||||
completion.globalBytes = jsonValueToInt(eventData.value(QLatin1String("globalBytes")));
|
completion.globalBytes = jsonValueToInt(eventData.value(QLatin1String("globalBytes")));
|
||||||
|
@ -2201,7 +2219,7 @@ void SyncthingConnection::readRemoteFolderCompletion(const SyncthingCompletion &
|
||||||
/*!
|
/*!
|
||||||
* \brief Reads results of requestEvents().
|
* \brief Reads results of requestEvents().
|
||||||
*/
|
*/
|
||||||
void SyncthingConnection::readRemoteIndexUpdated(DateTime eventTime, const QJsonObject &eventData)
|
void SyncthingConnection::readRemoteIndexUpdated(SyncthingEventId eventId, const QJsonObject &eventData)
|
||||||
{
|
{
|
||||||
// ignore those events if we're not updating completion automatically
|
// ignore those events if we're not updating completion automatically
|
||||||
if (!m_requestCompletion && !m_keepPolling) {
|
if (!m_requestCompletion && !m_keepPolling) {
|
||||||
|
@ -2234,20 +2252,15 @@ void SyncthingConnection::readRemoteIndexUpdated(DateTime eventTime, const QJson
|
||||||
// might meddle with that.
|
// might meddle with that.
|
||||||
auto *const completionFromDirInfo = dirInfo ? &dirInfo->completionByDevice[devId] : nullptr;
|
auto *const completionFromDirInfo = dirInfo ? &dirInfo->completionByDevice[devId] : nullptr;
|
||||||
auto *const completionFromDevInfo = devInfo ? &devInfo->completionByDir[dirId] : nullptr;
|
auto *const completionFromDevInfo = devInfo ? &devInfo->completionByDir[dirId] : nullptr;
|
||||||
if ((completionFromDirInfo && completionFromDirInfo->requested) || (completionFromDevInfo && completionFromDevInfo->requested)) {
|
if ((completionFromDirInfo && completionFromDirInfo->requestedForEventId >= eventId)
|
||||||
return;
|
|| (completionFromDevInfo && completionFromDevInfo->requestedForEventId >= eventId)) {
|
||||||
}
|
|
||||||
const auto lastUpdate = completionFromDirInfo && completionFromDevInfo
|
|
||||||
? min(completionFromDirInfo->lastUpdate, completionFromDevInfo->lastUpdate)
|
|
||||||
: (completionFromDirInfo ? completionFromDirInfo->lastUpdate : completionFromDevInfo->lastUpdate);
|
|
||||||
if (lastUpdate >= eventTime) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (completionFromDirInfo) {
|
if (completionFromDirInfo) {
|
||||||
completionFromDirInfo->requested = true;
|
completionFromDirInfo->requestedForEventId = eventId;
|
||||||
}
|
}
|
||||||
if (completionFromDevInfo) {
|
if (completionFromDevInfo) {
|
||||||
completionFromDevInfo->requested = true;
|
completionFromDevInfo->requestedForEventId = eventId;
|
||||||
}
|
}
|
||||||
if (devInfo && dirInfo && !devInfo->paused && !dirInfo->paused) {
|
if (devInfo && dirInfo && !devInfo->paused && !dirInfo->paused) {
|
||||||
requestCompletion(devId, dirId);
|
requestCompletion(devId, dirId);
|
||||||
|
|
|
@ -52,27 +52,30 @@ QString dirTypeString(SyncthingDirType dirType)
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyncthingDir::checkWhetherStatusUpdateRelevant(DateTime time)
|
bool SyncthingDir::checkWhetherStatusUpdateRelevant(SyncthingEventId eventId, DateTime time)
|
||||||
{
|
{
|
||||||
// ignore old updates
|
// ignore old updates
|
||||||
if (lastStatusUpdate > time) {
|
if (lastStatusUpdateEvent > eventId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lastStatusUpdate = time;
|
lastStatusUpdateEvent = eventId;
|
||||||
|
lastStatusUpdateTime = time;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyncthingDir::finalizeStatusUpdate(SyncthingDirStatus newStatus, DateTime time)
|
bool SyncthingDir::finalizeStatusUpdate(SyncthingDirStatus newStatus, SyncthingEventId eventId, DateTime time)
|
||||||
{
|
{
|
||||||
// handle obsoletion of out-of-sync items: no FolderErrors are accepted older than the last "sync" state are accepted
|
// handle obsoletion of out-of-sync items: no FolderErrors are accepted older than the last "sync" state are accepted
|
||||||
if (newStatus == SyncthingDirStatus::PreparingToSync || newStatus == SyncthingDirStatus::Synchronizing) {
|
if (newStatus == SyncthingDirStatus::PreparingToSync || newStatus == SyncthingDirStatus::Synchronizing) {
|
||||||
// update time of last "sync" state and obsolete currently assigned errors
|
// update time of last "sync" state and obsolete currently assigned errors
|
||||||
lastSyncStarted = time; // used internally and not displayed, hence keep it GMT
|
lastSyncStartedEvent = eventId;
|
||||||
|
lastSyncStartedTime = time; // used internally and not displayed, hence keep it GMT
|
||||||
itemErrors.clear();
|
itemErrors.clear();
|
||||||
pullErrorCount = 0;
|
pullErrorCount = 0;
|
||||||
} else if (lastSyncStarted.isNull() && newStatus != SyncthingDirStatus::OutOfSync) {
|
} else if (lastSyncStartedTime.isNull() && newStatus != SyncthingDirStatus::OutOfSync) {
|
||||||
// prevent adding new errors from "before the first status" if the time of the last "sync" state is unknown
|
// prevent adding new errors from "before the first status" if the time of the last "sync" state is unknown
|
||||||
lastSyncStarted = time;
|
lastSyncStartedEvent = eventId;
|
||||||
|
lastSyncStartedTime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear global error if not out-of-sync anymore
|
// clear global error if not out-of-sync anymore
|
||||||
|
@ -105,9 +108,9 @@ bool SyncthingDir::finalizeStatusUpdate(SyncthingDirStatus newStatus, DateTime t
|
||||||
* \brief Assigns the status from the specified status string.
|
* \brief Assigns the status from the specified status string.
|
||||||
* \returns Returns whether the status has actually changed.
|
* \returns Returns whether the status has actually changed.
|
||||||
*/
|
*/
|
||||||
bool SyncthingDir::assignStatus(const QString &statusStr, CppUtilities::DateTime time)
|
bool SyncthingDir::assignStatus(const QString &statusStr, SyncthingEventId eventId, CppUtilities::DateTime time)
|
||||||
{
|
{
|
||||||
if (!checkWhetherStatusUpdateRelevant(time)) {
|
if (!checkWhetherStatusUpdateRelevant(eventId, time)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +150,7 @@ bool SyncthingDir::assignStatus(const QString &statusStr, CppUtilities::DateTime
|
||||||
|
|
||||||
rawStatus = statusStr;
|
rawStatus = statusStr;
|
||||||
|
|
||||||
return finalizeStatusUpdate(newStatus, time);
|
return finalizeStatusUpdate(newStatus, eventId, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SyncthingDir::assignDirType(const QString &dirTypeStr)
|
bool SyncthingDir::assignDirType(const QString &dirTypeStr)
|
||||||
|
|
|
@ -126,8 +126,8 @@ constexpr bool SyncthingStatistics::operator!=(const SyncthingStatistics &other)
|
||||||
|
|
||||||
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingDir {
|
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingDir {
|
||||||
explicit SyncthingDir(const QString &id = QString(), const QString &label = QString(), const QString &path = QString());
|
explicit SyncthingDir(const QString &id = QString(), const QString &label = QString(), const QString &path = QString());
|
||||||
bool assignStatus(const QString &statusStr, CppUtilities::DateTime time);
|
bool assignStatus(const QString &statusStr, SyncthingEventId eventId, CppUtilities::DateTime time);
|
||||||
bool assignStatus(SyncthingDirStatus newStatus, CppUtilities::DateTime time);
|
bool assignStatus(SyncthingDirStatus newStatus, SyncthingEventId eventId, CppUtilities::DateTime time);
|
||||||
bool assignDirType(const QString &dirType);
|
bool assignDirType(const QString &dirType);
|
||||||
const QString &displayName() const;
|
const QString &displayName() const;
|
||||||
QString statusString() const;
|
QString statusString() const;
|
||||||
|
@ -146,8 +146,10 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingDir {
|
||||||
int rescanInterval = 0;
|
int rescanInterval = 0;
|
||||||
int minDiskFreePercentage = 0;
|
int minDiskFreePercentage = 0;
|
||||||
SyncthingDirStatus status = SyncthingDirStatus::Unknown;
|
SyncthingDirStatus status = SyncthingDirStatus::Unknown;
|
||||||
CppUtilities::DateTime lastStatusUpdate;
|
SyncthingEventId lastStatusUpdateEvent = 0;
|
||||||
CppUtilities::DateTime lastSyncStarted;
|
CppUtilities::DateTime lastStatusUpdateTime;
|
||||||
|
SyncthingEventId lastSyncStartedEvent = 0;
|
||||||
|
CppUtilities::DateTime lastSyncStartedTime;
|
||||||
int completionPercentage = 0;
|
int completionPercentage = 0;
|
||||||
int scanningPercentage = 0;
|
int scanningPercentage = 0;
|
||||||
double scanningRate = 0;
|
double scanningRate = 0;
|
||||||
|
@ -158,8 +160,10 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingDir {
|
||||||
std::vector<SyncthingItemError> itemErrors;
|
std::vector<SyncthingItemError> itemErrors;
|
||||||
std::vector<SyncthingFileChange> recentChanges;
|
std::vector<SyncthingFileChange> recentChanges;
|
||||||
SyncthingStatistics globalStats, localStats, neededStats;
|
SyncthingStatistics globalStats, localStats, neededStats;
|
||||||
CppUtilities::DateTime lastStatisticsUpdate;
|
SyncthingEventId lastStatisticsUpdateEvent = 0;
|
||||||
|
CppUtilities::DateTime lastStatisticsUpdateTime;
|
||||||
CppUtilities::DateTime lastScanTime;
|
CppUtilities::DateTime lastScanTime;
|
||||||
|
SyncthingEventId lastFileEvent;
|
||||||
CppUtilities::DateTime lastFileTime;
|
CppUtilities::DateTime lastFileTime;
|
||||||
QString lastFileName;
|
QString lastFileName;
|
||||||
std::vector<SyncthingItemDownloadProgress> downloadingItems;
|
std::vector<SyncthingItemDownloadProgress> downloadingItems;
|
||||||
|
@ -177,8 +181,8 @@ struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingDir {
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool checkWhetherStatusUpdateRelevant(CppUtilities::DateTime time);
|
bool checkWhetherStatusUpdateRelevant(SyncthingEventId eventId, CppUtilities::DateTime time);
|
||||||
bool finalizeStatusUpdate(SyncthingDirStatus newStatus, CppUtilities::DateTime time);
|
bool finalizeStatusUpdate(SyncthingDirStatus newStatus, SyncthingEventId eventId, CppUtilities::DateTime time);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline SyncthingDir::SyncthingDir(const QString &id, const QString &label, const QString &path)
|
inline SyncthingDir::SyncthingDir(const QString &id, const QString &label, const QString &path)
|
||||||
|
@ -208,13 +212,13 @@ inline bool SyncthingDir::isUnshared() const
|
||||||
return deviceIds.empty() && (status == SyncthingDirStatus::Idle || status == SyncthingDirStatus::Unknown);
|
return deviceIds.empty() && (status == SyncthingDirStatus::Idle || status == SyncthingDirStatus::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool SyncthingDir::assignStatus(SyncthingDirStatus newStatus, CppUtilities::DateTime time)
|
inline bool SyncthingDir::assignStatus(SyncthingDirStatus newStatus, SyncthingEventId eventId, CppUtilities::DateTime time)
|
||||||
{
|
{
|
||||||
if (!checkWhetherStatusUpdateRelevant(time)) {
|
if (!checkWhetherStatusUpdateRelevant(eventId, time)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rawStatus.clear();
|
rawStatus.clear();
|
||||||
return finalizeStatusUpdate(newStatus, time);
|
return finalizeStatusUpdate(newStatus, eventId, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingOverallDirStatistics {
|
struct LIB_SYNCTHING_CONNECTOR_EXPORT SyncthingOverallDirStatistics {
|
||||||
|
|
|
@ -199,74 +199,76 @@ void MiscTests::testSyncthingDir()
|
||||||
SyncthingDir dir;
|
SyncthingDir dir;
|
||||||
dir.status = SyncthingDirStatus::Unknown;
|
dir.status = SyncthingDirStatus::Unknown;
|
||||||
|
|
||||||
DateTime updateTime(DateTime::fromDate(2005, 2, 3));
|
auto updateEvent = static_cast<SyncthingEventId>(42);
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime));
|
auto updateTime = DateTime(DateTime::fromDate(2005, 2, 3));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("unshared"), dir.statusString());
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateEvent, updateTime));
|
||||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("status updated", QStringLiteral("unshared"), dir.statusString());
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("event updated", updateEvent, dir.lastStatusUpdateEvent);
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("time updated", updateTime, dir.lastStatusUpdateTime);
|
||||||
|
|
||||||
dir.deviceIds << QStringLiteral("dev1") << QStringLiteral("dev2");
|
dir.deviceIds << QStringLiteral("dev1") << QStringLiteral("dev2");
|
||||||
|
|
||||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Scanning, DateTime::fromDate(2003, 6, 7)));
|
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Scanning, updateEvent - 1, updateTime + TimeSpan::fromDays(1.0)));
|
||||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("status not updated", QStringLiteral("idle"), dir.statusString());
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("event not updated", updateEvent, dir.lastStatusUpdateEvent);
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("time not updated", updateTime, dir.lastStatusUpdateTime);
|
||||||
|
|
||||||
const DateTime lastScanTime(DateTime::now());
|
const auto lastScanTime = DateTime(DateTime::now());
|
||||||
updateTime += TimeSpan::fromSeconds(5);
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::WaitingToScan, updateEvent += 1, updateTime += TimeSpan::fromSeconds(5)));
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::WaitingToScan, updateTime));
|
|
||||||
CPPUNIT_ASSERT(dir.lastScanTime.isNull());
|
CPPUNIT_ASSERT(dir.lastScanTime.isNull());
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("waiting to scan"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("waiting to scan"), dir.statusString());
|
||||||
updateTime += TimeSpan::fromSeconds(5);
|
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Scanning, updateTime));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Scanning, updateEvent += 1, updateTime += TimeSpan::fromSeconds(5)));
|
||||||
CPPUNIT_ASSERT(dir.lastScanTime.isNull());
|
CPPUNIT_ASSERT(dir.lastScanTime.isNull());
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("scanning"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("scanning"), dir.statusString());
|
||||||
|
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromSeconds(2)));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateEvent += 1, updateTime += TimeSpan::fromSeconds(2)));
|
||||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastStatusUpdate);
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("event updated", updateEvent, dir.lastStatusUpdateEvent);
|
||||||
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("time updated", updateTime, dir.lastStatusUpdateTime);
|
||||||
CPPUNIT_ASSERT(dir.lastScanTime >= lastScanTime);
|
CPPUNIT_ASSERT(dir.lastScanTime >= lastScanTime);
|
||||||
|
|
||||||
dir.status = SyncthingDirStatus::Unknown;
|
dir.status = SyncthingDirStatus::Unknown;
|
||||||
dir.lastSyncStarted = DateTime(1);
|
dir.lastSyncStartedTime = DateTime(1);
|
||||||
dir.itemErrors.emplace_back(QStringLiteral("message"), QStringLiteral("path"));
|
dir.itemErrors.emplace_back(QStringLiteral("message"), QStringLiteral("path"));
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
||||||
CPPUNIT_ASSERT_EQUAL(1_st, dir.itemErrors.size());
|
CPPUNIT_ASSERT_EQUAL(1_st, dir.itemErrors.size());
|
||||||
dir.lastSyncStarted = DateTime();
|
dir.lastSyncStartedTime = DateTime();
|
||||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStarted);
|
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStartedTime);
|
||||||
const auto lastSyncTime(updateTime += TimeSpan::fromMinutes(1.5));
|
const auto lastSyncTime = updateTime += TimeSpan::fromMinutes(1.5);
|
||||||
dir.itemErrors.emplace_back();
|
dir.itemErrors.emplace_back();
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Synchronizing, lastSyncTime));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Synchronizing, updateEvent += 1, lastSyncTime));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("synchronizing"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("synchronizing"), dir.statusString());
|
||||||
CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size());
|
CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size());
|
||||||
CPPUNIT_ASSERT_EQUAL(lastSyncTime, dir.lastSyncStarted);
|
CPPUNIT_ASSERT_EQUAL(lastSyncTime, dir.lastSyncStartedTime);
|
||||||
const auto lastSyncTime2(updateTime += TimeSpan::fromMinutes(2.0));
|
const auto lastSyncTime2 = updateTime += TimeSpan::fromMinutes(2.0);
|
||||||
dir.itemErrors.emplace_back();
|
dir.itemErrors.emplace_back();
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::PreparingToSync, lastSyncTime2));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::PreparingToSync, updateEvent += 1, lastSyncTime2));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("preparing to sync"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("preparing to sync"), dir.statusString());
|
||||||
CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size());
|
CPPUNIT_ASSERT_EQUAL(0_st, dir.itemErrors.size());
|
||||||
CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStarted);
|
CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStartedTime);
|
||||||
|
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(dir.assignStatus(SyncthingDirStatus::Idle, updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStarted);
|
CPPUNIT_ASSERT_EQUAL(lastSyncTime2, dir.lastSyncStartedTime);
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("syncing"), updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("syncing"), updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStarted);
|
CPPUNIT_ASSERT_EQUAL(updateTime, dir.lastSyncStartedTime);
|
||||||
|
|
||||||
dir.itemErrors.clear();
|
dir.itemErrors.clear();
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("error"), updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("error"), updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("out of sync"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("out of sync"), dir.statusString());
|
||||||
|
|
||||||
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("wrong status"), updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(dir.assignStatus(QStringLiteral("wrong status"), updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong status treated as idle", QStringLiteral("idle"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("wrong status treated as idle", QStringLiteral("idle"), dir.statusString());
|
||||||
|
|
||||||
CPPUNIT_ASSERT_MESSAGE("older status discarded", !dir.assignStatus(QStringLiteral("scanning"), updateTime - TimeSpan::fromSeconds(1)));
|
CPPUNIT_ASSERT_MESSAGE("older status discarded", !dir.assignStatus(QStringLiteral("scanning"), updateEvent - 1, updateTime));
|
||||||
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL(QStringLiteral("idle"), dir.statusString());
|
||||||
|
|
||||||
dir.deviceIds.clear();
|
dir.deviceIds.clear();
|
||||||
CPPUNIT_ASSERT(!dir.assignStatus(QStringLiteral("idle"), updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(!dir.assignStatus(QStringLiteral("idle"), updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when no devs present", QStringLiteral("unshared"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when no devs present", QStringLiteral("unshared"), dir.statusString());
|
||||||
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateTime += TimeSpan::fromMinutes(1.5)));
|
CPPUNIT_ASSERT(!dir.assignStatus(SyncthingDirStatus::Idle, updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when no devs present", QStringLiteral("unshared"), dir.statusString());
|
CPPUNIT_ASSERT_EQUAL_MESSAGE("dir considered unshared when no devs present", QStringLiteral("unshared"), dir.statusString());
|
||||||
|
CPPUNIT_ASSERT_MESSAGE("same status again not considered an update",
|
||||||
updateTime += TimeSpan::fromMinutes(1.5);
|
!dir.assignStatus(QStringLiteral("idle"), updateEvent += 1, updateTime += TimeSpan::fromMinutes(1.5)));
|
||||||
CPPUNIT_ASSERT_MESSAGE("same status again not considered an update", !dir.assignStatus(QStringLiteral("idle"), updateTime));
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue