mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-16 10:25:36 +08:00
refs #601 Introduce "pinned" values, which are loaded synchronously by the CDataCache constructor.
This commit is contained in:
@@ -67,6 +67,7 @@ namespace BlackMisc
|
|||||||
if (! QFile::exists(m_revisionFileName)) { QFile(m_revisionFileName).open(QFile::WriteOnly); }
|
if (! QFile::exists(m_revisionFileName)) { QFile(m_revisionFileName).open(QFile::WriteOnly); }
|
||||||
m_watcher.addPath(m_revisionFileName);
|
m_watcher.addPath(m_revisionFileName);
|
||||||
m_serializer.start();
|
m_serializer.start();
|
||||||
|
m_serializer.loadFromStore({}, false, true); // load pinned values
|
||||||
loadFromStoreAsync();
|
loadFromStoreAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +114,11 @@ namespace BlackMisc
|
|||||||
QTimer::singleShot(0, &m_serializer, [this, key, timestamp] { m_revision.overrideTimestamp(key, timestamp); });
|
QTimer::singleShot(0, &m_serializer, [this, key, timestamp] { m_revision.overrideTimestamp(key, timestamp); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDataCache::pinValue(const QString &key)
|
||||||
|
{
|
||||||
|
QTimer::singleShot(0, &m_serializer, [this, key] { m_revision.pinValue(key); });
|
||||||
|
}
|
||||||
|
|
||||||
QString lockFileError(const QLockFile &lock)
|
QString lockFileError(const QLockFile &lock)
|
||||||
{
|
{
|
||||||
switch (lock.error())
|
switch (lock.error())
|
||||||
@@ -226,9 +232,9 @@ namespace BlackMisc
|
|||||||
applyDeferredChanges(); // apply changes which we grabbed at the last minute above
|
applyDeferredChanges(); // apply changes which we grabbed at the last minute above
|
||||||
}
|
}
|
||||||
|
|
||||||
CDataCacheRevision::LockGuard CDataCacheSerializer::loadFromStore(const BlackMisc::CValueCachePacket &baseline, bool defer)
|
CDataCacheRevision::LockGuard CDataCacheSerializer::loadFromStore(const BlackMisc::CValueCachePacket &baseline, bool defer, bool pinsOnly)
|
||||||
{
|
{
|
||||||
auto lock = m_cache->m_revision.beginUpdate(baseline.toTimestampMap());
|
auto lock = m_cache->m_revision.beginUpdate(baseline.toTimestampMap(), ! pinsOnly, pinsOnly);
|
||||||
if (lock && m_cache->m_revision.isPendingRead())
|
if (lock && m_cache->m_revision.isPendingRead())
|
||||||
{
|
{
|
||||||
CValueCachePacket newValues;
|
CValueCachePacket newValues;
|
||||||
@@ -263,7 +269,7 @@ namespace BlackMisc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CDataCacheRevision::LockGuard CDataCacheRevision::beginUpdate(const QMap<QString, qint64> ×tamps, bool updateUuid)
|
CDataCacheRevision::LockGuard CDataCacheRevision::beginUpdate(const QMap<QString, qint64> ×tamps, bool updateUuid, bool pinsOnly)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&m_mutex);
|
QMutexLocker lock(&m_mutex);
|
||||||
|
|
||||||
@@ -317,6 +323,15 @@ namespace BlackMisc
|
|||||||
if (m_pendingWrite) { return guard; }
|
if (m_pendingWrite) { return guard; }
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pinsOnly)
|
||||||
|
{
|
||||||
|
auto pins = fromJson(json.value("pins").toArray());
|
||||||
|
for (const auto &key : m_timestamps.keys())
|
||||||
|
{
|
||||||
|
if (! pins.contains(key)) { m_timestamps.remove(key); }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (revisionFile.size() > 0)
|
else if (revisionFile.size() > 0)
|
||||||
{
|
{
|
||||||
@@ -357,6 +372,7 @@ namespace BlackMisc
|
|||||||
json.insert("uuid", m_uuid.toString());
|
json.insert("uuid", m_uuid.toString());
|
||||||
json.insert("timestamps", toJson(timestamps));
|
json.insert("timestamps", toJson(timestamps));
|
||||||
json.insert("ttl", toJson(m_timesToLive));
|
json.insert("ttl", toJson(m_timesToLive));
|
||||||
|
json.insert("pins", toJson(m_pinnedValues));
|
||||||
revisionFile.write(QJsonDocument(json).toJson());
|
revisionFile.write(QJsonDocument(json).toJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,6 +481,13 @@ namespace BlackMisc
|
|||||||
m_lockFile.unlock();
|
m_lockFile.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDataCacheRevision::pinValue(const QString &key)
|
||||||
|
{
|
||||||
|
Q_ASSERT(! m_updateInProgress);
|
||||||
|
|
||||||
|
m_pinnedValues.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject CDataCacheRevision::toJson(const QMap<QString, qint64> ×tamps)
|
QJsonObject CDataCacheRevision::toJson(const QMap<QString, qint64> ×tamps)
|
||||||
{
|
{
|
||||||
QJsonObject result;
|
QJsonObject result;
|
||||||
@@ -484,6 +507,26 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonArray CDataCacheRevision::toJson(const QSet<QString> &pins)
|
||||||
|
{
|
||||||
|
QJsonArray result;
|
||||||
|
for (auto it = pins.begin(); it != pins.end(); ++it)
|
||||||
|
{
|
||||||
|
result.push_back(*it);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> CDataCacheRevision::fromJson(const QJsonArray &pins)
|
||||||
|
{
|
||||||
|
QSet<QString> result;
|
||||||
|
for (auto it = pins.begin(); it != pins.end(); ++it)
|
||||||
|
{
|
||||||
|
result.insert(it->toString());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ namespace BlackMisc
|
|||||||
//! Return value can be converted to bool, false means update is not started (error, or already up-to-date).
|
//! Return value can be converted to bool, false means update is not started (error, or already up-to-date).
|
||||||
//! \param timestamps Current in-memory timestamps, to be compared with the on-disk ones.
|
//! \param timestamps Current in-memory timestamps, to be compared with the on-disk ones.
|
||||||
//! \param updateUuid Whether to prepare for an actual update, or just interrograte whether one is needed.
|
//! \param updateUuid Whether to prepare for an actual update, or just interrograte whether one is needed.
|
||||||
LockGuard beginUpdate(const QMap<QString, qint64> ×tamps, bool updateUuid = true);
|
//! \param pinsOnly Only load pinned values.
|
||||||
|
LockGuard beginUpdate(const QMap<QString, qint64> ×tamps, bool updateUuid = true, bool pinsOnly = false);
|
||||||
|
|
||||||
//! During update, writes a new revision file with new timestamps.
|
//! During update, writes a new revision file with new timestamps.
|
||||||
void writeNewRevision(const QMap<QString, qint64> ×tamps);
|
void writeNewRevision(const QMap<QString, qint64> ×tamps);
|
||||||
@@ -110,6 +111,9 @@ namespace BlackMisc
|
|||||||
//! Causes the new timestamp to be written to the revision file.
|
//! Causes the new timestamp to be written to the revision file.
|
||||||
void overrideTimestamp(const QString &key, qint64 timestamp);
|
void overrideTimestamp(const QString &key, qint64 timestamp);
|
||||||
|
|
||||||
|
//! Set the flag which will cause the value to be pre-loaded.
|
||||||
|
void pinValue(const QString &key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable QMutex m_mutex { QMutex::Recursive };
|
mutable QMutex m_mutex { QMutex::Recursive };
|
||||||
bool m_updateInProgress = false;
|
bool m_updateInProgress = false;
|
||||||
@@ -120,10 +124,13 @@ namespace BlackMisc
|
|||||||
QUuid m_uuid;
|
QUuid m_uuid;
|
||||||
QMap<QString, qint64> m_timestamps;
|
QMap<QString, qint64> m_timestamps;
|
||||||
QMap<QString, qint64> m_timesToLive;
|
QMap<QString, qint64> m_timesToLive;
|
||||||
|
QSet<QString> m_pinnedValues;
|
||||||
std::vector<std::promise<void>> m_promises;
|
std::vector<std::promise<void>> m_promises;
|
||||||
|
|
||||||
static QJsonObject toJson(const QMap<QString, qint64> ×tamps);
|
static QJsonObject toJson(const QMap<QString, qint64> ×tamps);
|
||||||
static QMap<QString, qint64> fromJson(const QJsonObject ×tamps);
|
static QMap<QString, qint64> fromJson(const QJsonObject ×tamps);
|
||||||
|
static QJsonArray toJson(const QSet<QString> &pins);
|
||||||
|
static QSet<QString> fromJson(const QJsonArray &pins);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -145,8 +152,9 @@ namespace BlackMisc
|
|||||||
//! Also called by saveToStore, to ensure that remote changes to unrelated values are not lost.
|
//! Also called by saveToStore, to ensure that remote changes to unrelated values are not lost.
|
||||||
//! \param baseline A snapshot of the currently loaded values, taken when the load is queued.
|
//! \param baseline A snapshot of the currently loaded values, taken when the load is queued.
|
||||||
//! \param defer Whether to defer applying the changes. Used when called by saveToStore.
|
//! \param defer Whether to defer applying the changes. Used when called by saveToStore.
|
||||||
|
//! \param pinsOnly Only load pinned values.
|
||||||
//! \return Usually ignored, but can be held in order to retain the revision file lock.
|
//! \return Usually ignored, but can be held in order to retain the revision file lock.
|
||||||
CDataCacheRevision::LockGuard loadFromStore(const BlackMisc::CValueCachePacket &baseline, bool defer = false);
|
CDataCacheRevision::LockGuard loadFromStore(const BlackMisc::CValueCachePacket &baseline, bool defer = false, bool pinsOnly = false);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
//! Signal back to the cache when values have been loaded.
|
//! Signal back to the cache when values have been loaded.
|
||||||
@@ -194,6 +202,9 @@ namespace BlackMisc
|
|||||||
//! Method used for implementing timestamp renewal.
|
//! Method used for implementing timestamp renewal.
|
||||||
void renewTimestamp(const QString &key, qint64 timestamp);
|
void renewTimestamp(const QString &key, qint64 timestamp);
|
||||||
|
|
||||||
|
//! Method used for implementing pinning values.
|
||||||
|
void pinValue(const QString &key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CDataCache();
|
CDataCache();
|
||||||
|
|
||||||
@@ -231,6 +242,7 @@ namespace BlackMisc
|
|||||||
CData::CCached(CDataCache::instance(), Trait::key(), Trait::isValid, Trait::defaultValue(), owner, slot)
|
CData::CCached(CDataCache::instance(), Trait::key(), Trait::isValid, Trait::defaultValue(), owner, slot)
|
||||||
{
|
{
|
||||||
if (Trait::timeToLive() >= 0) { CDataCache::instance()->setTimeToLive(Trait::key(), Trait::timeToLive()); }
|
if (Trait::timeToLive() >= 0) { CDataCache::instance()->setTimeToLive(Trait::key(), Trait::timeToLive()); }
|
||||||
|
if (Trait::isPinned()) { CDataCache::instance()->pinValue(Trait::key()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Reset the data to its default value.
|
//! Reset the data to its default value.
|
||||||
@@ -282,6 +294,10 @@ namespace BlackMisc
|
|||||||
//! Default is -1 which means value never becomes stale.
|
//! Default is -1 which means value never becomes stale.
|
||||||
static int timeToLive() { return -1; }
|
static int timeToLive() { return -1; }
|
||||||
|
|
||||||
|
//! If true, then value will be synchronously loaded when CDataCache is constructed.
|
||||||
|
//! Good for small, important values; bad for large ones.
|
||||||
|
static bool isPinned() { return false; }
|
||||||
|
|
||||||
//! Deleted default constructor.
|
//! Deleted default constructor.
|
||||||
CDataTrait() = delete;
|
CDataTrait() = delete;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user