refs #450 Added disk file saving and loading of CValueCache.

This commit is contained in:
Mathew Sutcliffe
2015-09-05 16:43:30 +01:00
parent ca9256be82
commit 54bc3f265a
5 changed files with 110 additions and 0 deletions

View File

@@ -332,6 +332,9 @@ namespace BlackMisc
//! Insert new item with key and value
iterator insert(const Key &key, const Value &value) { return m_impl.insert(key, value); }
//! Insert all items of other dictionary into this dictionary
void insert(const CDictionary &other) { for (auto i = other.cbegin(); i != other.cend(); ++i) { insert(i.key(), i.value()); } }
//! Returns true if dictionary is empty
bool isEmpty() const { return m_impl.isEmpty(); }

View File

@@ -144,6 +144,65 @@ namespace BlackMisc
insertValues(map);
}
CStatusMessage CValueCache::saveToFiles(const QString &dir, const QString &keyPrefix) const
{
auto values = getAllValues(keyPrefix);
QMap<QString, CVariantMap> namespaces;
for (auto it = values.cbegin(); it != values.cend(); ++it)
{
namespaces[it.key().section('/', 0, 0)].insert(it.key(), it.value());
}
if (! QDir::root().mkpath(dir))
{
return CLogMessage(this).error("Failed to create directory %1") << dir;
}
for (auto it = namespaces.cbegin(); it != namespaces.cend(); ++it)
{
QFile file(dir + "/" + it.key() + ".json");
if (! file.open(QFile::ReadWrite | QFile::Text))
{
return CLogMessage(this).error("Failed to open %1: %2") << file.fileName() << file.errorString();
}
auto json = QJsonDocument::fromJson(file.readAll());
if (json.isArray() || (json.isNull() && ! json.isEmpty()))
{
return CLogMessage(this).error("Invalid JSON format in %1") << file.fileName();
}
CVariantMap storedValues;
storedValues.convertFromJson(json.object());
storedValues.insert(*it);
json.setObject(storedValues.toJson());
if (! (file.seek(0) && file.resize(0) && file.write(json.toJson()) > 0))
{
return CLogMessage(this).error("Failed to write to %1: %2") << file.fileName() << file.errorString();
}
}
return {};
}
CStatusMessage CValueCache::loadFromFiles(const QString &dir)
{
if (! QDir(dir).isReadable())
{
return CLogMessage(this).error("Failed to read directory %1") << dir;
}
for (const auto &filename : QDir(dir).entryList({ "*.json" }, QDir::Files))
{
QFile file(dir + "/" + filename);
if (! file.open(QFile::ReadOnly | QFile::Text))
{
return CLogMessage(this).error("Failed to open %1 : %2") << file.fileName() << file.errorString();
}
auto json = QJsonDocument::fromJson(file.readAll());
if (json.isArray() || (json.isNull() && ! json.isEmpty()))
{
return CLogMessage(this).error("Invalid JSON format in %1") << file.fileName();
}
loadFromJson(json.object());
}
return {};
}
CValueCache::BatchGuard CValueCache::batchChanges(QObject *owner)
{
Q_ASSERT(QThread::currentThread() == owner->thread());

View File

@@ -59,6 +59,16 @@ namespace BlackMisc
//! \threadsafe
void loadFromJson(const QJsonObject &json);
//! Save values to Json files in a given directory.
//! If prefix is provided then only those values whose keys start with that prefix.
//! \threadsafe
CStatusMessage saveToFiles(const QString &directory, const QString &keyPrefix = {}) const;
//! Load all values from Json files in a given directory.
//! Values already in the cache will remain in the cache unless they are overwritten.
//! \threadsafe
CStatusMessage loadFromFiles(const QString &directory);
//! Begins a batch of changes to be made through CCached instances owned by owner.
//! \details All changes made through those CCached instances will be deferred until the returned RAII object is
//! destroyed. If the destruction happens during stack unwinding due to an exception being thrown, the changes are