6#ifndef SWIFT_MISC_VALUECACHE_H
7#define SWIFT_MISC_VALUECACHE_H
16#include <QDBusArgument>
25#include <QSharedPointer>
62 public CDictionary<QString, std::pair<CVariant, qint64>, QMap>,
89 void setSaved(
bool saved =
true) { m_saved = saved; }
126 reference value()
const {
return CDictionary::const_iterator::value().first; }
127 reference operator*()
const {
return value(); }
128 pointer operator->()
const {
return &value(); }
129 qint64 timestamp()
const {
return CDictionary::const_iterator::value().second; }
141 bool m_saved =
false;
142 bool m_valuesChanged =
true;
239 void setHumanReadableName(
const QString &key,
const QString &name);
274 return makeRange(m_elements.lowerBound(keyPrefix),
279 return makeRange(m_elements.lowerBound(keyPrefix),
287 const QString &keysMessage = {})
const;
293 bool keysOnly =
false)
const;
315 static const QString &getCacheRootDirectory();
318 friend class private_ns::CValuePage;
325 const int m_fileSplitDepth = 1;
327 Element &getElement(
const QString &key);
329 std::tuple<CVariant, qint64, bool> getValue(
const QString &key);
330 void backupFile(
QFile &file)
const;
332 virtual void connectPage(private_ns::CValuePage *page);
351 template <
typename T>
360 template <
typename U>
362 :
CCached(cache, key, name, nullptr, T {}, owner)
372 template <
typename U,
typename F>
375 : m_page(&private_ns::CValuePage::getPageFor(owner, cache)),
376 m_element(&m_page->createElement(key, name, qMetaTypeId<T>(), wrap(validator),
381 cache->setHumanReadableName(
getKey(), name);
386 template <
typename F>
394 using U =
typename private_ns::TClassOfPointerToMember<F>::type;
395 Q_ASSERT_X(m_page->parent()->metaObject()->inherits(&U::staticMetaObject), Q_FUNC_INFO,
396 "Slot is member function of wrong class");
397 m_page->setNotifySlot(
399 { [slot](
QObject *obj) { private_ns::invokeSlot(slot,
static_cast<U *
>(obj)); }, makeId(slot) });
405 static const T empty {};
406 return *(isValid() ?
static_cast<const T *
>(getVariant().data()) : &empty);
411 T
get()
const {
return isValid() ? getVariantCopy().template value<T>() : T {}; }
432 v.setPropertyByIndex(index, value);
433 return set(v, timestamp);
440 v.setPropertyByIndex(index, value);
462 bool isSaved()
const {
return m_page->isSaved(*m_element); }
465 bool isSaving()
const {
return m_page->isSaving(*m_element); }
477 template <
typename F>
478 static private_ns::CValuePage::Validator wrap(F func)
480 return [func](
const CVariant &value,
QString &reason) ->
bool {
return func(value.
value<T>(), reason); };
482 static private_ns::CValuePage::Validator wrap(std::nullptr_t) {
return {}; }
484 template <
typename F>
485 static auto makeId(F &&)
489 template <
typename U,
typename M>
490 static auto makeId(M U::*slot)
492 return static_cast<std::tuple_element_t<1, private_ns::CValuePage::NotifySlot>
>(slot);
495 const QVariant &getVariant()
const {
return m_page->getValue(*m_element).getQVariant(); }
496 QVariant getVariantCopy()
const {
return m_page->getValueCopy(*m_element).getQVariant(); }
497 bool isValid()
const {
return m_page->isValid(*m_element, qMetaTypeId<T>()); }
501 void onOwnerNameChanged(
const std::function<
void()> &function)
506 private_ns::CValuePage *m_page = (
throw std::logic_error(
"Uninitialized member"),
nullptr);
507 private_ns::CValuePage::Element *m_element =
508 (
throw std::logic_error(
"Uninitialized member"),
nullptr);
532 std::swap(m_page, other.m_page);
538 BatchGuard(private_ns::CValuePage &page) : m_page(&page) {}
539 private_ns::CValuePage *m_page;
CStatusMessage setProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp=0)
Write a property of the value. Must be called from the thread in which the owner lives.
bool isSaving() const
Return true if this value is currently saving.
bool isInitialized() const
Can be false if key contains OwnerName% and owner's objectName was empty.
CStatusMessage save()
Save using the currently set value. Must be called from the thread in which the owner lives.
const QString & getKey() const
Get the key string of this value.
CCached(const CCached &)=delete
Deleted copy constructor.
qint64 getTimestampMsSinceEpoch() const
Return the time when this value was updated.
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
CCached(CValueCache *cache, const QString &key, const QString &name, F validator, const T &defaultValue, U *owner)
Constructor.
CStatusMessage set(const T &value, qint64 timestamp=0)
Write a new value. Must be called from the thread in which the owner lives.
CCached(CValueCache *cache, const QString &key, const QString &name, U *owner)
Constructor.
CCached & operator=(const CCached &)=delete
Deleted copy assignment operator.
void setNotifySlot(F slot)
Set a callback to be called when the value is changed by another source.
const T & getThreadLocal() const
Read the current value.
bool isOwnerThread() const
Is current thread the owner thread, so CCached::set is safe.
qint64 lastUpdatedAge() const
How old is that cache (ms)?
QDateTime getTimestamp() const
Return the time when this value was updated.
bool isSaved() const
Return true if this value was already saved.
T get() const
Get a copy of the current value.
CStatusMessage setAndSaveProperty(CPropertyIndexRef index, const CVariant &value, qint64 timestamp=0)
Write a property and save in the same step. Must be called from the thread in which the owner lives.
const std::pair< CVariant, qint64 > value(const QString &key) const
CRange< const_iterator > values() const
std::pair< CVariant, qint64 > value_type
const_iterator cbegin() const
Returns const iterator at the beginning of the dictionary.
iterator insert(const Key &key, const Value &value)
Insert new item with key and value.
std::pair< CVariant, qint64 > & reference
typename Impl< Key, Value >::const_iterator const_iterator
STL compatibility.
const QString key(const std::pair< CVariant, qint64 > &value) const
const_iterator cend() const
Returns const iterator at the end of the dictionary.
Value object encapsulating information identifying a component of a modular distributed swift process...
A sequence of log categories.
Non-owning reference to a CPropertyIndex with a subset of its features.
Streamable status message, e.g.
Status messages, e.g. from Core -> GUI.
RAII object returned by CValueCache::batchChanges.
BatchGuard & operator=(BatchGuard &&other) noexcept
Move assignment operator.
BatchGuard(const BatchGuard &)=delete
Deleted copy constructor. Class is move-only.
BatchGuard & operator=(const BatchGuard &)=delete
Deleted copy assignment operator. Class is move-only.
BatchGuard(BatchGuard &&other) noexcept
Move constructor.
~BatchGuard()
Destructor. Applies deferred changes.
Manages a map of { QString, CVariant } pairs, which can be distributed among multiple processes.
void changeValuesFromRemote(const swift::misc::CValueCachePacket &values, const swift::misc::CIdentifier &originator)
Notify this cache that values have been changed by one of the duplicate caches in the multi-process e...
auto elementsStartingWith(const QString &keyPrefix) const
Returns a range referring to all elements which start with the given prefix.
swift::misc::CVariantMap getAllValues(const QString &keyPrefix={}) const
Return map containing all values in the cache. If prefix is provided then only those values whose key...
QString getHumanReadableName(const QString &key) const
Return the human readable name of the given key, or the raw key string if there is none.
QStringList enumerateFiles(const QString &directory) const
List the Json files which are (or would be) used to save the current values. The files may or may not...
static const QStringList & getLogCategories()
Log categories.
QString filenameForKey(const QString &key) const
Return the (relative) filename that may is (or would be) used to save the value with the given key....
CStatusMessage loadFromFiles(const QString &directory, const QSet< QString > &keys, const CVariantMap ¤t, CValueCachePacket &o_values, const QString &keysMessage={}, bool keysOnly=false) const
Load from Json files in a given directory any values which differ from the current ones,...
void markAllAsSaved(const QStringList &keys)
Mark all values with given keys as having been saved.
BatchGuard batchChanges(QObject *owner)
Begins a batch of changes to be made through CCached instances owned by owner.
CVariant getValueSync(const QString &key)
Synchronously return a current value.
CStatusMessage saveToFiles(const QString &directory, const QStringList &keys)
Save values to Json files in a given directory.
CValueCache(int fileSplitDepth, QObject *parent=nullptr)
Constructor.
QRecursiveMutex m_mutex
Mutex protecting operations which are critical on m_elements.
void clearAllValues(const QString &keyPrefix={})
Clear all values from the cache.
CStatusMessage saveToFiles(const QString &directory, const CVariantMap &values, const QString &keysMessage={}) const
Save specific values to Json files in a given directory.
swift::misc::CValueCachePacket getAllValuesWithTimestamps(const QString &keyPrefix={}) const
Return map containing all values in the cache, and timestamps when they were modified.
QJsonObject saveToJson(const QString &keyPrefix={}) const
Save values in Json format. If prefix is provided then only those values whose keys start with that p...
void markAllAsSaved(const QString &keyPrefix)
Mark all values with keys that start with the given prefix as having been saved.
void insertValues(const swift::misc::CValueCachePacket &values)
Add some values to the cache. Values already in the cache will remain in the cache unless they are ov...
QString getHumanReadableWithKey(const QString &key) const
Return the human readable name of the given key, with the raw key string appended.
void valuesSaveRequested(const swift::misc::CValueCachePacket &values)
Emitted when this cache has ratified a change which included a request to save (i....
CStatusMessage loadFromFiles(const QString &directory)
Load all values from Json files in a given directory. Values already in the cache will remain in the ...
void valuesChangedByLocal(const swift::misc::CValueCachePacket &values)
Emitted when values in the cache are changed by an object in this very process. The interprocess comm...
swift::misc::CVariantMap getAllValues(const QStringList &keys) const
Return map containing all given values in the cache.
void loadFromJson(const QJsonObject &json)
Load all values in Json format. Values already in the cache will remain in the cache unless they are ...
QStringList getAllUnsavedKeys(const QString &keyPrefix={}) const
Return keys of all values which have been changed but not saved.
CStatusMessageList loadFromJsonNoThrow(const QJsonObject &json, const CLogCategoryList &categories, const QString &prefix)
Call loadFromJson, catch any CJsonException that are thrown and return them as CStatusMessage.
qint64 getTimestampSync(const QString &key)
Synchronously return a current timestamp.
CStatusMessage saveToFiles(const QString &directory, const QString &keyPrefix={})
Save values to Json files in a given directory. If prefix is provided then only those values whose ke...
auto elementsStartingWith(const QString &keyPrefix)
Returns a range referring to all elements which start with the given prefix.
Value class used for signalling changed values in the cache.
const_iterator begin() const
Iterators.
CValueCachePacket(bool saved=false, bool valuesChanged=true)
Constructor.
void setTimestamps(const QMap< QString, qint64 > &)
Change the timestamps of values.
void setSaved(bool saved=true)
Values are to be saved.
void insert(const CVariantMap &values, qint64 timestamp)
Insert a CVariantMap with a timestamp.
QString toTimestampMapString(const QStringList &keys) const
Return map of timestamps converted to string.
void insert(const QString &key, const CVariant &value, qint64 timestamp)
Insert a key/value pair with a timestamp.
CDictionary base_type
Base class.
void insert(const CValueCachePacket &other)
Insert values from another packet.
CValueCachePacket takeByKey(const QString &key)
Remove value matching the given key, and return it in a separate packet.
const_iterator cend() const
Iterators.
QMap< QString, qint64 > toTimestampMap() const
Discard values and return as map of timestamps.
const_iterator end() const
Iterators.
static void registerMetadata()
Register metadata.
bool valuesChanged() const
Values have been changed.
CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved=false, bool valuesChanged=true)
Construct from CVariantMap and a timestamp.
bool isSaved() const
Values are to be saved.
CVariantMap toVariantMap() const
Discard timestamps and return as variant map.
const_iterator cbegin() const
Iterators.
Wrapper around QVariant which provides transparent access to CValueObject methods of the contained ob...
static CVariant fromValue(T &&value)
Construct a variant from a value.
T value() const
Return the value converted to the type T.
Map of { QString, CVariant } pairs.
#define SWIFT_MISC_DECLARE_USING_MIXIN_DATASTREAM(DERIVED)
When a derived class and a base class both inherit from mixin::DataStreamByMetaClass,...
#define SWIFT_MISC_DECLARE_USING_MIXIN_DBUS(DERIVED,...)
When a derived class and a base class both inherit from mixin::DBusByTuple, the derived class uses th...
Free functions in swift::misc.
QMetaObject::Connection connectOnce(T *sender, F signal, U *receiver, G &&slot, Qt::ConnectionType type=Qt::AutoConnection)
Wrapper around QObject::connect which disconnects after the signal has been emitted once.
auto makeRange(I begin, I2 end) -> CRange< I >
Returns a CRange constructed from begin and end iterators of deduced types.
SWIFT_MISC_EXPORT void setMockCacheRootDirectory(const QString &path)
Overwrite the default root directory for cache and settings, for testing purposes.
qint64 currentMSecsSinceEpoch()
QDateTime fromMSecsSinceEpoch(qint64 msecs)
qint64 toMSecsSinceEpoch() const const
void objectNameChanged(const QString &objectName)
QObject * parent() const const
QThread * thread() const const
QThread * currentThread()
#define SWIFT_MISC_EXPORT
Export a class or function from the library.