diff --git a/src/libsync/clientstatusreporting.cpp b/src/libsync/clientstatusreporting.cpp index 3311141e869e5..bcc20d8fb1bf9 100644 --- a/src/libsync/clientstatusreporting.cpp +++ b/src/libsync/clientstatusreporting.cpp @@ -22,6 +22,7 @@ namespace { constexpr auto lastSentReportTimestamp = "lastClientStatusReportSentTime"; +constexpr auto statusNamesHash = "statusNamesHash"; } namespace OCC @@ -49,7 +50,7 @@ void ClientStatusReporting::init() return; } - for (int i = 0; i < ClientStatusReporting::Count; ++i) { + for (int i = 0; i < ClientStatusReporting::Status::Count; ++i) { const auto statusString = statusStringFromNumber(static_cast(i)); _statusNamesAndHashes[i] = {statusString, SyncJournalDb::getPHash(statusString)}; } @@ -82,6 +83,21 @@ void ClientStatusReporting::init() return; } + // prevent issues in case enum gets changed in future, hash its value and clean the db in case there was a change + QByteArray statusNamesContacenated; + for (int i = 0; i < ClientStatusReporting::Status::Count; ++i) { + statusNamesContacenated += statusStringFromNumber(static_cast(i)); + } + statusNamesContacenated += QByteArray::number(ClientStatusReporting::Status::Count); + const auto statusNamesHashCurrent = QCryptographicHash::hash(statusNamesContacenated, QCryptographicHash::Md5).toHex(); + const auto statusNamesHashFromDb = getStatusNamesHash(); + + if (statusNamesHashCurrent != statusNamesHashFromDb) { + deleteClientStatusReportingRecords(); + setStatusNamesHash(statusNamesHashCurrent); + } + // + _clientStatusReportingSendTimer.setInterval(clientStatusReportingTrySendTimerInterval); connect(&_clientStatusReportingSendTimer, &QTimer::timeout, this, &ClientStatusReporting::sendReportToServer); _clientStatusReportingSendTimer.start(); @@ -257,6 +273,38 @@ qulonglong ClientStatusReporting::getLastSentReportTimestamp() const return query.value(valueIndex).toULongLong(); } +void ClientStatusReporting::setStatusNamesHash(const QByteArray &hash) +{ + QMutexLocker locker(&_mutex); + QSqlQuery query; + const auto prepareResult = query.prepare("INSERT OR REPLACE INTO keyvalue (key, value) VALUES(:key, :value);"); + query.bindValue(":key", statusNamesHash); + query.bindValue(":value", hash); + if (!prepareResult || !query.exec()) { + qCDebug(lcClientStatusReporting) << "Could not set status names hash."; + return; + } +} + +QByteArray ClientStatusReporting::getStatusNamesHash() const +{ + QMutexLocker locker(&_mutex); + QSqlQuery query; + const auto prepareResult = query.prepare("SELECT value FROM keyvalue WHERE key = (:key)"); + query.bindValue(":key", statusNamesHash); + if (!prepareResult || !query.exec()) { + qCDebug(lcClientStatusReporting) << "Could not get status names hash. No such record:" << statusNamesHash; + return 0; + } + if (!query.next()) { + qCDebug(lcClientStatusReporting) << "Could not get status names hash:" << query.lastError().text(); + return 0; + } + + int valueIndex = query.record().indexOf("value"); + return query.value(valueIndex).toByteArray(); +} + QVariantMap ClientStatusReporting::prepareReport() const { const auto records = getClientStatusReportingRecords(); diff --git a/src/libsync/clientstatusreporting.h b/src/libsync/clientstatusreporting.h index 70e232086a72b..2f5ae3018d518 100644 --- a/src/libsync/clientstatusreporting.h +++ b/src/libsync/clientstatusreporting.h @@ -38,19 +38,19 @@ class OWNCLOUDSYNC_EXPORT ClientStatusReporting : public QObject Q_OBJECT public: enum Status { - DownloadError_Cannot_Create_File = 100, - DownloadError_Conflict = 101, - DownloadError_ConflictCaseClash = 102, - DownloadError_ConflictInvalidCharacters = 103, - DownloadError_No_Free_Space = 104, - DownloadError_ServerError = 105, - DownloadError_Virtual_File_Hydration_Failure = 106, - UploadError_Conflict = 107, - UploadError_ConflictInvalidCharacters = 108, - UploadError_No_Free_Space = 109, - UploadError_No_Write_Permissions = 110, - UploadError_ServerError = 111, - Count = UploadError_ServerError + 1, + DownloadError_Cannot_Create_File = 0, + DownloadError_Conflict, + DownloadError_ConflictCaseClash, + DownloadError_ConflictInvalidCharacters, + DownloadError_No_Free_Space, + DownloadError_ServerError, + DownloadError_Virtual_File_Hydration_Failure, + UploadError_Conflict, + UploadError_ConflictInvalidCharacters, + UploadError_No_Free_Space, + UploadError_No_Write_Permissions, + UploadError_ServerError, + Count, }; explicit ClientStatusReporting(Account *account, QObject *parent = nullptr); @@ -65,6 +65,8 @@ class OWNCLOUDSYNC_EXPORT ClientStatusReporting : public QObject [[nodiscard]] bool deleteClientStatusReportingRecords(); void setLastSentReportTimestamp(const qulonglong timestamp); [[nodiscard]] qulonglong getLastSentReportTimestamp() const; + void setStatusNamesHash(const QByteArray &hash); + [[nodiscard]] QByteArray getStatusNamesHash() const; [[nodiscard]] QVariantMap prepareReport() const; void reportToServerSentSuccessfully(); [[nodiscard]] QString makeDbPath() const;