mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-20 04:25:42 +08:00
refs #450 Added disk file saving and loading of CValueCache.
This commit is contained in:
@@ -332,6 +332,9 @@ namespace BlackMisc
|
|||||||
//! Insert new item with key and value
|
//! Insert new item with key and value
|
||||||
iterator insert(const Key &key, const Value &value) { return m_impl.insert(key, 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
|
//! Returns true if dictionary is empty
|
||||||
bool isEmpty() const { return m_impl.isEmpty(); }
|
bool isEmpty() const { return m_impl.isEmpty(); }
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,65 @@ namespace BlackMisc
|
|||||||
insertValues(map);
|
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)
|
CValueCache::BatchGuard CValueCache::batchChanges(QObject *owner)
|
||||||
{
|
{
|
||||||
Q_ASSERT(QThread::currentThread() == owner->thread());
|
Q_ASSERT(QThread::currentThread() == owner->thread());
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ namespace BlackMisc
|
|||||||
//! \threadsafe
|
//! \threadsafe
|
||||||
void loadFromJson(const QJsonObject &json);
|
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.
|
//! 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
|
//! \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
|
//! destroyed. If the destruction happens during stack unwinding due to an exception being thrown, the changes are
|
||||||
|
|||||||
@@ -10,12 +10,15 @@
|
|||||||
#include "testvaluecache.h"
|
#include "testvaluecache.h"
|
||||||
#include "blackmisc/worker.h"
|
#include "blackmisc/worker.h"
|
||||||
#include "blackmisc/identifier.h"
|
#include "blackmisc/identifier.h"
|
||||||
|
#include "blackmisc/aviation/aircraftlist.h"
|
||||||
|
#include "blackmisc/aviation/atcstationlist.h"
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
namespace BlackMiscTest
|
namespace BlackMiscTest
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace BlackMisc;
|
using namespace BlackMisc;
|
||||||
|
using namespace BlackMisc::Aviation;
|
||||||
|
|
||||||
CTestValueCache::CTestValueCache(QObject *parent) : QObject(parent)
|
CTestValueCache::CTestValueCache(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
@@ -195,6 +198,38 @@ namespace BlackMiscTest
|
|||||||
QVERIFY(cache.saveToJson() == testJson);
|
QVERIFY(cache.saveToJson() == testJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTestValueCache::saveAndLoad()
|
||||||
|
{
|
||||||
|
CAircraftList aircraft({ CAircraft("BAW001", {}, {}) });
|
||||||
|
CAtcStationList atcStations({ CAtcStation("EGLL_TWR" ) });
|
||||||
|
CVariantMap testData
|
||||||
|
{
|
||||||
|
{ "namespace1/value1", CVariant::from(1) },
|
||||||
|
{ "namespace1/value2", CVariant::from(2) },
|
||||||
|
{ "namespace1/value3", CVariant::from(3) },
|
||||||
|
{ "namespace2/aircraft", CVariant::from(aircraft) },
|
||||||
|
{ "namespace2/atcstations", CVariant::from(atcStations) }
|
||||||
|
};
|
||||||
|
CValueCache cache(CValueCache::LocalOnly);
|
||||||
|
cache.insertValues(testData);
|
||||||
|
|
||||||
|
QDir dir(QDir::currentPath() + "/testcache");
|
||||||
|
if (dir.exists()) { dir.removeRecursively(); }
|
||||||
|
|
||||||
|
auto status = cache.saveToFiles(dir.absolutePath());
|
||||||
|
QVERIFY(status.isEmpty());
|
||||||
|
|
||||||
|
auto files = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::Name);
|
||||||
|
QCOMPARE(files.size(), 2);
|
||||||
|
QCOMPARE(files[0].fileName(), QString("namespace1.json"));
|
||||||
|
QCOMPARE(files[1].fileName(), QString("namespace2.json"));
|
||||||
|
|
||||||
|
CValueCache cache2(CValueCache::LocalOnly);
|
||||||
|
status = cache2.loadFromFiles(dir.absolutePath());
|
||||||
|
QVERIFY(status.isEmpty());
|
||||||
|
QCOMPARE(cache2.getAllValues(), testData);
|
||||||
|
}
|
||||||
|
|
||||||
bool validator(int value)
|
bool validator(int value)
|
||||||
{
|
{
|
||||||
return value >= 0 && value <= 100;
|
return value >= 0 && value <= 100;
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ namespace BlackMiscTest
|
|||||||
|
|
||||||
//! Test Json serialization.
|
//! Test Json serialization.
|
||||||
void json();
|
void json();
|
||||||
|
|
||||||
|
//! Test saving to and loading from files.
|
||||||
|
void saveAndLoad();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
Reference in New Issue
Block a user