Fix crashes on database save

* Add saving mutex to database class to prevent re-entrant saving
* Prevent saving multiple times to the same file if the database is not marked as modified
* Prevent locking the database while saving. This also prevents closing the application and database tab while saving.
* FileWatcher: only perform async checksum calculations when triggered by timer (prevents random GUI freezes)
* Re-attempt database lock when requested during save operation
* Prevent database tabs from closing before all databases are locked on quit
This commit is contained in:
Jonathan White 2020-03-05 22:59:07 -05:00
parent 6bce5836f9
commit 7ac292e09b
12 changed files with 122 additions and 40 deletions

View file

@ -43,6 +43,11 @@ FileWatcher::FileWatcher(QObject* parent)
m_fileIgnoreDelayTimer.setSingleShot(true);
}
FileWatcher::~FileWatcher()
{
stop();
}
void FileWatcher::start(const QString& filePath, int checksumIntervalSeconds, int checksumSizeKibibytes)
{
stop();
@ -120,8 +125,7 @@ void FileWatcher::checkFileChanged()
// Prevent reentrance
m_ignoreFileChange = true;
// Only trigger the change notice if there is a checksum mismatch
auto checksum = calculateChecksum();
auto checksum = AsyncTask::runAndWaitForFuture([this]() -> QByteArray { return calculateChecksum(); });
if (checksum != m_fileChecksum) {
m_fileChecksum = checksum;
m_fileChangeDelayTimer.start(0);
@ -132,21 +136,19 @@ void FileWatcher::checkFileChanged()
QByteArray FileWatcher::calculateChecksum()
{
return AsyncTask::runAndWaitForFuture([this]() -> QByteArray {
QFile file(m_filePath);
if (file.open(QFile::ReadOnly)) {
QCryptographicHash hash(QCryptographicHash::Sha256);
if (m_fileChecksumSizeBytes > 0) {
hash.addData(file.read(m_fileChecksumSizeBytes));
} else {
hash.addData(&file);
}
return hash.result();
QFile file(m_filePath);
if (file.open(QFile::ReadOnly)) {
QCryptographicHash hash(QCryptographicHash::Sha256);
if (m_fileChecksumSizeBytes > 0) {
hash.addData(file.read(m_fileChecksumSizeBytes));
} else {
hash.addData(&file);
}
// If we fail to open the file return the last known checksum, this
// prevents unnecessary merge requests on intermittent network shares
return m_fileChecksum;
});
return hash.result();
}
// If we fail to open the file return the last known checksum, this
// prevents unnecessary merge requests on intermittent network shares
return m_fileChecksum;
}
BulkFileWatcher::BulkFileWatcher(QObject* parent)