refs #644 Add method CCached::save, like setAndSave but using the currently set value.

Implemented with a flag in CValueCachePacket to indicate a request to save only.
This commit is contained in:
Mathew Sutcliffe
2016-04-27 19:39:49 +01:00
parent d9d30a339a
commit f4eadddee7
4 changed files with 41 additions and 14 deletions

View File

@@ -268,6 +268,9 @@ namespace BlackMisc
//! Data cache doesn't support setAndSave (because set() already causes save anyway). //! Data cache doesn't support setAndSave (because set() already causes save anyway).
CStatusMessage setAndSave(const typename Trait::type &value, qint64 timestamp = 0) = delete; CStatusMessage setAndSave(const typename Trait::type &value, qint64 timestamp = 0) = delete;
//! Data cache doesn't support save (because currently set value is saved already).
CStatusMessage save() = delete;
}; };
/*! /*!

View File

@@ -33,8 +33,8 @@ namespace BlackMisc
// CValueCachePacket // CValueCachePacket
//////////////////////////////// ////////////////////////////////
CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved) : CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved, bool valuesChanged) :
m_saved(saved) m_saved(saved), m_valuesChanged(valuesChanged)
{ {
for (auto it = values.cbegin(); it != values.cend(); ++it) for (auto it = values.cbegin(); it != values.cend(); ++it)
{ {
@@ -182,13 +182,16 @@ namespace BlackMisc
while (out != end && out.key() < in.key()) { ++out; } while (out != end && out.key() < in.key()) { ++out; }
auto &element = getElement(in.key(), out); auto &element = getElement(in.key(), out);
Q_ASSERT(isSafeToIncrement(element.m_pendingChanges)); if (values.valuesChanged())
element.m_pendingChanges++; {
element.m_value = in.value(); Q_ASSERT(isSafeToIncrement(element.m_pendingChanges));
element.m_timestamp = in.timestamp(); element.m_pendingChanges++;
element.m_value = in.value();
element.m_timestamp = in.timestamp();
}
element.m_saved = values.isSaved(); element.m_saved = values.isSaved();
} }
emit valuesChanged(values, sender()); if (values.valuesChanged()) { emit valuesChanged(values, sender()); }
emit valuesChangedByLocal(values); emit valuesChangedByLocal(values);
} }
@@ -196,6 +199,11 @@ namespace BlackMisc
{ {
QMutexLocker lock(&m_mutex); QMutexLocker lock(&m_mutex);
if (values.empty()) { return; } if (values.empty()) { return; }
if (! values.valuesChanged())
{
if (values.isSaved()) { emit valuesSaveRequested(values); }
return;
}
CValueCachePacket ratifiedChanges(values.isSaved()); CValueCachePacket ratifiedChanges(values.isSaved());
auto out = m_elements.lowerBound(values.cbegin().key()); auto out = m_elements.lowerBound(values.cbegin().key());
auto end = m_elements.upperBound((values.cend() - 1).key()); auto end = m_elements.upperBound((values.cend() - 1).key());
@@ -453,17 +461,24 @@ namespace BlackMisc
return element.m_value.read(); return element.m_value.read();
} }
CStatusMessage CValuePage::setValue(Element &element, const CVariant &value, qint64 timestamp, bool save) CStatusMessage CValuePage::setValue(Element &element, CVariant value, qint64 timestamp, bool save, bool ignoreValue)
{ {
Q_ASSERT(QThread::currentThread() == thread()); Q_ASSERT(QThread::currentThread() == thread());
if (timestamp == 0) { timestamp = QDateTime::currentMSecsSinceEpoch(); } if (timestamp == 0) { timestamp = QDateTime::currentMSecsSinceEpoch(); }
if (element.m_value.read() == value && element.m_timestamp == timestamp) { return {}; } if (element.m_value.read() == value && element.m_timestamp == timestamp && ! ignoreValue) { return {}; }
if (ignoreValue) { value = element.m_value.read(); }
auto status = validate(element, value, CStatusMessage::SeverityError); auto status = validate(element, value, CStatusMessage::SeverityError);
if (status.isSuccess()) if (status.isSuccess())
{ {
if (m_batchMode > 0) if (ignoreValue)
{
element.m_saved = save;
emit valuesWantToCache({ { { element.m_key, {} } }, 0, save, false });
}
else if (m_batchMode > 0)
{ {
m_batchedValues[element.m_key] = value; m_batchedValues[element.m_key] = value;
} }
@@ -505,6 +520,7 @@ namespace BlackMisc
void CValuePage::setValuesFromCache(const CValueCachePacket &values, QObject *changedBy) void CValuePage::setValuesFromCache(const CValueCachePacket &values, QObject *changedBy)
{ {
Q_ASSERT(QThread::currentThread() == thread()); Q_ASSERT(QThread::currentThread() == thread());
Q_ASSERT_X(values.valuesChanged(), Q_FUNC_INFO, "packet with unchanged values should not reach here");
QList<NotifySlot> notifySlots; QList<NotifySlot> notifySlots;

View File

@@ -35,10 +35,13 @@ namespace BlackMisc
using base_type = CDictionary; using base_type = CDictionary;
//! Constructor. //! Constructor.
CValueCachePacket(bool saved = false) : m_saved(saved) {} CValueCachePacket(bool saved = false, bool valuesChanged = true) : m_saved(saved), m_valuesChanged(valuesChanged) {}
//! Construct from CVariantMap and a timestamp. //! Construct from CVariantMap and a timestamp.
CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false); CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false, bool valuesChanged = true);
//! Values have been changed.
bool valuesChanged() const { return m_valuesChanged; }
//! Values are to be saved. //! Values are to be saved.
//! @{ //! @{
@@ -90,10 +93,12 @@ namespace BlackMisc
private: private:
bool m_saved = false; bool m_saved = false;
bool m_valuesChanged = true;
BLACK_METACLASS( BLACK_METACLASS(
CValueCachePacket, CValueCachePacket,
BLACK_METAMEMBER(saved) BLACK_METAMEMBER(saved),
BLACK_METAMEMBER(valuesChanged)
); );
}; };
@@ -304,6 +309,9 @@ namespace BlackMisc
//! Write and save in the same step. Must be called from the thread in which the owner lives. //! Write and save in the same step. Must be called from the thread in which the owner lives.
CStatusMessage setAndSave(const T &value, qint64 timestamp = 0) { return m_page.setValue(m_element, CVariant::from(value), timestamp, true); } CStatusMessage setAndSave(const T &value, qint64 timestamp = 0) { return m_page.setValue(m_element, CVariant::from(value), timestamp, true); }
//! Save using the currently set value. Must be called from the thread in which the owner lives.
CStatusMessage save() { return m_page.setValue(m_element, {}, 0, true, true); }
//! Is current thread the owner thread, so CCached::set is safe //! Is current thread the owner thread, so CCached::set is safe
bool isOwnerThread() const { return QThread::currentThread() == m_page.thread(); } bool isOwnerThread() const { return QThread::currentThread() == m_page.thread(); }

View File

@@ -69,7 +69,7 @@ namespace BlackMisc
CVariant getValueCopy(const Element &element) const; CVariant getValueCopy(const Element &element) const;
//! Write the value corresponding to the element's key and begin synchronizing it to any other pages. //! Write the value corresponding to the element's key and begin synchronizing it to any other pages.
CStatusMessage setValue(Element &element, const CVariant &value, qint64 timestamp, bool save = false); CStatusMessage setValue(Element &element, CVariant value, qint64 timestamp, bool save = false, bool ignoreValue = false);
//! Get the key string corresponding to the element. //! Get the key string corresponding to the element.
const QString &getKey(const Element &element) const; const QString &getKey(const Element &element) const;