From 36e14157bef5788c8b7d4ee83078f9fbfb6704b0 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Wed, 30 Oct 2019 06:40:56 -0400 Subject: [PATCH] Significantly reduce impact of FileWatcher hashing (#3724) * Fix #3699 Reduce file watch hashing of open database files from every second to every 30 seconds. Additionally, only hash the first 1024 bytes of the database file. This is valid since most of the header and the entire encrypted portion are changed significantly on every save. --- src/core/Database.cpp | 4 ++-- src/core/FileWatcher.cpp | 17 +++++++++++++---- src/core/FileWatcher.h | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 944597f5..eb01f731 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -158,7 +158,7 @@ bool Database::open(const QString& filePath, QSharedPointer m_initialized = true; emit databaseOpened(); - m_fileWatcher->start(canonicalFilePath()); + m_fileWatcher->start(canonicalFilePath(), 30, 1); setEmitModified(true); return true; @@ -234,7 +234,7 @@ bool Database::saveAs(const QString& filePath, QString* error, bool atomic, bool bool ok = performSave(canonicalFilePath, error, atomic, backup); if (ok) { setFilePath(filePath); - m_fileWatcher->start(canonicalFilePath); + m_fileWatcher->start(canonicalFilePath, 30, 1); } else { // Saving failed, don't rewatch file since it does not represent our database markAsModified(); diff --git a/src/core/FileWatcher.cpp b/src/core/FileWatcher.cpp index 1b39e597..82328832 100644 --- a/src/core/FileWatcher.cpp +++ b/src/core/FileWatcher.cpp @@ -42,7 +42,7 @@ FileWatcher::FileWatcher(QObject* parent) m_fileIgnoreDelayTimer.setSingleShot(true); } -void FileWatcher::start(const QString& filePath, int checksumInterval) +void FileWatcher::start(const QString& filePath, int checksumIntervalSeconds, int checksumSizeKibibytes) { stop(); @@ -63,8 +63,14 @@ void FileWatcher::start(const QString& filePath, int checksumInterval) m_fileWatcher.addPath(filePath); m_filePath = filePath; + + // Handle file checksum + m_fileChecksumSizeBytes = checksumSizeKibibytes * 1024; m_fileChecksum = calculateChecksum(); - m_fileChecksumTimer.start(checksumInterval); + if (checksumIntervalSeconds > 0) { + m_fileChecksumTimer.start(checksumIntervalSeconds * 1000); + } + m_ignoreFileChange = false; } @@ -131,9 +137,12 @@ QByteArray FileWatcher::calculateChecksum() QFile file(m_filePath); if (file.open(QFile::ReadOnly)) { QCryptographicHash hash(QCryptographicHash::Sha256); - if (hash.addData(&file)) { - return hash.result(); + if (m_fileChecksumSizeBytes > 0) { + hash.addData(file.read(m_fileChecksumSizeBytes)); + } else { + hash.addData(&file); } + return hash.result(); } return {}; } diff --git a/src/core/FileWatcher.h b/src/core/FileWatcher.h index 3793ae86..fea05fc8 100644 --- a/src/core/FileWatcher.h +++ b/src/core/FileWatcher.h @@ -30,7 +30,7 @@ class FileWatcher : public QObject public: explicit FileWatcher(QObject* parent = nullptr); - void start(const QString& path, int checksumInterval = 1000); + void start(const QString& path, int checksumIntervalSeconds = 0, int checksumSizeKibibytes = -1); void stop(); bool hasSameFileChecksum(); @@ -56,6 +56,7 @@ private: QTimer m_fileChangeDelayTimer; QTimer m_fileIgnoreDelayTimer; QTimer m_fileChecksumTimer; + int m_fileChecksumSizeBytes; bool m_ignoreFileChange; };