VariableCacheController.cpp
228 lines
| 9.5 KiB
| text/x-c
|
CppLexer
r225 | #include "Variable/VariableCacheController.h" | |||
#include "Variable/Variable.h" | ||||
#include <unordered_map> | ||||
r338 | #include <QThread> | |||
r293 | Q_LOGGING_CATEGORY(LOG_VariableCacheController, "VariableCacheController") | |||
r225 | struct VariableCacheController::VariableCacheControllerPrivate { | |||
r229 | std::unordered_map<std::shared_ptr<Variable>, QVector<SqpDateTime> > | |||
r225 | m_VariableToSqpDateTimeListMap; | |||
r229 | ||||
void addInCacheDataByEnd(const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, | ||||
QVector<SqpDateTime> ¬InCache, int cacheIndex, | ||||
double currentTStart); | ||||
void addInCacheDataByStart(const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, | ||||
QVector<SqpDateTime> ¬InCache, int cacheIndex, | ||||
double currentTStart); | ||||
r230 | ||||
void addDateTimeRecurse(const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, | ||||
int cacheIndex); | ||||
r225 | }; | |||
VariableCacheController::VariableCacheController(QObject *parent) | ||||
r243 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableCacheControllerPrivate>()} | |||
r225 | { | |||
} | ||||
void VariableCacheController::addDateTime(std::shared_ptr<Variable> variable, | ||||
const SqpDateTime &dateTime) | ||||
{ | ||||
r340 | qCInfo(LOG_VariableCacheController()) << "VariableCacheController::addDateTime" | |||
<< QThread::currentThread()->objectName(); | ||||
r225 | if (variable) { | |||
r230 | auto findVariableIte = impl->m_VariableToSqpDateTimeListMap.find(variable); | |||
if (findVariableIte == impl->m_VariableToSqpDateTimeListMap.end()) { | ||||
impl->m_VariableToSqpDateTimeListMap[variable].push_back(dateTime); | ||||
} | ||||
else { | ||||
// addDateTime modify the list<SqpDateTime> of the variable in a way to ensure | ||||
// that the list is ordered : l(0) < l(1). We assume also a < b | ||||
// (with a & b of type SqpDateTime) means ts(b) > te(a) | ||||
// The algorithm will try the merge of two interval: | ||||
// - dateTime will be compare with the first interval of the list: | ||||
// A: if it is inferior, it will be inserted and it's finished. | ||||
// B: if it is in intersection, it will be merge then the merged one | ||||
// will be compared to the next interval. The old one is remove from the list | ||||
// C: if it is superior, we do the same with the next interval of the list | ||||
r300 | try { | |||
impl->addDateTimeRecurse(dateTime, | ||||
impl->m_VariableToSqpDateTimeListMap.at(variable), 0); | ||||
} | ||||
catch (const std::out_of_range &e) { | ||||
r319 | qCWarning(LOG_VariableCacheController()) << "addDateTime" << e.what(); | |||
r300 | } | |||
r230 | } | |||
r225 | } | |||
} | ||||
r229 | ||||
|
r331 | void VariableCacheController::clear(std::shared_ptr<Variable> variable) noexcept | ||
{ | ||||
if (!variable) { | ||||
qCCritical(LOG_VariableCacheController()) << "Can't clear variable cache: variable is null"; | ||||
return; | ||||
} | ||||
auto nbEntries = impl->m_VariableToSqpDateTimeListMap.erase(variable); | ||||
auto clearCacheMessage | ||||
= (nbEntries != 0) | ||||
? tr("Variable cache cleared for variable %1").arg(variable->name()) | ||||
: tr("No deletion of variable cache: no cache was associated with the variable"); | ||||
qCDebug(LOG_VariableCacheController()) << clearCacheMessage; | ||||
} | ||||
r229 | QVector<SqpDateTime> | |||
VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, | ||||
const SqpDateTime &dateTime) | ||||
{ | ||||
r338 | qCInfo(LOG_VariableCacheController()) | |||
<< "VariableCacheController::provideNotInCacheDateTimeList" | ||||
<< QThread::currentThread()->objectName(); | ||||
r229 | auto notInCache = QVector<SqpDateTime>{}; | |||
// This algorithm is recursif. The idea is to localise the start time then the end time in the | ||||
// list of date time request associated to the variable | ||||
// We assume that the list is ordered in a way that l(0) < l(1). We assume also a < b | ||||
// (with a & b of type SqpDateTime) means ts(b) > te(a) | ||||
r319 | auto it = impl->m_VariableToSqpDateTimeListMap.find(variable); | |||
if (it != impl->m_VariableToSqpDateTimeListMap.end()) { | ||||
impl->addInCacheDataByStart(dateTime, it->second, notInCache, 0, dateTime.m_TStart); | ||||
r300 | } | |||
r319 | else { | |||
notInCache << dateTime; | ||||
r300 | } | |||
r229 | ||||
return notInCache; | ||||
} | ||||
r230 | QVector<SqpDateTime> | |||
VariableCacheController::dateCacheList(std::shared_ptr<Variable> variable) const noexcept | ||||
{ | ||||
r340 | qCInfo(LOG_VariableCacheController()) << "VariableCacheController::dateCacheList" | |||
<< QThread::currentThread()->objectName(); | ||||
r300 | try { | |||
return impl->m_VariableToSqpDateTimeListMap.at(variable); | ||||
} | ||||
catch (const std::out_of_range &e) { | ||||
r303 | qCWarning(LOG_VariableCacheController()) << e.what(); | |||
r300 | return QVector<SqpDateTime>{}; | |||
} | ||||
r230 | } | |||
void VariableCacheController::VariableCacheControllerPrivate::addDateTimeRecurse( | ||||
const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, int cacheIndex) | ||||
{ | ||||
const auto dateTimeListSize = dateTimeList.count(); | ||||
if (cacheIndex >= dateTimeListSize) { | ||||
dateTimeList.push_back(dateTime); | ||||
// there is no anymore interval to compore, we can just push_back it | ||||
return; | ||||
} | ||||
auto currentDateTime = dateTimeList[cacheIndex]; | ||||
if (dateTime.m_TEnd < currentDateTime.m_TStart) { | ||||
// The compared one is < to current one compared, we can insert it | ||||
dateTimeList.insert(cacheIndex, dateTime); | ||||
} | ||||
else if (dateTime.m_TStart > currentDateTime.m_TEnd) { | ||||
// The compared one is > to current one compared we can comparet if to the next one | ||||
addDateTimeRecurse(dateTime, dateTimeList, ++cacheIndex); | ||||
} | ||||
else { | ||||
// Merge cases: we need to merge the two interval, remove the old one from the list then | ||||
// rerun the algo from this index with the merged interval | ||||
auto mTStart = std::min(dateTime.m_TStart, currentDateTime.m_TStart); | ||||
auto mTEnd = std::max(dateTime.m_TEnd, currentDateTime.m_TEnd); | ||||
auto mergeDateTime = SqpDateTime{mTStart, mTEnd}; | ||||
dateTimeList.remove(cacheIndex); | ||||
addDateTimeRecurse(mergeDateTime, dateTimeList, cacheIndex); | ||||
} | ||||
} | ||||
r229 | ||||
void VariableCacheController::VariableCacheControllerPrivate::addInCacheDataByEnd( | ||||
const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, | ||||
QVector<SqpDateTime> ¬InCache, int cacheIndex, double currentTStart) | ||||
{ | ||||
const auto dateTimeListSize = dateTimeList.count(); | ||||
if (cacheIndex >= dateTimeListSize) { | ||||
if (currentTStart < dateTime.m_TEnd) { | ||||
// te localised after all other interval: The last interval is [currentTsart, te] | ||||
notInCache.push_back(SqpDateTime{currentTStart, dateTime.m_TEnd}); | ||||
} | ||||
return; | ||||
} | ||||
auto currentDateTimeJ = dateTimeList[cacheIndex]; | ||||
if (dateTime.m_TEnd <= currentDateTimeJ.m_TStart) { | ||||
// te localised between to interval: The last interval is [currentTsart, te] | ||||
notInCache.push_back(SqpDateTime{currentTStart, dateTime.m_TEnd}); | ||||
} | ||||
else { | ||||
notInCache.push_back(SqpDateTime{currentTStart, currentDateTimeJ.m_TStart}); | ||||
if (dateTime.m_TEnd > currentDateTimeJ.m_TEnd) { | ||||
// te not localised before the current interval: we need to look at the next interval | ||||
addInCacheDataByEnd(dateTime, dateTimeList, notInCache, ++cacheIndex, | ||||
currentDateTimeJ.m_TEnd); | ||||
} | ||||
} | ||||
} | ||||
void VariableCacheController::VariableCacheControllerPrivate::addInCacheDataByStart( | ||||
const SqpDateTime &dateTime, QVector<SqpDateTime> &dateTimeList, | ||||
QVector<SqpDateTime> ¬InCache, int cacheIndex, double currentTStart) | ||||
{ | ||||
const auto dateTimeListSize = dateTimeList.count(); | ||||
if (cacheIndex >= dateTimeListSize) { | ||||
// ts localised after all other interval: The last interval is [ts, te] | ||||
notInCache.push_back(SqpDateTime{currentTStart, dateTime.m_TEnd}); | ||||
return; | ||||
} | ||||
auto currentDateTimeI = dateTimeList[cacheIndex]; | ||||
if (currentTStart < currentDateTimeI.m_TStart) { | ||||
// ts localised between to interval: let's localized te | ||||
r243 | addInCacheDataByEnd(dateTime, dateTimeList, notInCache, cacheIndex, currentTStart); | |||
r229 | } | |||
r293 | else if (currentTStart < currentDateTimeI.m_TEnd) { | |||
if (dateTime.m_TEnd > currentDateTimeI.m_TEnd) { | ||||
// ts not localised before the current interval: we need to look at the next interval | ||||
// We can assume now current tstart is the last interval tend, because data between them | ||||
// are | ||||
// in the cache | ||||
addInCacheDataByStart(dateTime, dateTimeList, notInCache, ++cacheIndex, | ||||
currentDateTimeI.m_TEnd); | ||||
} | ||||
r229 | } | |||
else { | ||||
// ts not localised before the current interval: we need to look at the next interval | ||||
addInCacheDataByStart(dateTime, dateTimeList, notInCache, ++cacheIndex, currentTStart); | ||||
} | ||||
} | ||||
r293 | ||||
r300 | void VariableCacheController::displayCache(std::shared_ptr<Variable> variable) const | |||
r293 | { | |||
r300 | auto variableDateTimeList = impl->m_VariableToSqpDateTimeListMap.find(variable); | |||
if (variableDateTimeList != impl->m_VariableToSqpDateTimeListMap.end()) { | ||||
r340 | qCInfo(LOG_VariableCacheController()) << tr("VariableCacheController::displayCache") | |||
<< variableDateTimeList->second; | ||||
r300 | } | |||
else { | ||||
qCWarning(LOG_VariableCacheController()) | ||||
<< tr("Cannot display a variable that is not in the cache"); | ||||
} | ||||
r293 | } | |||