From 527fddc441a1c103e8d8ece4fe6df3154dacb7e9 2017-06-23 14:26:20 From: mperrinel Date: 2017-06-23 14:26:20 Subject: [PATCH] Implementation of the cach interval algoritm --- diff --git a/core/src/Variable/VariableCacheController.cpp b/core/src/Variable/VariableCacheController.cpp index 1db6df5..cade905 100644 --- a/core/src/Variable/VariableCacheController.cpp +++ b/core/src/Variable/VariableCacheController.cpp @@ -5,8 +5,16 @@ struct VariableCacheController::VariableCacheControllerPrivate { - std::unordered_map, std::list > + std::unordered_map, QVector > m_VariableToSqpDateTimeListMap; + + void addInCacheDataByEnd(const SqpDateTime &dateTime, QVector &dateTimeList, + QVector ¬InCache, int cacheIndex, + double currentTStart); + + void addInCacheDataByStart(const SqpDateTime &dateTime, QVector &dateTimeList, + QVector ¬InCache, int cacheIndex, + double currentTStart); }; @@ -23,3 +31,81 @@ void VariableCacheController::addDateTime(std::shared_ptr variable, impl->m_VariableToSqpDateTimeListMap[variable].push_back(dateTime); } } + +QVector +VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr variable, + const SqpDateTime &dateTime) +{ + auto notInCache = QVector{}; + + // 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) + + impl->addInCacheDataByStart(dateTime, impl->m_VariableToSqpDateTimeListMap.at(variable), + notInCache, 0, dateTime.m_TStart); + + return notInCache; +} + + +void VariableCacheController::VariableCacheControllerPrivate::addInCacheDataByEnd( + const SqpDateTime &dateTime, QVector &dateTimeList, + QVector ¬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 &dateTimeList, + QVector ¬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]; + auto cacheIndexJ = cacheIndex; + if (currentTStart < currentDateTimeI.m_TStart) { + + // ts localised between to interval: let's localized te + addInCacheDataByEnd(dateTime, dateTimeList, notInCache, cacheIndexJ, currentTStart); + } + else if (dateTime.m_TStart < 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); + } + else { + // ts not localised before the current interval: we need to look at the next interval + addInCacheDataByStart(dateTime, dateTimeList, notInCache, ++cacheIndex, currentTStart); + } +} diff --git a/core/tests/Variable/TestVariableCacheController.cpp b/core/tests/Variable/TestVariableCacheController.cpp new file mode 100644 index 0000000..fa97f28 --- /dev/null +++ b/core/tests/Variable/TestVariableCacheController.cpp @@ -0,0 +1,245 @@ +#include +#include + +#include +#include + +#include + +class TestVariableCacheController : public QObject { + Q_OBJECT + +private slots: + void testProvideNotInCacheDateTimeList(); +}; + + +void TestVariableCacheController::testProvideNotInCacheDateTimeList() +{ + VariableCacheController variableCacheController{}; + + auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; + auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; + auto sqp0 = SqpDateTime{static_cast(ts0.toMSecsSinceEpoch()), + static_cast(te0.toMSecsSinceEpoch())}; + + auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}}; + auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}}; + auto sqp1 = SqpDateTime{static_cast(ts1.toMSecsSinceEpoch()), + static_cast(te1.toMSecsSinceEpoch())}; + + auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}}; + auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}}; + auto sqp2 = SqpDateTime{static_cast(ts2.toMSecsSinceEpoch()), + static_cast(te2.toMSecsSinceEpoch())}; + + auto var0 = std::make_shared("", "", "", sqp0); + + variableCacheController.addDateTime(var0, sqp0); + variableCacheController.addDateTime(var0, sqp1); + variableCacheController.addDateTime(var0, sqp2); + + // first case [ts,te] < ts0 + auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; + auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; + auto sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + auto notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + auto notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + + // second case ts < ts0 && ts0 < te <= te0 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts0.toMSecsSinceEpoch())); + + // 3th case ts < ts0 && te0 < te <= ts1 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 2); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts0.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(1); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 4th case ts < ts0 && ts1 < te <= te1 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 2); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts0.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(1); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts1.toMSecsSinceEpoch())); + + // 5th case ts < ts0 && te3 < te + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 4); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts0.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(1); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts1.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(2); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te1.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts2.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(3); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te2.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + + // 6th case ts2 < ts + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 45, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 7th case ts = te0 && te < ts1 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 8th case ts0 < ts < te0 && te < ts1 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 9th case ts0 < ts < te0 && ts1 < te < te1 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te0.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts1.toMSecsSinceEpoch())); + + // 10th case te1 < ts < te < ts2 + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 9, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 1); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 11th case te0 < ts < ts1 && te3 < te + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 3); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts1.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(1); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te1.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts2.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(2); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te2.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); + + // 12th case te0 < ts < ts1 && te3 < te + ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; + te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}}; + sqp = SqpDateTime{static_cast(ts.toMSecsSinceEpoch()), + static_cast(te.toMSecsSinceEpoch())}; + + notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); + + QCOMPARE(notInCach.size(), 2); + notInCashSqp = notInCach.first(); + QCOMPARE(notInCashSqp.m_TStart, static_cast(ts.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(ts1.toMSecsSinceEpoch())); + + notInCashSqp = notInCach.at(1); + QCOMPARE(notInCashSqp.m_TStart, static_cast(te1.toMSecsSinceEpoch())); + QCOMPARE(notInCashSqp.m_TEnd, static_cast(te.toMSecsSinceEpoch())); +} + +QTEST_MAIN(TestVariableCacheController) +#include "TestVariableCacheController.moc"