Skip to content

Commit

Permalink
Added background save for config (to work better on ZFS)
Browse files Browse the repository at this point in the history
  • Loading branch information
medo64 committed Dec 11, 2021
1 parent f6d0f03 commit e9de711
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 9 deletions.
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Welcome and thank you for your interest in contributing.

### Compiling Code

Project uses Qt 5 and Qt Creator is the preferred development environment.
Project uses Qt 5.12.8 and Qt Creator is the preferred development environment.

All code is situated in `src` directory.

Expand Down Expand Up @@ -56,7 +56,7 @@ all test cases.
Fixes can be contributed using pull requests. Do note project is under MIT
license and any contribution will inherit the same.

LF line ending is strongly preffered. To have Git check it for you, configure
LF line ending is strongly preferred. To have Git check it for you, configure
`core.whitespace` setting:

git config core.whitespace blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol
Expand All @@ -68,7 +68,7 @@ All textual files should be encoded as UTF-8 without BOM.

For non code files (xml, etc), use the best judgment. Albeit, do note that `tab`
character should be avoided and a number of `space` characters should be used
instead (4 being preffered).
instead (4 being preferred).

Code uses K&R coding style. Please do make sure any contribution follows the
coding style already in use.
Expand Down
63 changes: 58 additions & 5 deletions src/medo/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Config::PortableStatus Config::_isPortable(PortableStatus::Unknown);
bool Config::_immediateSave(true);
Config::ConfigFile* Config::_configFile(nullptr);
Config::ConfigFile* Config::_stateFile(nullptr);
Config::ConfigSaveThread Config::_configSaveThread{};

void Config::reset() {
qDebug().noquote().nospace() << "[Config] reset()";
Expand Down Expand Up @@ -130,7 +131,7 @@ bool Config::immediateSave() {
void Config::setImmediateSave(bool saveImmediately) {
QMutexLocker locker(&_publicAccessMutex);
_immediateSave = saveImmediately;
if (_immediateSave) { save(); } //to ensure any pending writes are cleared
if (_immediateSave) { Config::_configSaveThread.requestSave(); } //to ensure any pending writes are cleared
}


Expand Down Expand Up @@ -630,6 +631,58 @@ void Config::resetStateFile() {
}


Config::ConfigSaveThread::ConfigSaveThread(void) {
this->setObjectName("ConfigSaveThread");
this->start(LowPriority);
}

Config::ConfigSaveThread::~ConfigSaveThread() {
this->requestInterruption();
this->wait();
}

void Config::ConfigSaveThread::requestSave() {
QMutexLocker locker(&_syncRoot);
_saveRequested = true;
}

void Config::ConfigSaveThread::run() {
while (!this->isInterruptionRequested()) {
QMutexLocker locker(&_syncRoot);
bool saveRequested = _saveRequested;
locker.unlock();
if (saveRequested) {
qDebug().noquote().nospace() << "[Config] Background save()";
QElapsedTimer stopwatch; stopwatch.start();
if (Config::getConfigFile()->save()) {
locker.relock();
_saveRequested = false;
locker.unlock();
qDebug().noquote().nospace() << "[Config] Background save() done in " << stopwatch.elapsed() << "ms";
} else {
qDebug().noquote().nospace() << "[Config] Background save() failed in " << stopwatch.elapsed() << "ms";
this->msleep(2500); // give it some time
}
}
this->msleep(250);
}

{ // check once more when exiting
QMutexLocker locker(&_syncRoot);
bool saveRequested = _saveRequested;
locker.unlock();
if (saveRequested) {
qDebug().noquote().nospace() << "[Config] Final background save()";
QElapsedTimer stopwatch; stopwatch.start();
if (Config::getConfigFile()->save()) {
qDebug().noquote().nospace() << "[Config] Final background save() done in " << stopwatch.elapsed() << "ms";
} else {
qDebug().noquote().nospace() << "[Config] Final background save() failed in " << stopwatch.elapsed() << "ms";
}
}
}
}

Config::ConfigFile::ConfigFile(QString filePath) {
QString fileContent;
QString lineEnding = QString();
Expand Down Expand Up @@ -964,7 +1017,7 @@ void Config::ConfigFile::writeOne(QString key, QString value) {
}
}

if (_immediateSave) { save(); }
if (_immediateSave) { Config::_configSaveThread.requestSave(); }
}

void Config::ConfigFile::writeMany(QString key, QStringList values) {
Expand Down Expand Up @@ -1018,7 +1071,7 @@ void Config::ConfigFile::writeMany(QString key, QStringList values) {
}
}

if (_immediateSave) { save(); }
if (_immediateSave) { Config::_configSaveThread.requestSave(); }
}

void Config::ConfigFile::removeMany(QString key) {
Expand All @@ -1031,15 +1084,15 @@ void Config::ConfigFile::removeMany(QString key) {
_lines.removeAt(i);
}
}
if (_immediateSave) { save(); }
if (_immediateSave) { Config::_configSaveThread.requestSave(); }
}

void Config::ConfigFile::removeAll() {
QMutexLocker locker(&_cacheMutex);
_cache.clear(); //invalidate cache

_lines.clear();
if (_immediateSave) { save(); }
if (_immediateSave) { Config::_configSaveThread.requestSave(); }
}


Expand Down
24 changes: 23 additions & 1 deletion src/medo/config.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Josip Medved <[email protected]> * www.medo64.com * MIT License */

// 2021-12-10: Added background save
// 2020-05-25: Using strongly typed enums
// 2020-05-05: Added stateRead/stateWrite for integers, longs, and doubles
// Allowing : and = in key name
Expand All @@ -9,14 +10,15 @@
// 2019-11-01: Fixed readMany implementation
// 2019-11-17: Added stateReadMany and stateWriteMany
// Added option to set paths manually
// 2020-03-15: If QApplication hasn't bee initializesd, assume installed on Linux
// 2020-03-15: If QApplication hasn't been initialized, assume installed on Linux

#pragma once

#include <QHash>
#include <QMutex>
#include <QString>
#include <QStringList>
#include <QThread>
#include <QVariant>
#include <QVector>

Expand Down Expand Up @@ -291,6 +293,25 @@ class Config {
static QString dataDirectoryPathWhenPortable();
static QString dataDirectoryPathWhenInstalled();

private:
class ConfigSaveThread : private QThread {
public:
explicit ConfigSaveThread(void);
~ConfigSaveThread();

public:
void requestSave();

public:
ConfigSaveThread(const ConfigSaveThread&) = delete;
void operator=(const ConfigSaveThread&) = delete;

private:
QMutex _syncRoot;
bool _saveRequested = false;
void run();
};

private:
class ConfigFile {
public:
Expand Down Expand Up @@ -364,5 +385,6 @@ class Config {
static ConfigFile* getStateFile();
static void resetStateFile();
static ConfigFile* _stateFile;
static Config::ConfigSaveThread _configSaveThread;

};

0 comments on commit e9de711

Please sign in to comment.