From 2c0b4f955505d0c688abd857951f4c064662364c Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 20 Dec 2015 23:00:28 +0000 Subject: [PATCH] refs #545 CValueCache keeps track of which values have been saved. --- src/blackmisc/datacache.cpp | 9 ++++++++- src/blackmisc/settingscache.cpp | 2 +- src/blackmisc/settingscache.h | 2 +- src/blackmisc/valuecache.cpp | 22 ++++++++++++++++++--- src/blackmisc/valuecache.h | 34 ++++++++++++++++++++++++++++----- 5 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/blackmisc/datacache.cpp b/src/blackmisc/datacache.cpp index 32a7af612..c50f6d7f5 100644 --- a/src/blackmisc/datacache.cpp +++ b/src/blackmisc/datacache.cpp @@ -16,7 +16,7 @@ namespace BlackMisc { CDataCache::CDataCache() : - CValueCache(CValueCache::LocalOnly) // for signal loopback + CValueCache(CValueCache::Distributed) { if (! QDir::root().mkpath(persistentStore())) { @@ -24,6 +24,11 @@ namespace BlackMisc } connect(this, &CValueCache::valuesChangedByLocal, this, &CDataCache::saveToStoreAsync); + connect(this, &CValueCache::valuesChangedByLocal, this, [ = ](CValueCachePacket values) + { + values.setSaved(); + changeValuesFromRemote(values, CIdentifier()); + }); connect(&m_watcher, &QFileSystemWatcher::fileChanged, this, &CDataCache::loadFromStoreAsync); connect(&m_serializer, &CDataCacheSerializer::valuesLoadedFromStore, this, &CDataCache::changeValuesFromRemote); @@ -127,6 +132,7 @@ namespace BlackMisc if (! m_deferredChanges.isEmpty()) // apply changes which we grabbed at the last minute above { + m_deferredChanges.setSaved(); emit valuesLoadedFromStore(m_deferredChanges, CIdentifier::anonymous()); m_deferredChanges.clear(); } @@ -163,6 +169,7 @@ namespace BlackMisc if (! (m_deferredChanges.isEmpty() || defer)) { + m_deferredChanges.setSaved(); emit valuesLoadedFromStore(m_deferredChanges, CIdentifier::anonymous()); m_deferredChanges.clear(); } diff --git a/src/blackmisc/settingscache.cpp b/src/blackmisc/settingscache.cpp index fab728229..db64116c9 100644 --- a/src/blackmisc/settingscache.cpp +++ b/src/blackmisc/settingscache.cpp @@ -28,7 +28,7 @@ namespace BlackMisc return dir; } - BlackMisc::CStatusMessage CSettingsCache::saveToStore(const QString &keyPrefix) const + BlackMisc::CStatusMessage CSettingsCache::saveToStore(const QString &keyPrefix) { return saveToFiles(persistentStore(), keyPrefix); } diff --git a/src/blackmisc/settingscache.h b/src/blackmisc/settingscache.h index 1aa86aeb3..db6f04a5a 100644 --- a/src/blackmisc/settingscache.h +++ b/src/blackmisc/settingscache.h @@ -32,7 +32,7 @@ namespace BlackMisc static const QString &persistentStore(); //! Save core settings to disk. - BlackMisc::CStatusMessage saveToStore(const QString &keyPrefix = {}) const; + BlackMisc::CStatusMessage saveToStore(const QString &keyPrefix = {}); //! Load core settings from disk. BlackMisc::CStatusMessage loadFromStore(); diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index b73408528..27099e94f 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -29,7 +29,8 @@ namespace BlackMisc // CValueCachePacket //////////////////////////////// - CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp) + CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved) : + m_saved(saved) { for (auto it = values.cbegin(); it != values.cend(); ++it) { @@ -89,6 +90,7 @@ namespace BlackMisc const QString m_key; CVariant m_value; int m_pendingChanges = 0; + bool m_saved = false; std::atomic m_timestamp { QDateTime::currentMSecsSinceEpoch() }; }; @@ -156,6 +158,7 @@ namespace BlackMisc element.m_pendingChanges++; element.m_value = in.value(); element.m_timestamp = in.timestamp(); + element.m_saved = values.isSaved(); } emit valuesChanged(values, sender()); emit valuesChangedByLocal(values); @@ -182,6 +185,7 @@ namespace BlackMisc { element.m_value = in.value(); element.m_timestamp = in.timestamp(); + element.m_saved = values.isSaved(); ratifiedChanges.insert(in.key(), in.value(), in.timestamp()); } } @@ -203,11 +207,13 @@ namespace BlackMisc insertValues({ map, QDateTime::currentMSecsSinceEpoch() }); } - CStatusMessage CValueCache::saveToFiles(const QString &dir, const QString &keyPrefix) const + CStatusMessage CValueCache::saveToFiles(const QString &dir, const QString &keyPrefix) { QMutexLocker lock(&m_mutex); auto values = getAllValues(keyPrefix); - return saveToFiles(dir, values); + auto status = saveToFiles(dir, values); + if (! status.isEmpty()) { markAllAsSaved(keyPrefix); } + return status; } CStatusMessage CValueCache::saveToFiles(const QString &dir, const CVariantMap &values) const @@ -250,6 +256,7 @@ namespace BlackMisc QMutexLocker lock(&m_mutex); CValueCachePacket values; auto status = loadFromFiles(dir, getAllValues(), values); + values.setSaved(); insertValues(values); return status; } @@ -280,6 +287,15 @@ namespace BlackMisc return {}; } + void CValueCache::markAllAsSaved(const QString &keyPrefix) + { + QMutexLocker lock(&m_mutex); + for (const auto &element : elementsStartingWith(keyPrefix)) + { + element->m_saved = true; + } + } + QString CValueCache::filenameForKey(const QString &key) { return key.section('/', 0, 0) + ".json"; diff --git a/src/blackmisc/valuecache.h b/src/blackmisc/valuecache.h index de345fca8..574afe521 100644 --- a/src/blackmisc/valuecache.h +++ b/src/blackmisc/valuecache.h @@ -23,14 +23,29 @@ namespace BlackMisc */ class BLACKMISC_EXPORT CValueCachePacket : public CDictionary, QMap>, - public Mixin::MetaType + public Mixin::MetaType, + public Mixin::DBusByTuple, + public Mixin::JsonByTuple, + public Mixin::EqualsByTuple { public: - //! Default constructor. - CValueCachePacket() {} + BLACKMISC_DECLARE_USING_MIXIN_DBUS(CValueCachePacket) + BLACKMISC_DECLARE_USING_MIXIN_JSON(CValueCachePacket) + + //! \copydoc BlackMisc::CValueObject::base_type + using base_type = CDictionary; + + //! Constructor. + CValueCachePacket(bool saved = false) : m_saved(saved) {} //! Construct from CVariantMap and a timestamp. - CValueCachePacket(const CVariantMap &values, qint64 timestamp); + CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false); + + //! Values are to be saved. + //! @{ + bool isSaved() const { return m_saved; } + void setSaved(bool saved = true) { m_saved = saved; } + //! @} //! Insert a key/value pair with a timestamp. void insert(const QString &key, const CVariant &value, qint64 timestamp); @@ -67,6 +82,10 @@ namespace BlackMisc const_iterator begin() const { return CDictionary::cbegin(); } const_iterator end() const { return CDictionary::cend(); } //! @} + + private: + BLACK_ENABLE_TUPLE_CONVERSION(CValueCachePacket) + bool m_saved = false; }; /*! @@ -118,7 +137,7 @@ namespace BlackMisc //! 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; + CStatusMessage saveToFiles(const QString &directory, const QString &keyPrefix = {}); //! Load all values from Json files in a given directory. //! Values already in the cache will remain in the cache unless they are overwritten. @@ -186,6 +205,10 @@ namespace BlackMisc //! \threadsafe CStatusMessage loadFromFiles(const QString &directory, const CVariantMap ¤t, CValueCachePacket &o_values) const; + //! Mark all values with keys that start with the given prefix as having been saved. + //! \threadsafe + void markAllAsSaved(const QString &keyPrefix); + //! Mutex protecting operations which are critical on m_elements. mutable QMutex m_mutex { QMutex::Recursive }; @@ -308,5 +331,6 @@ namespace BlackMisc } // namespace Q_DECLARE_METATYPE(BlackMisc::CValueCachePacket) +BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CValueCachePacket, (attr(o.m_saved))) #endif