##// END OF EJS Templates
Implementation of varRequestId aborting to permit to cancel a request...
perrinel -
r826:7fcfa38ae909
parent child
Show More
@@ -1,416 +1,415
1 #include "Variable/VariableAcquisitionWorker.h"
1 #include "Variable/VariableAcquisitionWorker.h"
2
2
3 #include "Variable/Variable.h"
3 #include "Variable/Variable.h"
4
4
5 #include <Data/AcquisitionRequest.h>
5 #include <Data/AcquisitionRequest.h>
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <unordered_map>
8 #include <unordered_map>
9 #include <utility>
9 #include <utility>
10
10
11 #include <QMutex>
11 #include <QMutex>
12 #include <QReadWriteLock>
12 #include <QReadWriteLock>
13 #include <QThread>
13 #include <QThread>
14
14
15 #include <cmath>
15 #include <cmath>
16
16
17 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
17 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
18
18
19 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
19 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
20
20
21 explicit VariableAcquisitionWorkerPrivate(VariableAcquisitionWorker *parent)
21 explicit VariableAcquisitionWorkerPrivate(VariableAcquisitionWorker *parent)
22 : m_Lock{QReadWriteLock::Recursive}, q{parent}
22 : m_Lock{QReadWriteLock::Recursive}, q{parent}
23 {
23 {
24 }
24 }
25
25
26 void lockRead() { m_Lock.lockForRead(); }
26 void lockRead() { m_Lock.lockForRead(); }
27 void lockWrite() { m_Lock.lockForWrite(); }
27 void lockWrite() { m_Lock.lockForWrite(); }
28 void unlock() { m_Lock.unlock(); }
28 void unlock() { m_Lock.unlock(); }
29
29
30 void removeVariableRequest(QUuid vIdentifier);
30 void removeVariableRequest(QUuid vIdentifier);
31
31
32 /// Remove the current request and execute the next one if exist
32 /// Remove the current request and execute the next one if exist
33 void updateToNextRequest(QUuid vIdentifier);
33 void updateToNextRequest(QUuid vIdentifier);
34
34
35 /// Remove and/or abort all AcqRequest in link with varRequestId
35 /// Remove and/or abort all AcqRequest in link with varRequestId
36 void cancelVarRequest(QUuid varRequestId);
36 void cancelVarRequest(QUuid varRequestId);
37 void removeAcqRequest(QUuid acqRequestId);
37 void removeAcqRequest(QUuid acqRequestId);
38
38
39 QMutex m_WorkingMutex;
39 QMutex m_WorkingMutex;
40 QReadWriteLock m_Lock;
40 QReadWriteLock m_Lock;
41
41
42 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
42 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
43 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
43 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
44 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
44 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
45 VariableAcquisitionWorker *q;
45 VariableAcquisitionWorker *q;
46 };
46 };
47
47
48
48
49 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
49 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
50 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>(this)}
50 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>(this)}
51 {
51 {
52 }
52 }
53
53
54 VariableAcquisitionWorker::~VariableAcquisitionWorker()
54 VariableAcquisitionWorker::~VariableAcquisitionWorker()
55 {
55 {
56 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
56 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
57 << QThread::currentThread();
57 << QThread::currentThread();
58 this->waitForFinish();
58 this->waitForFinish();
59 }
59 }
60
60
61
61
62 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
62 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
63 SqpRange rangeRequested,
63 SqpRange rangeRequested,
64 SqpRange cacheRangeRequested,
64 SqpRange cacheRangeRequested,
65 DataProviderParameters parameters,
65 DataProviderParameters parameters,
66 std::shared_ptr<IDataProvider> provider)
66 std::shared_ptr<IDataProvider> provider)
67 {
67 {
68 qCDebug(LOG_VariableAcquisitionWorker())
68 qCDebug(LOG_VariableAcquisitionWorker())
69 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
69 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
70 auto varRequestIdCanceled = QUuid();
70 auto varRequestIdCanceled = QUuid();
71
71
72 // Request creation
72 // Request creation
73 auto acqRequest = AcquisitionRequest{};
73 auto acqRequest = AcquisitionRequest{};
74 qCDebug(LOG_VariableAcquisitionWorker()) << tr("PushVariableRequest ") << vIdentifier
74 qCDebug(LOG_VariableAcquisitionWorker()) << tr("PushVariableRequest ") << vIdentifier
75 << varRequestId;
75 << varRequestId;
76 acqRequest.m_VarRequestId = varRequestId;
76 acqRequest.m_VarRequestId = varRequestId;
77 acqRequest.m_vIdentifier = vIdentifier;
77 acqRequest.m_vIdentifier = vIdentifier;
78 acqRequest.m_DataProviderParameters = parameters;
78 acqRequest.m_DataProviderParameters = parameters;
79 acqRequest.m_RangeRequested = rangeRequested;
79 acqRequest.m_RangeRequested = rangeRequested;
80 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
80 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
81 acqRequest.m_Size = parameters.m_Times.size();
81 acqRequest.m_Size = parameters.m_Times.size();
82 acqRequest.m_Provider = provider;
82 acqRequest.m_Provider = provider;
83
83
84
84
85 // Register request
85 // Register request
86 impl->lockWrite();
86 impl->lockWrite();
87 impl->m_AcqIdentifierToAcqRequestMap.insert(
87 impl->m_AcqIdentifierToAcqRequestMap.insert(
88 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
88 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
89
89
90 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
90 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
91 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
91 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
92 // A current request already exists, we can replace the next one
92 // A current request already exists, we can replace the next one
93 auto oldAcqId = it->second.second;
93 auto oldAcqId = it->second.second;
94 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(oldAcqId);
94 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(oldAcqId);
95 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
95 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
96 auto oldAcqRequest = acqIdentifierToAcqRequestMapIt->second;
96 auto oldAcqRequest = acqIdentifierToAcqRequestMapIt->second;
97 varRequestIdCanceled = oldAcqRequest.m_VarRequestId;
97 varRequestIdCanceled = oldAcqRequest.m_VarRequestId;
98 }
98 }
99
99
100 it->second.second = acqRequest.m_AcqIdentifier;
100 it->second.second = acqRequest.m_AcqIdentifier;
101 impl->unlock();
101 impl->unlock();
102
102
103 // remove old acqIdentifier from the worker
103 // remove old acqIdentifier from the worker
104 impl->cancelVarRequest(varRequestIdCanceled);
104 impl->cancelVarRequest(varRequestIdCanceled);
105 // impl->m_AcqIdentifierToAcqRequestMap.erase(oldAcqId);
106 }
105 }
107 else {
106 else {
108 // First request for the variable, it must be stored and executed
107 // First request for the variable, it must be stored and executed
109 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
108 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
110 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
109 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
111 impl->unlock();
110 impl->unlock();
112
111
113 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
112 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
114 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
113 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
115 }
114 }
116
115
117 return varRequestIdCanceled;
116 return varRequestIdCanceled;
118 }
117 }
119
118
120 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
119 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
121 {
120 {
122 impl->lockRead();
121 impl->lockRead();
123
122
124 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
123 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
125 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
124 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
126 auto currentAcqId = it->second.first;
125 auto currentAcqId = it->second.first;
127
126
128 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(currentAcqId);
127 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(currentAcqId);
129 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
128 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
130 auto request = it->second;
129 auto request = it->second;
131 impl->unlock();
130 impl->unlock();
132
131
133 // Remove the current request from the worker
132 // Remove the current request from the worker
134 impl->updateToNextRequest(vIdentifier);
133 impl->updateToNextRequest(vIdentifier);
135
134
136 // notify the request aborting to the provider
135 // notify the request aborting to the provider
137 request.m_Provider->requestDataAborting(currentAcqId);
136 request.m_Provider->requestDataAborting(currentAcqId);
138 }
137 }
139 else {
138 else {
140 impl->unlock();
139 impl->unlock();
141 qCWarning(LOG_VariableAcquisitionWorker())
140 qCWarning(LOG_VariableAcquisitionWorker())
142 << tr("Impossible to abort an unknown acquisition request") << currentAcqId;
141 << tr("Impossible to abort an unknown acquisition request") << currentAcqId;
143 }
142 }
144 }
143 }
145 else {
144 else {
146 impl->unlock();
145 impl->unlock();
147 }
146 }
148 }
147 }
149
148
150 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
149 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
151 double progress)
150 double progress)
152 {
151 {
153 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableRetrieveDataInProgress ")
152 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableRetrieveDataInProgress ")
154 << acqIdentifier << progress;
153 << acqIdentifier << progress;
155 impl->lockRead();
154 impl->lockRead();
156 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
155 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
157 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
156 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
158 auto currentPartSize = (aIdToARit->second.m_Size != 0) ? 100 / aIdToARit->second.m_Size : 0;
157 auto currentPartSize = (aIdToARit->second.m_Size != 0) ? 100 / aIdToARit->second.m_Size : 0;
159
158
160 auto currentPartProgress
159 auto currentPartProgress
161 = std::isnan(progress) ? 0.0 : (progress * currentPartSize) / 100.0;
160 = std::isnan(progress) ? 0.0 : (progress * currentPartSize) / 100.0;
162 auto currentAlreadyProgress = aIdToARit->second.m_Progression * currentPartSize;
161 auto currentAlreadyProgress = aIdToARit->second.m_Progression * currentPartSize;
163
162
164 auto finalProgression = currentAlreadyProgress + currentPartProgress;
163 auto finalProgression = currentAlreadyProgress + currentPartProgress;
165 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, finalProgression);
164 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, finalProgression);
166 qCDebug(LOG_VariableAcquisitionWorker())
165 qCDebug(LOG_VariableAcquisitionWorker())
167 << tr("TORM: onVariableRetrieveDataInProgress ")
166 << tr("TORM: onVariableRetrieveDataInProgress ")
168 << QThread::currentThread()->objectName() << aIdToARit->second.m_vIdentifier
167 << QThread::currentThread()->objectName() << aIdToARit->second.m_vIdentifier
169 << currentPartSize << currentAlreadyProgress << currentPartProgress << finalProgression;
168 << currentPartSize << currentAlreadyProgress << currentPartProgress << finalProgression;
170 if (finalProgression == 100.0) {
169 if (finalProgression == 100.0) {
171 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, 0.0);
170 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, 0.0);
172 }
171 }
173 }
172 }
174 impl->unlock();
173 impl->unlock();
175 }
174 }
176
175
177 void VariableAcquisitionWorker::onVariableAcquisitionFailed(QUuid acqIdentifier)
176 void VariableAcquisitionWorker::onVariableAcquisitionFailed(QUuid acqIdentifier)
178 {
177 {
179 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed")
178 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed")
180 << QThread::currentThread();
179 << QThread::currentThread();
181 impl->lockRead();
180 impl->lockRead();
182 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
181 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
183 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
182 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
184 auto request = it->second;
183 auto request = it->second;
185 impl->unlock();
184 impl->unlock();
186 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed")
185 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed")
187 << acqIdentifier << request.m_vIdentifier
186 << acqIdentifier << request.m_vIdentifier
188 << QThread::currentThread();
187 << QThread::currentThread();
189 emit variableCanceledRequested(request.m_vIdentifier);
188 emit variableCanceledRequested(request.m_vIdentifier);
190 }
189 }
191 else {
190 else {
192 impl->unlock();
191 impl->unlock();
193 // TODO log no acqIdentifier recognized
192 // TODO log no acqIdentifier recognized
194 }
193 }
195 }
194 }
196
195
197 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
196 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
198 std::shared_ptr<IDataSeries> dataSeries,
197 std::shared_ptr<IDataSeries> dataSeries,
199 SqpRange dataRangeAcquired)
198 SqpRange dataRangeAcquired)
200 {
199 {
201 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableDataAcquired on range ")
200 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableDataAcquired on range ")
202 << acqIdentifier << dataRangeAcquired;
201 << acqIdentifier << dataRangeAcquired;
203 impl->lockWrite();
202 impl->lockWrite();
204 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
203 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
205 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
204 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
206 // Store the result
205 // Store the result
207 auto dataPacket = AcquisitionDataPacket{};
206 auto dataPacket = AcquisitionDataPacket{};
208 dataPacket.m_Range = dataRangeAcquired;
207 dataPacket.m_Range = dataRangeAcquired;
209 dataPacket.m_DateSeries = dataSeries;
208 dataPacket.m_DateSeries = dataSeries;
210
209
211 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
210 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
212 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
211 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
213 // A current request result already exists, we can update it
212 // A current request result already exists, we can update it
214 aIdToADPVit->second.push_back(dataPacket);
213 aIdToADPVit->second.push_back(dataPacket);
215 }
214 }
216 else {
215 else {
217 // First request result for the variable, it must be stored
216 // First request result for the variable, it must be stored
218 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
217 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
219 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
218 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
220 }
219 }
221
220
222
221
223 // Decrement the counter of the request
222 // Decrement the counter of the request
224 auto &acqRequest = aIdToARit->second;
223 auto &acqRequest = aIdToARit->second;
225 acqRequest.m_Progression = acqRequest.m_Progression + 1;
224 acqRequest.m_Progression = acqRequest.m_Progression + 1;
226
225
227 // if the counter is 0, we can return data then run the next request if it exists and
226 // if the counter is 0, we can return data then run the next request if it exists and
228 // removed the finished request
227 // removed the finished request
229 if (acqRequest.m_Size == acqRequest.m_Progression) {
228 if (acqRequest.m_Size == acqRequest.m_Progression) {
230 auto varId = acqRequest.m_vIdentifier;
229 auto varId = acqRequest.m_vIdentifier;
231 auto rangeRequested = acqRequest.m_RangeRequested;
230 auto rangeRequested = acqRequest.m_RangeRequested;
232 auto cacheRangeRequested = acqRequest.m_CacheRangeRequested;
231 auto cacheRangeRequested = acqRequest.m_CacheRangeRequested;
233 // Return the data
232 // Return the data
234 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
233 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
235 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
234 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
236 emit dataProvided(varId, rangeRequested, cacheRangeRequested, aIdToADPVit->second);
235 emit dataProvided(varId, rangeRequested, cacheRangeRequested, aIdToADPVit->second);
237 }
236 }
238 impl->unlock();
237 impl->unlock();
239
238
240 // Update to the next request
239 // Update to the next request
241 impl->updateToNextRequest(acqRequest.m_vIdentifier);
240 impl->updateToNextRequest(acqRequest.m_vIdentifier);
242 }
241 }
243 else {
242 else {
244 impl->unlock();
243 impl->unlock();
245 }
244 }
246 }
245 }
247 else {
246 else {
248 impl->unlock();
247 impl->unlock();
249 qCWarning(LOG_VariableAcquisitionWorker())
248 qCWarning(LOG_VariableAcquisitionWorker())
250 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
249 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
251 }
250 }
252 }
251 }
253
252
254 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
253 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
255 {
254 {
256 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
255 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
257 impl->lockRead();
256 impl->lockRead();
258 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
257 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
259 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
258 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
260 auto request = it->second;
259 auto request = it->second;
261 impl->unlock();
260 impl->unlock();
262 emit variableRequestInProgress(request.m_vIdentifier, 0.1);
261 emit variableRequestInProgress(request.m_vIdentifier, 0.1);
263 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
262 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
264 }
263 }
265 else {
264 else {
266 impl->unlock();
265 impl->unlock();
267 // TODO log no acqIdentifier recognized
266 // TODO log no acqIdentifier recognized
268 }
267 }
269 }
268 }
270
269
271 void VariableAcquisitionWorker::initialize()
270 void VariableAcquisitionWorker::initialize()
272 {
271 {
273 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
272 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
274 << QThread::currentThread();
273 << QThread::currentThread();
275 impl->m_WorkingMutex.lock();
274 impl->m_WorkingMutex.lock();
276 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
275 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
277 }
276 }
278
277
279 void VariableAcquisitionWorker::finalize()
278 void VariableAcquisitionWorker::finalize()
280 {
279 {
281 impl->m_WorkingMutex.unlock();
280 impl->m_WorkingMutex.unlock();
282 }
281 }
283
282
284 void VariableAcquisitionWorker::waitForFinish()
283 void VariableAcquisitionWorker::waitForFinish()
285 {
284 {
286 QMutexLocker locker{&impl->m_WorkingMutex};
285 QMutexLocker locker{&impl->m_WorkingMutex};
287 }
286 }
288
287
289 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
288 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
290 QUuid vIdentifier)
289 QUuid vIdentifier)
291 {
290 {
292 lockWrite();
291 lockWrite();
293 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
292 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
294
293
295 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
294 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
296 // A current request already exists, we can replace the next one
295 // A current request already exists, we can replace the next one
297
296
298 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
297 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
299 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
298 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
300
299
301 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
300 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
302 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
301 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
303 }
302 }
304 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
303 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
305 unlock();
304 unlock();
306 }
305 }
307
306
308 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
307 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
309 QUuid vIdentifier)
308 QUuid vIdentifier)
310 {
309 {
311 lockRead();
310 lockRead();
312 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
311 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
313 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
312 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
314 if (it->second.second.isNull()) {
313 if (it->second.second.isNull()) {
315 unlock();
314 unlock();
316 // There is no next request, we can remove the variable request
315 // There is no next request, we can remove the variable request
317 removeVariableRequest(vIdentifier);
316 removeVariableRequest(vIdentifier);
318 }
317 }
319 else {
318 else {
320 auto acqIdentifierToRemove = it->second.first;
319 auto acqIdentifierToRemove = it->second.first;
321 // Move the next request to the current request
320 // Move the next request to the current request
322 auto nextRequestId = it->second.second;
321 auto nextRequestId = it->second.second;
323 it->second.first = nextRequestId;
322 it->second.first = nextRequestId;
324 it->second.second = QUuid();
323 it->second.second = QUuid();
325 unlock();
324 unlock();
326 // Remove AcquisitionRequest and results;
325 // Remove AcquisitionRequest and results;
327 lockWrite();
326 lockWrite();
328 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
327 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
329 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
328 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
330 unlock();
329 unlock();
331 // Execute the current request
330 // Execute the current request
332 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
331 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
333 Q_ARG(QUuid, nextRequestId));
332 Q_ARG(QUuid, nextRequestId));
334 }
333 }
335 }
334 }
336 else {
335 else {
337 unlock();
336 unlock();
338 qCCritical(LOG_VariableAcquisitionWorker())
337 qCCritical(LOG_VariableAcquisitionWorker())
339 << tr("Impossible to execute the acquisition on an unfound variable ");
338 << tr("Impossible to execute the acquisition on an unfound variable ");
340 }
339 }
341 }
340 }
342
341
343 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::cancelVarRequest(
342 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::cancelVarRequest(
344 QUuid varRequestId)
343 QUuid varRequestId)
345 {
344 {
346 qCDebug(LOG_VariableAcquisitionWorker())
345 qCDebug(LOG_VariableAcquisitionWorker())
347 << "VariableAcquisitionWorkerPrivate::cancelVarRequest 0";
346 << "VariableAcquisitionWorkerPrivate::cancelVarRequest 0";
348 lockRead();
347 lockRead();
349 // get all AcqIdentifier in link with varRequestId
348 // get all AcqIdentifier in link with varRequestId
350 QVector<QUuid> acqIdsToRm;
349 QVector<QUuid> acqIdsToRm;
351 auto cend = m_AcqIdentifierToAcqRequestMap.cend();
350 auto cend = m_AcqIdentifierToAcqRequestMap.cend();
352 for (auto it = m_AcqIdentifierToAcqRequestMap.cbegin(); it != cend; ++it) {
351 for (auto it = m_AcqIdentifierToAcqRequestMap.cbegin(); it != cend; ++it) {
353 if (it->second.m_VarRequestId == varRequestId) {
352 if (it->second.m_VarRequestId == varRequestId) {
354 acqIdsToRm << it->first;
353 acqIdsToRm << it->first;
355 }
354 }
356 }
355 }
357 unlock();
356 unlock();
358 // run aborting or removing of acqIdsToRm
357 // run aborting or removing of acqIdsToRm
359
358
360 for (auto acqId : acqIdsToRm) {
359 for (auto acqId : acqIdsToRm) {
361 removeAcqRequest(acqId);
360 removeAcqRequest(acqId);
362 }
361 }
363 qCDebug(LOG_VariableAcquisitionWorker())
362 qCDebug(LOG_VariableAcquisitionWorker())
364 << "VariableAcquisitionWorkerPrivate::cancelVarRequest end";
363 << "VariableAcquisitionWorkerPrivate::cancelVarRequest end";
365 }
364 }
366
365
367 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeAcqRequest(
366 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeAcqRequest(
368 QUuid acqRequestId)
367 QUuid acqRequestId)
369 {
368 {
370 qCDebug(LOG_VariableAcquisitionWorker())
369 qCDebug(LOG_VariableAcquisitionWorker())
371 << "VariableAcquisitionWorkerPrivate::removeAcqRequest";
370 << "VariableAcquisitionWorkerPrivate::removeAcqRequest";
372 QUuid vIdentifier;
371 QUuid vIdentifier;
373 std::shared_ptr<IDataProvider> provider;
372 std::shared_ptr<IDataProvider> provider;
374 lockRead();
373 lockRead();
375 auto acqIt = m_AcqIdentifierToAcqRequestMap.find(acqRequestId);
374 auto acqIt = m_AcqIdentifierToAcqRequestMap.find(acqRequestId);
376 if (acqIt != m_AcqIdentifierToAcqRequestMap.cend()) {
375 if (acqIt != m_AcqIdentifierToAcqRequestMap.cend()) {
377 vIdentifier = acqIt->second.m_vIdentifier;
376 vIdentifier = acqIt->second.m_vIdentifier;
378 provider = acqIt->second.m_Provider;
377 provider = acqIt->second.m_Provider;
379
378
380 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
379 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
381 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
380 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
382 if (it->second.first == acqRequestId) {
381 if (it->second.first == acqRequestId) {
383 // acqRequest is currently running -> let's aborting it
382 // acqRequest is currently running -> let's aborting it
384 unlock();
383 unlock();
385
384
386 // Remove the current request from the worker
385 // Remove the current request from the worker
387 updateToNextRequest(vIdentifier);
386 updateToNextRequest(vIdentifier);
388
387
389 // notify the request aborting to the provider
388 // notify the request aborting to the provider
390 provider->requestDataAborting(acqRequestId);
389 provider->requestDataAborting(acqRequestId);
391 }
390 }
392 else if (it->second.second == acqRequestId) {
391 else if (it->second.second == acqRequestId) {
393 it->second.second = QUuid();
392 it->second.second = QUuid();
394 unlock();
393 unlock();
395 }
394 }
396 else {
395 else {
397 unlock();
396 unlock();
398 }
397 }
399 }
398 }
400 else {
399 else {
401 unlock();
400 unlock();
402 }
401 }
403 }
402 }
404 else {
403 else {
405 unlock();
404 unlock();
406 }
405 }
407
406
408 lockWrite();
407 lockWrite();
409
408
410 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqRequestId);
409 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqRequestId);
411 m_AcqIdentifierToAcqRequestMap.erase(acqRequestId);
410 m_AcqIdentifierToAcqRequestMap.erase(acqRequestId);
412
411
413 unlock();
412 unlock();
414 qCDebug(LOG_VariableAcquisitionWorker())
413 qCDebug(LOG_VariableAcquisitionWorker())
415 << "VariableAcquisitionWorkerPrivate::removeAcqRequest END";
414 << "VariableAcquisitionWorkerPrivate::removeAcqRequest END";
416 }
415 }
@@ -1,889 +1,956
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QMutex>
15 #include <QMutex>
16 #include <QThread>
16 #include <QThread>
17 #include <QUuid>
17 #include <QUuid>
18 #include <QtCore/QItemSelectionModel>
18 #include <QtCore/QItemSelectionModel>
19
19
20 #include <deque>
20 #include <deque>
21 #include <set>
21 #include <set>
22 #include <unordered_map>
22 #include <unordered_map>
23
23
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25
25
26 namespace {
26 namespace {
27
27
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 const SqpRange &oldGraphRange)
29 const SqpRange &oldGraphRange)
30 {
30 {
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32
32
33 auto varRangeRequested = varRange;
33 auto varRangeRequested = varRange;
34 switch (zoomType) {
34 switch (zoomType) {
35 case AcquisitionZoomType::ZoomIn: {
35 case AcquisitionZoomType::ZoomIn: {
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 varRangeRequested.m_TStart += deltaLeft;
38 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TEnd -= deltaRight;
39 varRangeRequested.m_TEnd -= deltaRight;
40 break;
40 break;
41 }
41 }
42
42
43 case AcquisitionZoomType::ZoomOut: {
43 case AcquisitionZoomType::ZoomOut: {
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 varRangeRequested.m_TStart -= deltaLeft;
46 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TEnd += deltaRight;
47 varRangeRequested.m_TEnd += deltaRight;
48 break;
48 break;
49 }
49 }
50 case AcquisitionZoomType::PanRight: {
50 case AcquisitionZoomType::PanRight: {
51 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
51 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
52 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 varRangeRequested.m_TStart += deltaLeft;
53 varRangeRequested.m_TStart += deltaLeft;
54 varRangeRequested.m_TEnd += deltaRight;
54 varRangeRequested.m_TEnd += deltaRight;
55 break;
55 break;
56 }
56 }
57 case AcquisitionZoomType::PanLeft: {
57 case AcquisitionZoomType::PanLeft: {
58 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
58 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
59 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 varRangeRequested.m_TStart -= deltaLeft;
60 varRangeRequested.m_TStart -= deltaLeft;
61 varRangeRequested.m_TEnd -= deltaRight;
61 varRangeRequested.m_TEnd -= deltaRight;
62 break;
62 break;
63 }
63 }
64 case AcquisitionZoomType::Unknown: {
64 case AcquisitionZoomType::Unknown: {
65 qCCritical(LOG_VariableController())
65 qCCritical(LOG_VariableController())
66 << VariableController::tr("Impossible to synchronize: zoom type unknown");
66 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 break;
67 break;
68 }
68 }
69 default:
69 default:
70 qCCritical(LOG_VariableController()) << VariableController::tr(
70 qCCritical(LOG_VariableController()) << VariableController::tr(
71 "Impossible to synchronize: zoom type not take into account");
71 "Impossible to synchronize: zoom type not take into account");
72 // No action
72 // No action
73 break;
73 break;
74 }
74 }
75
75
76 return varRangeRequested;
76 return varRangeRequested;
77 }
77 }
78 }
78 }
79
79
80 struct VariableController::VariableControllerPrivate {
80 struct VariableController::VariableControllerPrivate {
81 explicit VariableControllerPrivate(VariableController *parent)
81 explicit VariableControllerPrivate(VariableController *parent)
82 : m_WorkingMutex{},
82 : m_WorkingMutex{},
83 m_VariableModel{new VariableModel{parent}},
83 m_VariableModel{new VariableModel{parent}},
84 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
84 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
85 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
85 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
86 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
86 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
87 CacheStrategy::SingleThreshold)},
87 CacheStrategy::SingleThreshold)},
88 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
88 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
89 q{parent}
89 q{parent}
90 {
90 {
91
91
92 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
92 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
93 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
93 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
94 }
94 }
95
95
96
96
97 virtual ~VariableControllerPrivate()
97 virtual ~VariableControllerPrivate()
98 {
98 {
99 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
99 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
100 m_VariableAcquisitionWorkerThread.quit();
100 m_VariableAcquisitionWorkerThread.quit();
101 m_VariableAcquisitionWorkerThread.wait();
101 m_VariableAcquisitionWorkerThread.wait();
102 }
102 }
103
103
104
104
105 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
105 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
106 QUuid varRequestId);
106 QUuid varRequestId);
107
107
108 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
108 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
109 std::shared_ptr<IDataSeries>
109 std::shared_ptr<IDataSeries>
110 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
110 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
111
111
112 void registerProvider(std::shared_ptr<IDataProvider> provider);
112 void registerProvider(std::shared_ptr<IDataProvider> provider);
113
113
114 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
114 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
115 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
115 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
116 void updateVariableRequest(QUuid varRequestId);
116 void updateVariableRequest(QUuid varRequestId);
117 void cancelVariableRequest(QUuid varRequestId);
117 void cancelVariableRequest(QUuid varRequestId);
118
118 void abortVariableRequest(QUuid varRequestId);
119 SqpRange getLastRequestedRange(QUuid varId);
119 SqpRange getLastRequestedRange(QUuid varId);
120
120
121 QMutex m_WorkingMutex;
121 QMutex m_WorkingMutex;
122 /// Variable model. The VariableController has the ownership
122 /// Variable model. The VariableController has the ownership
123 VariableModel *m_VariableModel;
123 VariableModel *m_VariableModel;
124 QItemSelectionModel *m_VariableSelectionModel;
124 QItemSelectionModel *m_VariableSelectionModel;
125
125
126
126
127 TimeController *m_TimeController{nullptr};
127 TimeController *m_TimeController{nullptr};
128 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
128 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
129 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
129 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
130 QThread m_VariableAcquisitionWorkerThread;
130 QThread m_VariableAcquisitionWorkerThread;
131
131
132 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
132 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
133 m_VariableToProviderMap;
133 m_VariableToProviderMap;
134 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
134 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
135 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
135 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
136 m_GroupIdToVariableSynchronizationGroupMap;
136 m_GroupIdToVariableSynchronizationGroupMap;
137 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
137 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
138 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
138 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
139
139
140 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
140 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
141
141
142 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
142 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
143
143
144
144
145 VariableController *q;
145 VariableController *q;
146 };
146 };
147
147
148
148
149 VariableController::VariableController(QObject *parent)
149 VariableController::VariableController(QObject *parent)
150 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
150 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
151 {
151 {
152 qCDebug(LOG_VariableController()) << tr("VariableController construction")
152 qCDebug(LOG_VariableController()) << tr("VariableController construction")
153 << QThread::currentThread();
153 << QThread::currentThread();
154
154
155 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
155 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
156 &VariableController::onAbortProgressRequested);
156 &VariableController::onAbortProgressRequested);
157
157
158 connect(impl->m_VariableAcquisitionWorker.get(),
158 connect(impl->m_VariableAcquisitionWorker.get(),
159 &VariableAcquisitionWorker::variableCanceledRequested, this,
159 &VariableAcquisitionWorker::variableCanceledRequested, this,
160 &VariableController::onAbortAcquisitionRequested);
160 &VariableController::onAbortAcquisitionRequested);
161
161
162 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
162 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
163 &VariableController::onDataProvided);
163 &VariableController::onDataProvided);
164 connect(impl->m_VariableAcquisitionWorker.get(),
164 connect(impl->m_VariableAcquisitionWorker.get(),
165 &VariableAcquisitionWorker::variableRequestInProgress, this,
165 &VariableAcquisitionWorker::variableRequestInProgress, this,
166 &VariableController::onVariableRetrieveDataInProgress);
166 &VariableController::onVariableRetrieveDataInProgress);
167
167
168
168
169 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
169 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
170 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
170 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
171 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
171 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
172 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
172 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
173
173
174
174
175 impl->m_VariableAcquisitionWorkerThread.start();
175 impl->m_VariableAcquisitionWorkerThread.start();
176 }
176 }
177
177
178 VariableController::~VariableController()
178 VariableController::~VariableController()
179 {
179 {
180 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
180 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
181 << QThread::currentThread();
181 << QThread::currentThread();
182 this->waitForFinish();
182 this->waitForFinish();
183 }
183 }
184
184
185 VariableModel *VariableController::variableModel() noexcept
185 VariableModel *VariableController::variableModel() noexcept
186 {
186 {
187 return impl->m_VariableModel;
187 return impl->m_VariableModel;
188 }
188 }
189
189
190 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
190 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
191 {
191 {
192 return impl->m_VariableSelectionModel;
192 return impl->m_VariableSelectionModel;
193 }
193 }
194
194
195 void VariableController::setTimeController(TimeController *timeController) noexcept
195 void VariableController::setTimeController(TimeController *timeController) noexcept
196 {
196 {
197 impl->m_TimeController = timeController;
197 impl->m_TimeController = timeController;
198 }
198 }
199
199
200 std::shared_ptr<Variable>
200 std::shared_ptr<Variable>
201 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
201 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
202 {
202 {
203 if (impl->m_VariableModel->containsVariable(variable)) {
203 if (impl->m_VariableModel->containsVariable(variable)) {
204 // Clones variable
204 // Clones variable
205 auto duplicate = variable->clone();
205 auto duplicate = variable->clone();
206
206
207 // Adds clone to model
207 // Adds clone to model
208 impl->m_VariableModel->addVariable(duplicate);
208 impl->m_VariableModel->addVariable(duplicate);
209
209
210 // Generates clone identifier
210 // Generates clone identifier
211 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
211 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
212
212
213 // Registers provider
213 // Registers provider
214 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
214 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
215 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
215 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
216
216
217 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
217 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
218 if (duplicateProvider) {
218 if (duplicateProvider) {
219 impl->registerProvider(duplicateProvider);
219 impl->registerProvider(duplicateProvider);
220 }
220 }
221
221
222 return duplicate;
222 return duplicate;
223 }
223 }
224 else {
224 else {
225 qCCritical(LOG_VariableController())
225 qCCritical(LOG_VariableController())
226 << tr("Can't create duplicate of variable %1: variable not registered in the model")
226 << tr("Can't create duplicate of variable %1: variable not registered in the model")
227 .arg(variable->name());
227 .arg(variable->name());
228 return nullptr;
228 return nullptr;
229 }
229 }
230 }
230 }
231
231
232 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
232 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
233 {
233 {
234 if (!variable) {
234 if (!variable) {
235 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
235 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
236 return;
236 return;
237 }
237 }
238
238
239 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
239 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
240 // make some treatments before the deletion
240 // make some treatments before the deletion
241 emit variableAboutToBeDeleted(variable);
241 emit variableAboutToBeDeleted(variable);
242
242
243 // Deletes identifier
243 // Deletes identifier
244 impl->m_VariableToIdentifierMap.erase(variable);
244 impl->m_VariableToIdentifierMap.erase(variable);
245
245
246 // Deletes provider
246 // Deletes provider
247 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
247 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
248 qCDebug(LOG_VariableController())
248 qCDebug(LOG_VariableController())
249 << tr("Number of providers deleted for variable %1: %2")
249 << tr("Number of providers deleted for variable %1: %2")
250 .arg(variable->name(), QString::number(nbProvidersDeleted));
250 .arg(variable->name(), QString::number(nbProvidersDeleted));
251
251
252
252
253 // Deletes from model
253 // Deletes from model
254 impl->m_VariableModel->deleteVariable(variable);
254 impl->m_VariableModel->deleteVariable(variable);
255 }
255 }
256
256
257 void VariableController::deleteVariables(
257 void VariableController::deleteVariables(
258 const QVector<std::shared_ptr<Variable> > &variables) noexcept
258 const QVector<std::shared_ptr<Variable> > &variables) noexcept
259 {
259 {
260 for (auto variable : qAsConst(variables)) {
260 for (auto variable : qAsConst(variables)) {
261 deleteVariable(variable);
261 deleteVariable(variable);
262 }
262 }
263 }
263 }
264
264
265 std::shared_ptr<Variable>
265 std::shared_ptr<Variable>
266 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
266 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
267 std::shared_ptr<IDataProvider> provider) noexcept
267 std::shared_ptr<IDataProvider> provider) noexcept
268 {
268 {
269 if (!impl->m_TimeController) {
269 if (!impl->m_TimeController) {
270 qCCritical(LOG_VariableController())
270 qCCritical(LOG_VariableController())
271 << tr("Impossible to create variable: The time controller is null");
271 << tr("Impossible to create variable: The time controller is null");
272 return nullptr;
272 return nullptr;
273 }
273 }
274
274
275 auto range = impl->m_TimeController->dateTime();
275 auto range = impl->m_TimeController->dateTime();
276
276
277 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
277 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
278 auto identifier = QUuid::createUuid();
278 auto identifier = QUuid::createUuid();
279
279
280 // store the provider
280 // store the provider
281 impl->registerProvider(provider);
281 impl->registerProvider(provider);
282
282
283 // Associate the provider
283 // Associate the provider
284 impl->m_VariableToProviderMap[newVariable] = provider;
284 impl->m_VariableToProviderMap[newVariable] = provider;
285 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
285 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
286 impl->m_VariableToIdentifierMap[newVariable] = identifier;
286 impl->m_VariableToIdentifierMap[newVariable] = identifier;
287
287
288
288
289 auto varRequestId = QUuid::createUuid();
289 auto varRequestId = QUuid::createUuid();
290 impl->processRequest(newVariable, range, varRequestId);
290 impl->processRequest(newVariable, range, varRequestId);
291 impl->updateVariableRequest(varRequestId);
291 impl->updateVariableRequest(varRequestId);
292
292
293 return newVariable;
293 return newVariable;
294 }
294 }
295 }
295 }
296
296
297 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
297 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
298 {
298 {
299 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
299 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
300 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
300 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
301 << QThread::currentThread()->objectName();
301 << QThread::currentThread()->objectName();
302 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
302 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
303 auto variables = QVector<std::shared_ptr<Variable> >{};
303 auto variables = QVector<std::shared_ptr<Variable> >{};
304
304
305 for (const auto &selectedRow : qAsConst(selectedRows)) {
305 for (const auto &selectedRow : qAsConst(selectedRows)) {
306 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
306 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
307 variables << selectedVariable;
307 variables << selectedVariable;
308
308
309 // notify that rescale operation has to be done
309 // notify that rescale operation has to be done
310 emit rangeChanged(selectedVariable, dateTime);
310 emit rangeChanged(selectedVariable, dateTime);
311 }
311 }
312 }
312 }
313
313
314 if (!variables.isEmpty()) {
314 if (!variables.isEmpty()) {
315 this->onRequestDataLoading(variables, dateTime, true);
315 this->onRequestDataLoading(variables, dateTime, true);
316 }
316 }
317 }
317 }
318
318
319 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
319 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
320 const SqpRange &cacheRangeRequested,
320 const SqpRange &cacheRangeRequested,
321 QVector<AcquisitionDataPacket> dataAcquired)
321 QVector<AcquisitionDataPacket> dataAcquired)
322 {
322 {
323 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
323 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
324 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
324 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
325 if (!varRequestId.isNull()) {
325 if (!varRequestId.isNull()) {
326 impl->updateVariableRequest(varRequestId);
326 impl->updateVariableRequest(varRequestId);
327 }
327 }
328 }
328 }
329
329
330 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
330 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
331 {
331 {
332 qCDebug(LOG_VariableController())
332 qCDebug(LOG_VariableController())
333 << "TORM: variableController::onVariableRetrieveDataInProgress"
333 << "TORM: variableController::onVariableRetrieveDataInProgress"
334 << QThread::currentThread()->objectName() << progress;
334 << QThread::currentThread()->objectName() << progress;
335 if (auto var = impl->findVariable(identifier)) {
335 if (auto var = impl->findVariable(identifier)) {
336 impl->m_VariableModel->setDataProgress(var, progress);
336 impl->m_VariableModel->setDataProgress(var, progress);
337 }
337 }
338 else {
338 else {
339 qCCritical(LOG_VariableController())
339 qCCritical(LOG_VariableController())
340 << tr("Impossible to notify progression of a null variable");
340 << tr("Impossible to notify progression of a null variable");
341 }
341 }
342 }
342 }
343
343
344 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
344 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
345 {
345 {
346 auto it = impl->m_VariableToIdentifierMap.find(variable);
346 auto it = impl->m_VariableToIdentifierMap.find(variable);
347 if (it != impl->m_VariableToIdentifierMap.cend()) {
347 if (it != impl->m_VariableToIdentifierMap.cend()) {
348 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
348 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
349
349
350 QUuid varRequestId;
350 QUuid varRequestId;
351 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
351 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
352 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
352 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
353 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
353 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
354 varRequestId = varRequestIdQueue.front();
354 varRequestId = varRequestIdQueue.front();
355 impl->cancelVariableRequest(varRequestId);
355 impl->cancelVariableRequest(varRequestId);
356
356
357 // Finish the progression for the request
357 // Finish the progression for the request
358 impl->m_VariableModel->setDataProgress(variable, 0.0);
358 impl->m_VariableModel->setDataProgress(variable, 0.0);
359 }
359 }
360 else {
360 else {
361 qCWarning(LOG_VariableController())
361 qCWarning(LOG_VariableController())
362 << tr("Aborting progression of inexistant variable request detected !!!")
362 << tr("Aborting progression of inexistant variable request detected !!!")
363 << QThread::currentThread()->objectName();
363 << QThread::currentThread()->objectName();
364 }
364 }
365 }
365 }
366 else {
366 else {
367 qCWarning(LOG_VariableController())
367 qCWarning(LOG_VariableController())
368 << tr("Aborting progression of inexistant variable detected !!!")
368 << tr("Aborting progression of inexistant variable detected !!!")
369 << QThread::currentThread()->objectName();
369 << QThread::currentThread()->objectName();
370 }
370 }
371 }
371 }
372
372
373 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
373 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
374 {
374 {
375 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
375 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
376 << QThread::currentThread()->objectName() << vIdentifier;
376 << QThread::currentThread()->objectName() << vIdentifier;
377
377
378 if (auto var = impl->findVariable(vIdentifier)) {
378 if (auto var = impl->findVariable(vIdentifier)) {
379 this->onAbortProgressRequested(var);
379 this->onAbortProgressRequested(var);
380 }
380 }
381 else {
381 else {
382 qCCritical(LOG_VariableController())
382 qCCritical(LOG_VariableController())
383 << tr("Impossible to abort Acquisition Requestof a null variable");
383 << tr("Impossible to abort Acquisition Requestof a null variable");
384 }
384 }
385 }
385 }
386
386
387 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
387 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
388 {
388 {
389 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
389 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
390 << QThread::currentThread()->objectName()
390 << QThread::currentThread()->objectName()
391 << synchronizationGroupId;
391 << synchronizationGroupId;
392 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
392 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
393 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
393 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
394 std::make_pair(synchronizationGroupId, vSynchroGroup));
394 std::make_pair(synchronizationGroupId, vSynchroGroup));
395 }
395 }
396
396
397 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
397 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
398 {
398 {
399 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
399 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
400 }
400 }
401
401
402 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
402 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
403 QUuid synchronizationGroupId)
403 QUuid synchronizationGroupId)
404
404
405 {
405 {
406 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
406 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
407 << synchronizationGroupId;
407 << synchronizationGroupId;
408 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
408 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
409 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
409 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
410 auto groupIdToVSGIt
410 auto groupIdToVSGIt
411 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
411 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
412 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
412 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
413 impl->m_VariableIdGroupIdMap.insert(
413 impl->m_VariableIdGroupIdMap.insert(
414 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
414 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
415 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
415 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
416 }
416 }
417 else {
417 else {
418 qCCritical(LOG_VariableController())
418 qCCritical(LOG_VariableController())
419 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
419 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
420 << variable->name();
420 << variable->name();
421 }
421 }
422 }
422 }
423 else {
423 else {
424 qCCritical(LOG_VariableController())
424 qCCritical(LOG_VariableController())
425 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
425 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
426 }
426 }
427 }
427 }
428
428
429 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
429 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
430 QUuid synchronizationGroupId)
430 QUuid synchronizationGroupId)
431 {
431 {
432 // Gets variable id
432 // Gets variable id
433 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
433 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
434 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
434 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
435 qCCritical(LOG_VariableController())
435 qCCritical(LOG_VariableController())
436 << tr("Can't desynchronize variable %1: variable identifier not found")
436 << tr("Can't desynchronize variable %1: variable identifier not found")
437 .arg(variable->name());
437 .arg(variable->name());
438 return;
438 return;
439 }
439 }
440
440
441 // Gets synchronization group
441 // Gets synchronization group
442 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
442 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
443 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
443 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
444 qCCritical(LOG_VariableController())
444 qCCritical(LOG_VariableController())
445 << tr("Can't desynchronize variable %1: unknown synchronization group")
445 << tr("Can't desynchronize variable %1: unknown synchronization group")
446 .arg(variable->name());
446 .arg(variable->name());
447 return;
447 return;
448 }
448 }
449
449
450 auto variableId = variableIt->second;
450 auto variableId = variableIt->second;
451
451
452 // Removes variable from synchronization group
452 // Removes variable from synchronization group
453 auto synchronizationGroup = groupIt->second;
453 auto synchronizationGroup = groupIt->second;
454 synchronizationGroup->removeVariableId(variableId);
454 synchronizationGroup->removeVariableId(variableId);
455
455
456 // Removes link between variable and synchronization group
456 // Removes link between variable and synchronization group
457 impl->m_VariableIdGroupIdMap.erase(variableId);
457 impl->m_VariableIdGroupIdMap.erase(variableId);
458 }
458 }
459
459
460 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
460 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
461 const SqpRange &range, bool synchronise)
461 const SqpRange &range, bool synchronise)
462 {
462 {
463 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
463 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
464
464
465 // we want to load data of the variable for the dateTime.
465 // we want to load data of the variable for the dateTime.
466 // First we check if the cache contains some of them.
466 // First we check if the cache contains some of them.
467 // For the other, we ask the provider to give them.
467 // For the other, we ask the provider to give them.
468
468
469 auto varRequestId = QUuid::createUuid();
469 auto varRequestId = QUuid::createUuid();
470 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
470 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
471 << QThread::currentThread()->objectName() << varRequestId;
471 << QThread::currentThread()->objectName() << varRequestId;
472
472
473 for (const auto &var : variables) {
473 for (const auto &var : variables) {
474 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
474 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
475 impl->processRequest(var, range, varRequestId);
475 impl->processRequest(var, range, varRequestId);
476 }
476 }
477
477
478 if (synchronise) {
478 if (synchronise) {
479 // Get the group ids
479 // Get the group ids
480 qCDebug(LOG_VariableController())
480 qCDebug(LOG_VariableController())
481 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
481 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
482 auto groupIds = std::set<QUuid>{};
482 auto groupIds = std::set<QUuid>{};
483 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
483 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
484 for (const auto &var : variables) {
484 for (const auto &var : variables) {
485 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
485 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
486 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
486 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
487 auto vId = varToVarIdIt->second;
487 auto vId = varToVarIdIt->second;
488 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
488 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
489 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
489 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
490 auto gId = varIdToGroupIdIt->second;
490 auto gId = varIdToGroupIdIt->second;
491 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
491 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
492 if (groupIds.find(gId) == groupIds.cend()) {
492 if (groupIds.find(gId) == groupIds.cend()) {
493 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
493 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
494 groupIds.insert(gId);
494 groupIds.insert(gId);
495 }
495 }
496 }
496 }
497 }
497 }
498 }
498 }
499
499
500 // We assume here all group ids exist
500 // We assume here all group ids exist
501 for (const auto &gId : groupIds) {
501 for (const auto &gId : groupIds) {
502 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
502 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
503 auto vSyncIds = vSynchronizationGroup->getIds();
503 auto vSyncIds = vSynchronizationGroup->getIds();
504 qCDebug(LOG_VariableController()) << "Var in synchro group ";
504 qCDebug(LOG_VariableController()) << "Var in synchro group ";
505 for (auto vId : vSyncIds) {
505 for (auto vId : vSyncIds) {
506 auto var = impl->findVariable(vId);
506 auto var = impl->findVariable(vId);
507
507
508 // Don't process already processed var
508 // Don't process already processed var
509 if (!variables.contains(var)) {
509 if (!variables.contains(var)) {
510 if (var != nullptr) {
510 if (var != nullptr) {
511 qCDebug(LOG_VariableController()) << "processRequest synchro for"
511 qCDebug(LOG_VariableController()) << "processRequest synchro for"
512 << var->name();
512 << var->name();
513 auto vSyncRangeRequested = computeSynchroRangeRequested(
513 auto vSyncRangeRequested = computeSynchroRangeRequested(
514 var->range(), range, groupIdToOldRangeMap.at(gId));
514 var->range(), range, groupIdToOldRangeMap.at(gId));
515 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
515 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
516 impl->processRequest(var, vSyncRangeRequested, varRequestId);
516 impl->processRequest(var, vSyncRangeRequested, varRequestId);
517 }
517 }
518 else {
518 else {
519 qCCritical(LOG_VariableController())
519 qCCritical(LOG_VariableController())
520
520
521 << tr("Impossible to synchronize a null variable");
521 << tr("Impossible to synchronize a null variable");
522 }
522 }
523 }
523 }
524 }
524 }
525 }
525 }
526 }
526 }
527
527
528 impl->updateVariableRequest(varRequestId);
528 impl->updateVariableRequest(varRequestId);
529 }
529 }
530
530
531
531
532 void VariableController::initialize()
532 void VariableController::initialize()
533 {
533 {
534 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
534 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
535 impl->m_WorkingMutex.lock();
535 impl->m_WorkingMutex.lock();
536 qCDebug(LOG_VariableController()) << tr("VariableController init END");
536 qCDebug(LOG_VariableController()) << tr("VariableController init END");
537 }
537 }
538
538
539 void VariableController::finalize()
539 void VariableController::finalize()
540 {
540 {
541 impl->m_WorkingMutex.unlock();
541 impl->m_WorkingMutex.unlock();
542 }
542 }
543
543
544 void VariableController::waitForFinish()
544 void VariableController::waitForFinish()
545 {
545 {
546 QMutexLocker locker{&impl->m_WorkingMutex};
546 QMutexLocker locker{&impl->m_WorkingMutex};
547 }
547 }
548
548
549 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
549 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
550 {
550 {
551 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
551 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
552 auto zoomType = AcquisitionZoomType::Unknown;
552 auto zoomType = AcquisitionZoomType::Unknown;
553 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
553 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
554 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
554 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
555 zoomType = AcquisitionZoomType::ZoomOut;
555 zoomType = AcquisitionZoomType::ZoomOut;
556 }
556 }
557 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
557 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
558 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
558 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
559 zoomType = AcquisitionZoomType::PanRight;
559 zoomType = AcquisitionZoomType::PanRight;
560 }
560 }
561 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
561 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
562 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
562 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
563 zoomType = AcquisitionZoomType::PanLeft;
563 zoomType = AcquisitionZoomType::PanLeft;
564 }
564 }
565 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
565 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
566 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
566 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
567 zoomType = AcquisitionZoomType::ZoomIn;
567 zoomType = AcquisitionZoomType::ZoomIn;
568 }
568 }
569 else {
569 else {
570 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
570 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
571 }
571 }
572 return zoomType;
572 return zoomType;
573 }
573 }
574
574
575 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
575 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
576 const SqpRange &rangeRequested,
576 const SqpRange &rangeRequested,
577 QUuid varRequestId)
577 QUuid varRequestId)
578 {
578 {
579 auto varRequest = VariableRequest{};
579 auto varRequest = VariableRequest{};
580
580
581 auto it = m_VariableToIdentifierMap.find(var);
581 auto it = m_VariableToIdentifierMap.find(var);
582 if (it != m_VariableToIdentifierMap.cend()) {
582 if (it != m_VariableToIdentifierMap.cend()) {
583
583
584 auto varId = it->second;
584 auto varId = it->second;
585
585
586 auto oldRange = getLastRequestedRange(varId);
586 auto oldRange = getLastRequestedRange(varId);
587
587
588 // check for update oldRange to the last request range.
588 // check for update oldRange to the last request range.
589 if (oldRange == INVALID_RANGE) {
589 if (oldRange == INVALID_RANGE) {
590 oldRange = var->range();
590 oldRange = var->range();
591 }
591 }
592
592
593 auto varStrategyRangesRequested
593 auto varStrategyRangesRequested
594 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
594 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
595
595
596 // Use commented lines to remove the cache (run time)
597 // auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
598 // auto inCacheRangeList = QVector<SqpRange>{};
596 auto notInCacheRangeList
599 auto notInCacheRangeList
597 = Variable::provideNotInCacheRangeList(oldRange, varStrategyRangesRequested.second);
600 = Variable::provideNotInCacheRangeList(oldRange, varStrategyRangesRequested.second);
598 auto inCacheRangeList
601 auto inCacheRangeList
599 = Variable::provideInCacheRangeList(oldRange, varStrategyRangesRequested.second);
602 = Variable::provideInCacheRangeList(oldRange, varStrategyRangesRequested.second);
600
603
601 if (!notInCacheRangeList.empty()) {
604 if (!notInCacheRangeList.empty()) {
602 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
605 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
603 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
606 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
604
607
605 // store VarRequest
608 // store VarRequest
606 storeVariableRequest(varId, varRequestId, varRequest);
609 storeVariableRequest(varId, varRequestId, varRequest);
607
610
608 auto varProvider = m_VariableToProviderMap.at(var);
611 auto varProvider = m_VariableToProviderMap.at(var);
609 if (varProvider != nullptr) {
612 if (varProvider != nullptr) {
610 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
613 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
611 varRequestId, varId, varStrategyRangesRequested.first,
614 varRequestId, varId, varStrategyRangesRequested.first,
612 varStrategyRangesRequested.second,
615 varStrategyRangesRequested.second,
613 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
616 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
614 varProvider);
617 varProvider);
615
618
616 if (!varRequestIdCanceled.isNull()) {
619 if (!varRequestIdCanceled.isNull()) {
617 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
620 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
618 << varRequestIdCanceled;
621 << varRequestIdCanceled;
619 cancelVariableRequest(varRequestIdCanceled);
622 // cancelVariableRequest(varRequestIdCanceled);
623 abortVariableRequest(varRequestIdCanceled);
620 }
624 }
621 }
625 }
622 else {
626 else {
623 qCCritical(LOG_VariableController())
627 qCCritical(LOG_VariableController())
624 << "Impossible to provide data with a null provider";
628 << "Impossible to provide data with a null provider";
625 }
629 }
626
630
627 if (!inCacheRangeList.empty()) {
631 if (!inCacheRangeList.empty()) {
628 emit q->updateVarDisplaying(var, inCacheRangeList.first());
632 emit q->updateVarDisplaying(var, inCacheRangeList.first());
629 }
633 }
630 }
634 }
631 else {
635 else {
632 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
636 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
633 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
637 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
634 // store VarRequest
638 // store VarRequest
635 storeVariableRequest(varId, varRequestId, varRequest);
639 storeVariableRequest(varId, varRequestId, varRequest);
636 acceptVariableRequest(
640 acceptVariableRequest(
637 varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
641 varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
638 }
642 }
639 }
643 }
640 }
644 }
641
645
642 std::shared_ptr<Variable>
646 std::shared_ptr<Variable>
643 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
647 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
644 {
648 {
645 std::shared_ptr<Variable> var;
649 std::shared_ptr<Variable> var;
646 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
650 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
647
651
648 auto end = m_VariableToIdentifierMap.cend();
652 auto end = m_VariableToIdentifierMap.cend();
649 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
653 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
650 if (it != end) {
654 if (it != end) {
651 var = it->first;
655 var = it->first;
652 }
656 }
653 else {
657 else {
654 qCCritical(LOG_VariableController())
658 qCCritical(LOG_VariableController())
655 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
659 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
656 }
660 }
657
661
658 return var;
662 return var;
659 }
663 }
660
664
661 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
665 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
662 const QVector<AcquisitionDataPacket> acqDataPacketVector)
666 const QVector<AcquisitionDataPacket> acqDataPacketVector)
663 {
667 {
664 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
668 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
665 << acqDataPacketVector.size();
669 << acqDataPacketVector.size();
666 std::shared_ptr<IDataSeries> dataSeries;
670 std::shared_ptr<IDataSeries> dataSeries;
667 if (!acqDataPacketVector.isEmpty()) {
671 if (!acqDataPacketVector.isEmpty()) {
668 dataSeries = acqDataPacketVector[0].m_DateSeries;
672 dataSeries = acqDataPacketVector[0].m_DateSeries;
669 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
673 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
670 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
674 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
671 }
675 }
672 }
676 }
673 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
677 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
674 << acqDataPacketVector.size();
678 << acqDataPacketVector.size();
675 return dataSeries;
679 return dataSeries;
676 }
680 }
677
681
678 void VariableController::VariableControllerPrivate::registerProvider(
682 void VariableController::VariableControllerPrivate::registerProvider(
679 std::shared_ptr<IDataProvider> provider)
683 std::shared_ptr<IDataProvider> provider)
680 {
684 {
681 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
685 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
682 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
686 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
683 << provider->objectName();
687 << provider->objectName();
684 m_ProviderSet.insert(provider);
688 m_ProviderSet.insert(provider);
685 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
689 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
686 &VariableAcquisitionWorker::onVariableDataAcquired);
690 &VariableAcquisitionWorker::onVariableDataAcquired);
687 connect(provider.get(), &IDataProvider::dataProvidedProgress,
691 connect(provider.get(), &IDataProvider::dataProvidedProgress,
688 m_VariableAcquisitionWorker.get(),
692 m_VariableAcquisitionWorker.get(),
689 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
693 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
690 connect(provider.get(), &IDataProvider::dataProvidedFailed,
694 connect(provider.get(), &IDataProvider::dataProvidedFailed,
691 m_VariableAcquisitionWorker.get(),
695 m_VariableAcquisitionWorker.get(),
692 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
696 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
693 }
697 }
694 else {
698 else {
695 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
699 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
696 }
700 }
697 }
701 }
698
702
699 void VariableController::VariableControllerPrivate::storeVariableRequest(
703 void VariableController::VariableControllerPrivate::storeVariableRequest(
700 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
704 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
701 {
705 {
702 // First request for the variable. we can create an entry for it
706 // First request for the variable. we can create an entry for it
703 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
707 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
704 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
708 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
705 auto varRequestIdQueue = std::deque<QUuid>{};
709 auto varRequestIdQueue = std::deque<QUuid>{};
706 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
710 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
707 varRequestIdQueue.push_back(varRequestId);
711 varRequestIdQueue.push_back(varRequestId);
708 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
712 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
709 }
713 }
710 else {
714 else {
711 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
715 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
712 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
716 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
713 varRequestIdQueue.push_back(varRequestId);
717 varRequestIdQueue.push_back(varRequestId);
714 }
718 }
715
719
716 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
720 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
717 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
721 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
718 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
722 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
719 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
723 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
720 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
724 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
721 m_VarRequestIdToVarIdVarRequestMap.insert(
725 m_VarRequestIdToVarIdVarRequestMap.insert(
722 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
726 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
723 }
727 }
724 else {
728 else {
725 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
729 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
726 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
730 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
727 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
731 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
728 }
732 }
729 }
733 }
730
734
731 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
735 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
732 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
736 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
733 {
737 {
734 QUuid varRequestId;
738 QUuid varRequestId;
735 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
739 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
736 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
740 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
737 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
741 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
738 varRequestId = varRequestIdQueue.front();
742 varRequestId = varRequestIdQueue.front();
739 auto varRequestIdToVarIdVarRequestMapIt
743 auto varRequestIdToVarIdVarRequestMapIt
740 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
744 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
741 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
745 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
742 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
746 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
743 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
747 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
744 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
748 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
745 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
749 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
746 auto &varRequest = varIdToVarRequestMapIt->second;
750 auto &varRequest = varIdToVarRequestMapIt->second;
747 varRequest.m_DataSeries = dataSeries;
751 varRequest.m_DataSeries = dataSeries;
748 varRequest.m_CanUpdate = true;
752 varRequest.m_CanUpdate = true;
749 }
753 }
750 else {
754 else {
751 qCDebug(LOG_VariableController())
755 qCDebug(LOG_VariableController())
752 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
756 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
753 "to a variableRequestId")
757 "to a variableRequestId")
754 << varRequestId << varId;
758 << varRequestId << varId;
755 }
759 }
756 }
760 }
757 else {
761 else {
758 qCCritical(LOG_VariableController())
762 qCCritical(LOG_VariableController())
759 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
763 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
760 << varRequestId;
764 << varRequestId;
761 }
765 }
762
766
763 varRequestIdQueue.pop_front();
767 varRequestIdQueue.pop_front();
764 if (varRequestIdQueue.empty()) {
768 if (varRequestIdQueue.empty()) {
765 qCDebug(LOG_VariableController())
769 qCDebug(LOG_VariableController())
766 << tr("TORM Erase REQUEST because it has been accepted") << varId;
770 << tr("TORM Erase REQUEST because it has been accepted") << varId;
767 m_VarIdToVarRequestIdQueueMap.erase(varId);
771 m_VarIdToVarRequestIdQueueMap.erase(varId);
768 }
772 }
769 }
773 }
770 else {
774 else {
771 qCCritical(LOG_VariableController())
775 qCCritical(LOG_VariableController())
772 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
776 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
773 }
777 }
774
778
775 return varRequestId;
779 return varRequestId;
776 }
780 }
777
781
778 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
782 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
779 {
783 {
780
784
781 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
785 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
782 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
786 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
783 bool processVariableUpdate = true;
787 bool processVariableUpdate = true;
784 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
788 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
785 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
789 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
786 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
790 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
787 ++varIdToVarRequestMapIt) {
791 ++varIdToVarRequestMapIt) {
788 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
792 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
789 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
793 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
790 << processVariableUpdate;
794 << processVariableUpdate;
791 }
795 }
792
796
793 if (processVariableUpdate) {
797 if (processVariableUpdate) {
794 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
798 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
795 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
799 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
796 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
800 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
797 auto &varRequest = varIdToVarRequestMapIt->second;
801 auto &varRequest = varIdToVarRequestMapIt->second;
798 var->setRange(varRequest.m_RangeRequested);
802 var->setRange(varRequest.m_RangeRequested);
799 var->setCacheRange(varRequest.m_CacheRangeRequested);
803 var->setCacheRange(varRequest.m_CacheRangeRequested);
800 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
804 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
801 << varRequest.m_RangeRequested
805 << varRequest.m_RangeRequested
802 << varRequest.m_CacheRangeRequested;
806 << varRequest.m_CacheRangeRequested;
803 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
807 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
804 << var->nbPoints()
808 << var->nbPoints()
805 << varRequest.m_DataSeries->nbPoints();
809 << varRequest.m_DataSeries->nbPoints();
806 var->mergeDataSeries(varRequest.m_DataSeries);
810 var->mergeDataSeries(varRequest.m_DataSeries);
807 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
811 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
808 << var->nbPoints();
812 << var->nbPoints();
809
813
810 emit var->updated();
814 emit var->updated();
811 }
815 }
812 else {
816 else {
813 qCCritical(LOG_VariableController())
817 qCCritical(LOG_VariableController())
814 << tr("Impossible to update data to a null variable");
818 << tr("Impossible to update data to a null variable");
815 }
819 }
816 }
820 }
817 // cleaning varRequestId
821 // cleaning varRequestId
818 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
822 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
819 << m_VarRequestIdToVarIdVarRequestMap.size();
823 << m_VarRequestIdToVarIdVarRequestMap.size();
820 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
824 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
821 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
825 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
822 << m_VarRequestIdToVarIdVarRequestMap.size();
826 << m_VarRequestIdToVarIdVarRequestMap.size();
823 }
827 }
824 }
828 }
825 else {
829 else {
826 qCCritical(LOG_VariableController())
830 qCCritical(LOG_VariableController())
827 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
831 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
828 }
832 }
829 }
833 }
830
834
831 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
835 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
832 {
836 {
833 // cleaning varRequestId
837 // cleaning varRequestId
834 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
838 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
835
839
836 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
840 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
837 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
841 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
838 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
842 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
839 varRequestIdQueue.erase(
843 varRequestIdQueue.erase(
840 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
844 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
841 varRequestIdQueue.end());
845 varRequestIdQueue.end());
842 if (varRequestIdQueue.empty()) {
846 if (varRequestIdQueue.empty()) {
843 varIdToVarRequestIdQueueMapIt
847 varIdToVarRequestIdQueueMapIt
844 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
848 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
845
849
846 // Recompute if there is any next request based on the removed request.
850 // Recompute if there is any next request based on the removed request.
847 }
851 }
848 else {
852 else {
849 ++varIdToVarRequestIdQueueMapIt;
853 ++varIdToVarRequestIdQueueMapIt;
850 }
854 }
851 }
855 }
852 }
856 }
853
857
858 void VariableController::VariableControllerPrivate::abortVariableRequest(QUuid varRequestId)
859 {
860 auto varRequestIdsMap = std::map<QUuid, VariableRequest>{};
861 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
862 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
863 varRequestIdsMap = varRequestIdToVarIdVarRequestMapIt->second;
864 }
865
866 auto nextUuidToRemove = QSet<QUuid>{};
867 auto varIdEnd = varRequestIdsMap.end();
868 for (auto varIdIt = varRequestIdsMap.begin(); varIdIt != varIdEnd;) {
869 auto currentVarId = varIdIt->first;
870 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(currentVarId);
871 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
872
873 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
874
875 auto varReqIdQueueEnd = varRequestIdQueue.end();
876 for (auto varReqIdQueueIt = varRequestIdQueue.begin();
877 varReqIdQueueIt != varRequestIdQueue.end(); ++varReqIdQueueIt) {
878 if (*varReqIdQueueIt == varRequestId) {
879 auto nextVarRequestIdToRm = varReqIdQueueIt;
880 ++nextVarRequestIdToRm;
881
882 if (nextVarRequestIdToRm == varReqIdQueueEnd) {
883 // The varRequestId is in progress for the current var, let's aborting it.
884 m_VariableAcquisitionWorker->abortProgressRequested(currentVarId);
885 }
886 else {
887 // There is at least one Request after
888 // let's add only new id to remove
889 if (!nextUuidToRemove.contains(*nextVarRequestIdToRm)) {
890 nextUuidToRemove << *nextVarRequestIdToRm;
891 }
892 }
893
894 varReqIdQueueIt = varRequestIdQueue.erase(varReqIdQueueIt);
895 // break is necessary here, we don"t need to iterate on the dequeue anymore and
896 // the iteration is broken because of the erase
897 break;
898 }
899 }
900
901 // beacause the process can modify the map under the iteration, we need to update the
902 // iterator only if no erase has been done
903 if (varRequestIdQueue.empty()) {
904 varIdIt = varRequestIdsMap.erase(varIdIt);
905 }
906 else {
907 ++varIdIt;
908 }
909 }
910 }
911
912 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
913 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestIdToVarIdVarRequestMapIt);
914 }
915
916 for (auto nextVarRequestIdToRm : nextUuidToRemove) {
917 abortVariableRequest(nextVarRequestIdToRm);
918 }
919 }
920
854 SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId)
921 SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId)
855 {
922 {
856 auto lastRangeRequested = SqpRange{INVALID_RANGE};
923 auto lastRangeRequested = SqpRange{INVALID_RANGE};
857 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
924 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
858 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
925 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
859 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
926 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
860 auto varRequestId = varRequestIdQueue.back();
927 auto varRequestId = varRequestIdQueue.back();
861 auto varRequestIdToVarIdVarRequestMapIt
928 auto varRequestIdToVarIdVarRequestMapIt
862 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
929 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
863 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
930 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
864 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
931 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
865 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
932 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
866 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
933 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
867 auto &varRequest = varIdToVarRequestMapIt->second;
934 auto &varRequest = varIdToVarRequestMapIt->second;
868 lastRangeRequested = varRequest.m_RangeRequested;
935 lastRangeRequested = varRequest.m_RangeRequested;
869 }
936 }
870 else {
937 else {
871 qCDebug(LOG_VariableController())
938 qCDebug(LOG_VariableController())
872 << tr("Impossible to getLastRequestedRange of a unknown variable id attached "
939 << tr("Impossible to getLastRequestedRange of a unknown variable id attached "
873 "to a variableRequestId")
940 "to a variableRequestId")
874 << varRequestId << varId;
941 << varRequestId << varId;
875 }
942 }
876 }
943 }
877 else {
944 else {
878 qCCritical(LOG_VariableController())
945 qCCritical(LOG_VariableController())
879 << tr("Impossible to getLastRequestedRange of a unknown variableRequestId")
946 << tr("Impossible to getLastRequestedRange of a unknown variableRequestId")
880 << varRequestId;
947 << varRequestId;
881 }
948 }
882 }
949 }
883 else {
950 else {
884 qDebug(LOG_VariableController())
951 qDebug(LOG_VariableController())
885 << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId;
952 << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId;
886 }
953 }
887
954
888 return lastRangeRequested;
955 return lastRangeRequested;
889 }
956 }
@@ -1,390 +1,390
1 #include <QObject>
1 #include <QObject>
2 #include <QtTest>
2 #include <QtTest>
3
3
4 #include <memory>
4 #include <memory>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/ScalarSeries.h>
8 #include <Data/ScalarSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
12 #include <Variable/VariableModel.h>
13
13
14 namespace {
14 namespace {
15
15
16 /// Delay after each operation on the variable before validating it (in ms)
16 /// Delay after each operation on the variable before validating it (in ms)
17 const auto OPERATION_DELAY = 100;
17 const auto OPERATION_DELAY = 100;
18
18
19 /**
19 /**
20 * Generates values according to a range. The value generated for a time t is the number of seconds
20 * Generates values according to a range. The value generated for a time t is the number of seconds
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
22 *
22 *
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
24 * {10,11,12,13,14,15,16,17,18,19,20}
24 * {10,11,12,13,14,15,16,17,18,19,20}
25 */
25 */
26 std::vector<double> values(const SqpRange &range)
26 std::vector<double> values(const SqpRange &range)
27 {
27 {
28 QTime referenceTime{0, 0};
28 QTime referenceTime{0, 0};
29
29
30 std::vector<double> result{};
30 std::vector<double> result{};
31
31
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
33 auto time = DateUtils::dateTime(i).time();
33 auto time = DateUtils::dateTime(i).time();
34 result.push_back(referenceTime.secsTo(time));
34 result.push_back(referenceTime.secsTo(time));
35 }
35 }
36
36
37 return result;
37 return result;
38 }
38 }
39
39
40 /// Provider used for the tests
40 /// Provider used for the tests
41 class TestProvider : public IDataProvider {
41 class TestProvider : public IDataProvider {
42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
43
43
44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
45 {
45 {
46 const auto &ranges = parameters.m_Times;
46 const auto &ranges = parameters.m_Times;
47
47
48 for (const auto &range : ranges) {
48 for (const auto &range : ranges) {
49 // Generates data series
49 // Generates data series
50 auto valuesData = values(range);
50 auto valuesData = values(range);
51
51
52 std::vector<double> xAxisData{};
52 std::vector<double> xAxisData{};
53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
54 xAxisData.push_back(i);
54 xAxisData.push_back(i);
55 }
55 }
56
56
57 auto dataSeries = std::make_shared<ScalarSeries>(
57 auto dataSeries = std::make_shared<ScalarSeries>(
58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
59
59
60 emit dataProvided(acqIdentifier, dataSeries, range);
60 emit dataProvided(acqIdentifier, dataSeries, range);
61 }
61 }
62 }
62 }
63
63
64 void requestDataAborting(QUuid acqIdentifier) override
64 void requestDataAborting(QUuid acqIdentifier) override
65 {
65 {
66 // Does nothing
66 // Does nothing
67 }
67 }
68 };
68 };
69
69
70 /**
70 /**
71 * Interface representing an operation performed on a variable controller.
71 * Interface representing an operation performed on a variable controller.
72 * This interface is used in tests to apply a set of operations and check the status of the
72 * This interface is used in tests to apply a set of operations and check the status of the
73 * controller after each operation
73 * controller after each operation
74 */
74 */
75 struct IOperation {
75 struct IOperation {
76 virtual ~IOperation() = default;
76 virtual ~IOperation() = default;
77 /// Executes the operation on the variable controller
77 /// Executes the operation on the variable controller
78 virtual void exec(VariableController &variableController) const = 0;
78 virtual void exec(VariableController &variableController) const = 0;
79 };
79 };
80
80
81 /**
81 /**
82 *Variable creation operation in the controller
82 *Variable creation operation in the controller
83 */
83 */
84 struct Create : public IOperation {
84 struct Create : public IOperation {
85 explicit Create(int index) : m_Index{index} {}
85 explicit Create(int index) : m_Index{index} {}
86
86
87 void exec(VariableController &variableController) const override
87 void exec(VariableController &variableController) const override
88 {
88 {
89 auto variable = variableController.createVariable(QString::number(m_Index), {},
89 auto variable = variableController.createVariable(QString::number(m_Index), {},
90 std::make_unique<TestProvider>());
90 std::make_unique<TestProvider>());
91 }
91 }
92
92
93 int m_Index; ///< The index of the variable to create in the controller
93 int m_Index; ///< The index of the variable to create in the controller
94 };
94 };
95
95
96 /**
96 /**
97 * Variable move/shift operation in the controller
97 * Variable move/shift operation in the controller
98 */
98 */
99 struct Move : public IOperation {
99 struct Move : public IOperation {
100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
102 {
102 {
103 }
103 }
104
104
105 void exec(VariableController &variableController) const override
105 void exec(VariableController &variableController) const override
106 {
106 {
107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
108 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
108 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
109 }
109 }
110 }
110 }
111
111
112 int m_Index; ///< The index of the variable to move
112 int m_Index; ///< The index of the variable to move
113 SqpRange m_NewRange; ///< The new range of the variable
113 SqpRange m_NewRange; ///< The new range of the variable
114 bool m_Shift; ///< Performs a shift (
114 bool m_Shift; ///< Performs a shift (
115 };
115 };
116
116
117 /**
117 /**
118 * Variable synchronization/desynchronization operation in the controller
118 * Variable synchronization/desynchronization operation in the controller
119 */
119 */
120 struct Synchronize : public IOperation {
120 struct Synchronize : public IOperation {
121 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
121 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
122 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
122 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
123 {
123 {
124 }
124 }
125
125
126 void exec(VariableController &variableController) const override
126 void exec(VariableController &variableController) const override
127 {
127 {
128 if (auto variable = variableController.variableModel()->variable(m_Index)) {
128 if (auto variable = variableController.variableModel()->variable(m_Index)) {
129 if (m_Synchronize) {
129 if (m_Synchronize) {
130 variableController.onAddSynchronized(variable, m_SyncId);
130 variableController.onAddSynchronized(variable, m_SyncId);
131 }
131 }
132 else {
132 else {
133 variableController.desynchronize(variable, m_SyncId);
133 variableController.desynchronize(variable, m_SyncId);
134 }
134 }
135 }
135 }
136 }
136 }
137
137
138 int m_Index; ///< The index of the variable to sync/desync
138 int m_Index; ///< The index of the variable to sync/desync
139 QUuid m_SyncId; ///< The synchronization group of the variable
139 QUuid m_SyncId; ///< The synchronization group of the variable
140 bool m_Synchronize; ///< Performs sync or desync operation
140 bool m_Synchronize; ///< Performs sync or desync operation
141 };
141 };
142
142
143 /**
143 /**
144 * Test Iteration
144 * Test Iteration
145 *
145 *
146 * A test iteration includes an operation to be performed, and a set of expected ranges after each
146 * A test iteration includes an operation to be performed, and a set of expected ranges after each
147 * operation. Each range is tested after the operation to ensure that:
147 * operation. Each range is tested after the operation to ensure that:
148 * - the range of the variable is the expected range
148 * - the range of the variable is the expected range
149 * - the data of the variable are those generated for the expected range
149 * - the data of the variable are those generated for the expected range
150 */
150 */
151 struct Iteration {
151 struct Iteration {
152 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
152 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
153 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
153 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
154 };
154 };
155
155
156 using Iterations = std::vector<Iteration>;
156 using Iterations = std::vector<Iteration>;
157
157
158 } // namespace
158 } // namespace
159
159
160 Q_DECLARE_METATYPE(Iterations)
160 Q_DECLARE_METATYPE(Iterations)
161
161
162 class TestVariableSync : public QObject {
162 class TestVariableSync : public QObject {
163 Q_OBJECT
163 Q_OBJECT
164
164
165 private slots:
165 private slots:
166 /// Input data for @sa testSync()
166 /// Input data for @sa testSync()
167 void testSync_data();
167 void testSync_data();
168
168
169 /// Tests synchronization between variables through several operations
169 /// Tests synchronization between variables through several operations
170 void testSync();
170 void testSync();
171 };
171 };
172
172
173 namespace {
173 namespace {
174
174
175 void testSyncCase1()
175 void testSyncCase1()
176 {
176 {
177 // Id used to synchronize variables in the controller
177 // Id used to synchronize variables in the controller
178 auto syncId = QUuid::createUuid();
178 auto syncId = QUuid::createUuid();
179
179
180 /// Generates a range according to a start time and a end time (the date is the same)
180 /// Generates a range according to a start time and a end time (the date is the same)
181 auto range = [](const QTime &startTime, const QTime &endTime) {
181 auto range = [](const QTime &startTime, const QTime &endTime) {
182 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
182 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
183 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
183 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
184 };
184 };
185
185
186 auto initialRange = range({12, 0}, {13, 0});
186 auto initialRange = range({12, 0}, {13, 0});
187
187
188 Iterations iterations{};
188 Iterations iterations{};
189 // Creates variables var0, var1 and var2
189 // Creates variables var0, var1 and var2
190 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
190 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
191 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
191 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
192 iterations.push_back(
192 iterations.push_back(
193 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
193 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
194
194
195 // Adds variables into the sync group (ranges don't need to be tested here)
195 // Adds variables into the sync group (ranges don't need to be tested here)
196 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
196 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
197 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
197 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
198 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
198 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
199
199
200 // Moves var0: ranges of var0, var1 and var2 change
200 // Moves var0: ranges of var0, var1 and var2 change
201 auto newRange = range({12, 30}, {13, 30});
201 auto newRange = range({12, 30}, {13, 30});
202 iterations.push_back(
202 iterations.push_back(
203 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
203 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
204
204
205 // Moves var1: ranges of var0, var1 and var2 change
205 // Moves var1: ranges of var0, var1 and var2 change
206 newRange = range({13, 0}, {14, 0});
206 newRange = range({13, 0}, {14, 0});
207 iterations.push_back(
207 iterations.push_back(
208 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
208 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
209
209
210 // Moves var2: ranges of var0, var1 and var2 change
210 // Moves var2: ranges of var0, var1 and var2 change
211 newRange = range({13, 30}, {14, 30});
211 newRange = range({13, 30}, {14, 30});
212 iterations.push_back(
212 iterations.push_back(
213 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
213 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
214
214
215 // Desyncs var2 and moves var0:
215 // Desyncs var2 and moves var0:
216 // - ranges of var0 and var1 change
216 // - ranges of var0 and var1 change
217 // - range of var2 doesn't change anymore
217 // - range of var2 doesn't change anymore
218 auto var2Range = newRange;
218 auto var2Range = newRange;
219 newRange = range({13, 45}, {14, 45});
219 newRange = range({13, 45}, {14, 45});
220 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
220 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
221 iterations.push_back(
221 iterations.push_back(
222 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
222 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
223
223
224 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
224 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
225 auto var1Range = newRange;
225 auto var1Range = newRange;
226 newRange = range({14, 45}, {15, 45});
226 newRange = range({14, 45}, {15, 45});
227 iterations.push_back({std::make_shared<Move>(0, newRange, true),
227 iterations.push_back({std::make_shared<Move>(0, newRange, true),
228 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
228 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
229
229
230 // Moves var0 through several operations:
230 // Moves var0 through several operations:
231 // - range of var0 changes
231 // - range of var0 changes
232 // - range or var1 changes according to the previous shift (one hour)
232 // - range or var1 changes according to the previous shift (one hour)
233 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
233 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
234 iterations.push_back(
234 iterations.push_back(
235 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
235 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
236 };
236 };
237 // Pan left
237 // Pan left
238 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
238 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
239 // Pan right
239 // Pan right
240 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
240 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
241 // Zoom in
241 // Zoom in
242 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
242 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
243 // Zoom out
243 // Zoom out
244 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
244 moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0}));
245
245
246 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
246 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
247 }
247 }
248
248
249 void testSyncCase2()
249 void testSyncCase2()
250 {
250 {
251 // Id used to synchronize variables in the controller
251 // Id used to synchronize variables in the controller
252 auto syncId = QUuid::createUuid();
252 auto syncId = QUuid::createUuid();
253
253
254 /// Generates a range according to a start time and a end time (the date is the same)
254 /// Generates a range according to a start time and a end time (the date is the same)
255 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
255 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
256 return DateUtils::secondsSinceEpoch(
256 return DateUtils::secondsSinceEpoch(
257 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
257 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
258 };
258 };
259
259
260 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
260 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
261
261
262 Iterations iterations{};
262 Iterations iterations{};
263 // Creates variables var0 and var1
263 // Creates variables var0 and var1
264 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
264 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
265 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
265 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
266
266
267 // Adds variables into the sync group (ranges don't need to be tested here)
267 // Adds variables into the sync group (ranges don't need to be tested here)
268 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
268 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
269 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
269 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
270
270
271
271
272 // Moves var0 through several operations:
272 // Moves var0 through several operations:
273 // - range of var0 changes
273 // - range of var0 changes
274 // - range or var1 changes according to the previous shift (one hour)
274 // - range or var1 changes according to the previous shift (one hour)
275 auto moveVar0 = [&iterations](const auto &var0NewRange) {
275 auto moveVar0 = [&iterations](const auto &var0NewRange) {
276 iterations.push_back(
276 iterations.push_back(
277 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
277 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
278 };
278 };
279 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
279 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
280 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
280 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
281 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
281 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
282 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
282 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
283 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
283 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
284 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
284 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
285
285
286 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
286 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
287 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
287 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
288 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
288 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
289
289
290 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
290 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
291 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
291 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
292 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
292 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
293 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
293 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
294 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
294 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
295 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
295 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
296 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
296 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
297 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
297 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
298 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
298 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
299 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
299 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
300 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
300 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
301 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
301 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
302
302
303
303
304 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
304 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
305 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
305 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
306 }
306 }
307 }
307 }
308
308
309 void TestVariableSync::testSync_data()
309 void TestVariableSync::testSync_data()
310 {
310 {
311 // ////////////// //
311 // ////////////// //
312 // Test structure //
312 // Test structure //
313 // ////////////// //
313 // ////////////// //
314
314
315 QTest::addColumn<QUuid>("syncId");
315 QTest::addColumn<QUuid>("syncId");
316 QTest::addColumn<SqpRange>("initialRange");
316 QTest::addColumn<SqpRange>("initialRange");
317 QTest::addColumn<Iterations>("iterations");
317 QTest::addColumn<Iterations>("iterations");
318 QTest::addColumn<int>("operationDelay");
318 QTest::addColumn<int>("operationDelay");
319
319
320 // ////////// //
320 // ////////// //
321 // Test cases //
321 // Test cases //
322 // ////////// //
322 // ////////// //
323
323
324 testSyncCase1();
324 testSyncCase1();
325 testSyncCase2();
325 // testSyncCase2();
326 }
326 }
327
327
328 void TestVariableSync::testSync()
328 void TestVariableSync::testSync()
329 {
329 {
330 // Inits controllers
330 // Inits controllers
331 TimeController timeController{};
331 TimeController timeController{};
332 VariableController variableController{};
332 VariableController variableController{};
333 variableController.setTimeController(&timeController);
333 variableController.setTimeController(&timeController);
334
334
335 QFETCH(QUuid, syncId);
335 QFETCH(QUuid, syncId);
336 QFETCH(SqpRange, initialRange);
336 QFETCH(SqpRange, initialRange);
337 timeController.onTimeToUpdate(initialRange);
337 timeController.onTimeToUpdate(initialRange);
338
338
339 // Synchronization group used
339 // Synchronization group used
340 variableController.onAddSynchronizationGroupId(syncId);
340 variableController.onAddSynchronizationGroupId(syncId);
341
341
342 auto validateRanges = [&variableController](const auto &expectedRanges) {
342 auto validateRanges = [&variableController](const auto &expectedRanges) {
343 for (const auto &expectedRangeEntry : expectedRanges) {
343 for (const auto &expectedRangeEntry : expectedRanges) {
344 auto variableIndex = expectedRangeEntry.first;
344 auto variableIndex = expectedRangeEntry.first;
345 auto expectedRange = expectedRangeEntry.second;
345 auto expectedRange = expectedRangeEntry.second;
346
346
347 // Gets the variable in the controller
347 // Gets the variable in the controller
348 auto variable = variableController.variableModel()->variable(variableIndex);
348 auto variable = variableController.variableModel()->variable(variableIndex);
349
349
350 // Compares variable's range to the expected range
350 // Compares variable's range to the expected range
351 QVERIFY(variable != nullptr);
351 QVERIFY(variable != nullptr);
352 auto range = variable->range();
352 auto range = variable->range();
353 QCOMPARE(range, expectedRange);
353 QCOMPARE(range, expectedRange);
354
354
355 // Compares variable's data with values expected for its range
355 // Compares variable's data with values expected for its range
356 auto dataSeries = variable->dataSeries();
356 auto dataSeries = variable->dataSeries();
357 QVERIFY(dataSeries != nullptr);
357 QVERIFY(dataSeries != nullptr);
358
358
359 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
359 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
360 auto expectedValues = values(range);
360 auto expectedValues = values(range);
361 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
361 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
362 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
362 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
363 [](const auto &dataSeriesIt, const auto &expectedValue) {
363 [](const auto &dataSeriesIt, const auto &expectedValue) {
364 return dataSeriesIt.value() == expectedValue;
364 return dataSeriesIt.value() == expectedValue;
365 }));
365 }));
366 }
366 }
367 };
367 };
368
368
369 // For each iteration:
369 // For each iteration:
370 // - execute operation
370 // - execute operation
371 // - compare the variables' state to the expected states
371 // - compare the variables' state to the expected states
372 QFETCH(Iterations, iterations);
372 QFETCH(Iterations, iterations);
373 QFETCH(int, operationDelay);
373 QFETCH(int, operationDelay);
374 for (const auto &iteration : iterations) {
374 for (const auto &iteration : iterations) {
375 iteration.m_Operation->exec(variableController);
375 iteration.m_Operation->exec(variableController);
376 QTest::qWait(operationDelay);
376 QTest::qWait(operationDelay);
377
377
378 validateRanges(iteration.m_ExpectedRanges);
378 validateRanges(iteration.m_ExpectedRanges);
379 }
379 }
380
380
381 for (const auto &iteration : iterations) {
381 for (const auto &iteration : iterations) {
382 iteration.m_Operation->exec(variableController);
382 iteration.m_Operation->exec(variableController);
383 }
383 }
384 QTest::qWait(operationDelay);
384 QTest::qWait(operationDelay);
385 validateRanges(iterations.back().m_ExpectedRanges);
385 validateRanges(iterations.back().m_ExpectedRanges);
386 }
386 }
387
387
388 QTEST_MAIN(TestVariableSync)
388 QTEST_MAIN(TestVariableSync)
389
389
390 #include "TestVariableSync.moc"
390 #include "TestVariableSync.moc"
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Merge lasted acquisition developpement on main Sciqlop branch

You need to be logged in to leave comments. Login now