##// END OF EJS Templates
Transits tokens in provider requests
Alexandre Leroux -
r376:313aeb6a2933
parent child
Show More
@@ -1,38 +1,40
1 1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 2 #define SCIQLOP_IDATAPROVIDER_H
3 3
4 4 #include <memory>
5 5
6 6 #include <QObject>
7 #include <QUuid>
7 8
8 9 #include <Common/MetaTypes.h>
9 10
10 11 #include <Data/SqpDateTime.h>
11 12
12 13 class DataProviderParameters;
13 14 class IDataSeries;
14 15
15 16 /**
16 17 * @brief The IDataProvider interface aims to declare a data provider.
17 18 *
18 19 * A data provider is an entity that generates data and returns it according to various parameters
19 20 * (time interval, product to retrieve the data, etc.)
20 21 *
21 22 * @sa IDataSeries
22 23 */
23 24 class IDataProvider : public QObject {
24 25
25 26 Q_OBJECT
26 27 public:
27 28 virtual ~IDataProvider() noexcept = default;
28 29
29 virtual void requestDataLoading(const QVector<SqpDateTime> &dateTimeList) = 0;
30 virtual void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) = 0;
30 31
31 32 signals:
32 void dataProvided(std::shared_ptr<IDataSeries> dateSerie, const SqpDateTime &dateTime);
33 void dataProvided(QUuid token, std::shared_ptr<IDataSeries> dateSerie,
34 const SqpDateTime &dateTime);
33 35 };
34 36
35 37 // Required for using shared_ptr in signals/slots
36 38 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
37 39
38 40 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,197 +1,205
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableCacheController.h>
3 3 #include <Variable/VariableController.h>
4 4 #include <Variable/VariableModel.h>
5 5
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Data/IDataProvider.h>
8 8 #include <Data/IDataSeries.h>
9 9 #include <Time/TimeController.h>
10 10
11 11 #include <QDateTime>
12 12 #include <QMutex>
13 13 #include <QThread>
14 #include <QUuid>
14 15 #include <QtCore/QItemSelectionModel>
15 16
16 17 #include <unordered_map>
17 18
18 19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19 20
20 21 struct VariableController::VariableControllerPrivate {
21 22 explicit VariableControllerPrivate(VariableController *parent)
22 23 : m_WorkingMutex{},
23 24 m_VariableModel{new VariableModel{parent}},
24 25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
25 26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
26 27 {
27 28 }
28 29
29 30 QMutex m_WorkingMutex;
30 31 /// Variable model. The VariableController has the ownership
31 32 VariableModel *m_VariableModel;
32 33 QItemSelectionModel *m_VariableSelectionModel;
33 34
34 35
35 36 TimeController *m_TimeController{nullptr};
36 37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
37 38
38 39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 40 m_VariableToProviderMap;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToToken;
40 42 };
41 43
42 44 VariableController::VariableController(QObject *parent)
43 45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
44 46 {
45 47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
46 48 << QThread::currentThread();
47 49 }
48 50
49 51 VariableController::~VariableController()
50 52 {
51 53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
52 54 << QThread::currentThread();
53 55 this->waitForFinish();
54 56 }
55 57
56 58 VariableModel *VariableController::variableModel() noexcept
57 59 {
58 60 return impl->m_VariableModel;
59 61 }
60 62
61 63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
62 64 {
63 65 return impl->m_VariableSelectionModel;
64 66 }
65 67
66 68 void VariableController::setTimeController(TimeController *timeController) noexcept
67 69 {
68 70 impl->m_TimeController = timeController;
69 71 }
70 72
71 73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
72 74 {
73 75 if (!variable) {
74 76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
75 77 return;
76 78 }
77 79
78 80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
79 81 // make some treatments before the deletion
80 82 emit variableAboutToBeDeleted(variable);
81 83
82 84 // Deletes provider
83 85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
84 86 qCDebug(LOG_VariableController())
85 87 << tr("Number of providers deleted for variable %1: %2")
86 88 .arg(variable->name(), QString::number(nbProvidersDeleted));
87 89
88 90 // Clears cache
89 91 impl->m_VariableCacheController->clear(variable);
90 92
91 93 // Deletes from model
92 94 impl->m_VariableModel->deleteVariable(variable);
93 95 }
94 96
95 97 void VariableController::deleteVariables(
96 98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
97 99 {
98 100 for (auto variable : qAsConst(variables)) {
99 101 deleteVariable(variable);
100 102 }
101 103 }
102 104
103 105 void VariableController::createVariable(const QString &name,
104 106 std::shared_ptr<IDataProvider> provider) noexcept
105 107 {
106 108
107 109 if (!impl->m_TimeController) {
108 110 qCCritical(LOG_VariableController())
109 111 << tr("Impossible to create variable: The time controller is null");
110 112 return;
111 113 }
112 114
113 115
114 116 /// @todo : for the moment :
115 117 /// - the provider is only used to retrieve data from the variable for its initialization, but
116 118 /// it will be retained later
117 119 /// - default data are generated for the variable, without taking into account the timerange set
118 120 /// in sciqlop
119 121 auto dateTime = impl->m_TimeController->dateTime();
120 122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
123 auto token = QUuid::createUuid();
121 124
122 125 // store the provider
123 126 impl->m_VariableToProviderMap[newVariable] = provider;
127 impl->m_VariableToToken[newVariable] = token;
124 128
125 129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
126 auto dataSeriesAcquired, auto dateTimeToPutInCache)
130 QUuid token, auto dataSeriesAcquired, auto dateTimeToPutInCache)
127 131 {
128 132 if (auto variable = varW.lock()) {
129 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
130 variable->setDataSeries(dataSeriesAcquired);
133 auto varToken = impl->m_VariableToToken.at(variable);
134 if (varToken == token) {
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 variable->setDataSeries(dataSeriesAcquired);
137 }
131 138 }
132 139 };
133 140
134 141 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
135 142 this->onRequestDataLoading(newVariable, dateTime);
136 143 }
137 144 }
138 145
139 146 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
140 147 {
141 148 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
142 149 << QThread::currentThread()->objectName();
143 150 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
144 151
145 152 for (const auto &selectedRow : qAsConst(selectedRows)) {
146 153 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
147 154 selectedVariable->setDateTime(dateTime);
148 155 this->onRequestDataLoading(selectedVariable, dateTime);
149 156 }
150 157 }
151 158 }
152 159
153 160
154 161 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
155 162 const SqpDateTime &dateTime)
156 163 {
157 164 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
158 165 << QThread::currentThread()->objectName();
159 166 // we want to load data of the variable for the dateTime.
160 167 // First we check if the cache contains some of them.
161 168 // For the other, we ask the provider to give them.
162 169 if (variable) {
163 170
164 171 auto dateTimeListNotInCache
165 172 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
166 173
167 174 if (!dateTimeListNotInCache.empty()) {
168 175 // Ask the provider for each data on the dateTimeListNotInCache
176 auto token = impl->m_VariableToToken.at(variable);
169 177 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
170 std::move(dateTimeListNotInCache));
178 token, std::move(dateTimeListNotInCache));
171 179 }
172 180 else {
173 181 emit variable->updated();
174 182 }
175 183 }
176 184 else {
177 185 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
178 186 }
179 187 }
180 188
181 189
182 190 void VariableController::initialize()
183 191 {
184 192 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
185 193 impl->m_WorkingMutex.lock();
186 194 qCDebug(LOG_VariableController()) << tr("VariableController init END");
187 195 }
188 196
189 197 void VariableController::finalize()
190 198 {
191 199 impl->m_WorkingMutex.unlock();
192 200 }
193 201
194 202 void VariableController::waitForFinish()
195 203 {
196 204 QMutexLocker locker{&impl->m_WorkingMutex};
197 205 }
@@ -1,26 +1,26
1 1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 2 #define SCIQLOP_COSINUSPROVIDER_H
3 3
4 4 #include "MockPluginGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
11 11
12 12 /**
13 13 * @brief The CosinusProvider class is an example of how a data provider can generate data
14 14 */
15 15 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 16 public:
17 void requestDataLoading(const QVector<SqpDateTime> &dateTimeList) override;
17 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
18 18
19 19
20 20 private:
21 21 /// @sa IDataProvider::retrieveData()
22 22 std::shared_ptr<IDataSeries> retrieveData(const DataProviderParameters &parameters) const;
23 23 std::shared_ptr<IDataSeries> retrieveDataSeries(const SqpDateTime &dateTime);
24 24 };
25 25
26 26 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,50 +1,50
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QDateTime>
9 9 #include <QThread>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12 12
13 13 std::shared_ptr<IDataSeries>
14 14 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
15 15 {
16 16 auto dateTime = parameters.m_Time;
17 17
18 18 auto dataIndex = 0;
19 19
20 20 // Gets the timerange from the parameters
21 21 double freq = 100.0;
22 22 double start = dateTime.m_TStart * freq; // 100 htz
23 23 double end = dateTime.m_TEnd * freq; // 100 htz
24 24
25 25 // We assure that timerange is valid
26 26 if (end < start) {
27 27 std::swap(start, end);
28 28 }
29 29
30 30 // Generates scalar series containing cosinus values (one value per second)
31 31 auto scalarSeries
32 32 = std::make_shared<ScalarSeries>(end - start, Unit{QStringLiteral("t"), true}, Unit{});
33 33
34 34 for (auto time = start; time < end; ++time, ++dataIndex) {
35 35 const auto timeOnFreq = time / freq;
36 36 scalarSeries->setData(dataIndex, timeOnFreq, std::cos(timeOnFreq));
37 37 }
38 38 return scalarSeries;
39 39 }
40 40
41 void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList)
41 void CosinusProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
42 42 {
43 43 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
44 44 << QThread::currentThread()->objectName();
45 45 // NOTE: Try to use multithread if possible
46 46 for (const auto &dateTime : dateTimeList) {
47 47 auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime});
48 emit dataProvided(scalarSeries, dateTime);
48 emit dataProvided(token, scalarSeries, dateTime);
49 49 }
50 50 }
General Comments 0
You need to be logged in to leave comments. Login now