@@ -15,12 +15,10 | |||||
15 | * @brief The VariableRequest struct holds the information of an acquisition request |
|
15 | * @brief The VariableRequest struct holds the information of an acquisition request | |
16 | */ |
|
16 | */ | |
17 | struct VariableRequest { |
|
17 | struct VariableRequest { | |
18 | VariableRequest() { m_CanUpdate = false; } |
|
18 | QUuid m_VariableGroupId; | |
19 |
|
||||
20 | SqpRange m_RangeRequested; |
|
19 | SqpRange m_RangeRequested; | |
21 | SqpRange m_CacheRangeRequested; |
|
20 | SqpRange m_CacheRangeRequested; | |
22 | std::shared_ptr<IDataSeries> m_DataSeries; |
|
21 | std::shared_ptr<IDataSeries> m_DataSeries; | |
23 | bool m_CanUpdate; |
|
|||
24 | }; |
|
22 | }; | |
25 |
|
23 | |||
26 | SCIQLOP_REGISTER_META_TYPE(VARIABLEREQUEST_REGISTRY, VariableRequest) |
|
24 | SCIQLOP_REGISTER_META_TYPE(VARIABLEREQUEST_REGISTRY, VariableRequest) |
@@ -183,7 +183,7 void VariableAcquisitionWorker::onVariableAcquisitionFailed(QUuid acqIdentifier) | |||||
183 | if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) { |
|
183 | if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |
184 | auto request = it->second; |
|
184 | auto request = it->second; | |
185 | impl->unlock(); |
|
185 | impl->unlock(); | |
186 |
qC |
|
186 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed") | |
187 | << acqIdentifier << request.m_vIdentifier |
|
187 | << acqIdentifier << request.m_vIdentifier | |
188 | << QThread::currentThread(); |
|
188 | << QThread::currentThread(); | |
189 | emit variableCanceledRequested(request.m_vIdentifier); |
|
189 | emit variableCanceledRequested(request.m_vIdentifier); |
This diff has been collapsed as it changes many lines, (627 lines changed) Show them Hide them | |||||
@@ -77,6 +77,23 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange & | |||||
77 | } |
|
77 | } | |
78 | } |
|
78 | } | |
79 |
|
79 | |||
|
80 | enum class VariableRequestHandlerState { OFF, RUNNING, PENDING }; | |||
|
81 | ||||
|
82 | struct VariableRequestHandler { | |||
|
83 | ||||
|
84 | VariableRequestHandler() | |||
|
85 | { | |||
|
86 | m_CanUpdate = false; | |||
|
87 | m_State = VariableRequestHandlerState::OFF; | |||
|
88 | } | |||
|
89 | ||||
|
90 | QUuid m_VarId; | |||
|
91 | VariableRequest m_RunningVarRequest; | |||
|
92 | VariableRequest m_PendingVarRequest; | |||
|
93 | VariableRequestHandlerState m_State; | |||
|
94 | bool m_CanUpdate; | |||
|
95 | }; | |||
|
96 | ||||
80 | struct VariableController::VariableControllerPrivate { |
|
97 | struct VariableController::VariableControllerPrivate { | |
81 | explicit VariableControllerPrivate(VariableController *parent) |
|
98 | explicit VariableControllerPrivate(VariableController *parent) | |
82 | : m_WorkingMutex{}, |
|
99 | : m_WorkingMutex{}, | |
@@ -113,10 +130,10 struct VariableController::VariableControllerPrivate { | |||||
113 |
|
130 | |||
114 | void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest); |
|
131 | void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest); | |
115 | QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries); |
|
132 | QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries); | |
|
133 | void updateVariables(QUuid varRequestId); | |||
116 | void updateVariableRequest(QUuid varRequestId); |
|
134 | void updateVariableRequest(QUuid varRequestId); | |
117 | void cancelVariableRequest(QUuid varRequestId); |
|
135 | void cancelVariableRequest(QUuid varRequestId); | |
118 |
|
136 | void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest); | ||
119 | SqpRange getLastRequestedRange(QUuid varId); |
|
|||
120 |
|
137 | |||
121 | QMutex m_WorkingMutex; |
|
138 | QMutex m_WorkingMutex; | |
122 | /// Variable model. The VariableController has the ownership |
|
139 | /// Variable model. The VariableController has the ownership | |
@@ -137,10 +154,8 struct VariableController::VariableControllerPrivate { | |||||
137 | std::map<QUuid, QUuid> m_VariableIdGroupIdMap; |
|
154 | std::map<QUuid, QUuid> m_VariableIdGroupIdMap; | |
138 | std::set<std::shared_ptr<IDataProvider> > m_ProviderSet; |
|
155 | std::set<std::shared_ptr<IDataProvider> > m_ProviderSet; | |
139 |
|
156 | |||
140 |
std::map<QUuid, std:: |
|
157 | std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds; | |
141 |
|
158 | std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler; | ||
142 | std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap; |
|
|||
143 |
|
||||
144 |
|
159 | |||
145 | VariableController *q; |
|
160 | VariableController *q; | |
146 | }; |
|
161 | }; | |
@@ -275,20 +290,28 VariableController::createVariable(const QString &name, const QVariantHash &meta | |||||
275 | auto range = impl->m_TimeController->dateTime(); |
|
290 | auto range = impl->m_TimeController->dateTime(); | |
276 |
|
291 | |||
277 | if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) { |
|
292 | if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) { | |
278 |
auto |
|
293 | auto varId = QUuid::createUuid(); | |
|
294 | ||||
|
295 | // Create the handler | |||
|
296 | auto varRequestHandler = std::make_unique<VariableRequestHandler>(); | |||
|
297 | varRequestHandler->m_VarId = varId; | |||
|
298 | ||||
|
299 | impl->m_VarIdToVarRequestHandler.insert( | |||
|
300 | std::make_pair(varId, std::move(varRequestHandler))); | |||
279 |
|
301 | |||
280 | // store the provider |
|
302 | // store the provider | |
281 | impl->registerProvider(provider); |
|
303 | impl->registerProvider(provider); | |
282 |
|
304 | |||
283 | // Associate the provider |
|
305 | // Associate the provider | |
284 | impl->m_VariableToProviderMap[newVariable] = provider; |
|
306 | impl->m_VariableToProviderMap[newVariable] = provider; | |
285 | qCInfo(LOG_VariableController()) << "createVariable: " << identifier; |
|
307 | impl->m_VariableToIdentifierMap[newVariable] = varId; | |
286 | impl->m_VariableToIdentifierMap[newVariable] = identifier; |
|
|||
287 |
|
308 | |||
|
309 | this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false); | |||
288 |
|
310 | |||
289 | auto varRequestId = QUuid::createUuid(); |
|
311 | // auto varRequestId = QUuid::createUuid(); | |
290 | impl->processRequest(newVariable, range, varRequestId); |
|
312 | // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId; | |
291 |
impl-> |
|
313 | // impl->processRequest(newVariable, range, varRequestId); | |
|
314 | // impl->updateVariableRequest(varRequestId); | |||
292 |
|
315 | |||
293 | return newVariable; |
|
316 | return newVariable; | |
294 | } |
|
317 | } | |
@@ -300,19 +323,51 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime) | |||||
300 | qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection" |
|
323 | qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection" | |
301 | << QThread::currentThread()->objectName(); |
|
324 | << QThread::currentThread()->objectName(); | |
302 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); |
|
325 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); | |
303 | auto variables = QVector<std::shared_ptr<Variable> >{}; |
|
|||
304 |
|
326 | |||
305 | for (const auto &selectedRow : qAsConst(selectedRows)) { |
|
327 | // NOTE we only permit the time modification for one variable | |
306 | if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) { |
|
328 | // DEPRECATED | |
307 | variables << selectedVariable; |
|
329 | // auto variables = QVector<std::shared_ptr<Variable> >{}; | |
|
330 | // for (const auto &selectedRow : qAsConst(selectedRows)) { | |||
|
331 | // if (auto selectedVariable = | |||
|
332 | // impl->m_VariableModel->variable(selectedRow.row())) { | |||
|
333 | // variables << selectedVariable; | |||
|
334 | ||||
|
335 | // // notify that rescale operation has to be done | |||
|
336 | // emit rangeChanged(selectedVariable, dateTime); | |||
|
337 | // } | |||
|
338 | // } | |||
|
339 | // if (!variables.isEmpty()) { | |||
|
340 | // this->onRequestDataLoading(variables, dateTime, synchro); | |||
|
341 | // } | |||
|
342 | if (selectedRows.size() == 1) { | |||
|
343 | ||||
|
344 | if (auto selectedVariable | |||
|
345 | = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) { | |||
|
346 | ||||
|
347 | auto itVar = impl->m_VariableToIdentifierMap.find(selectedVariable); | |||
|
348 | if (itVar == impl->m_VariableToIdentifierMap.cend()) { | |||
|
349 | qCCritical(LOG_VariableController()) | |||
|
350 | << tr("Impossible to onDateTimeOnSelection request for unknown variable"); | |||
|
351 | return; | |||
|
352 | } | |||
308 |
|
353 | |||
309 | // notify that rescale operation has to be done |
|
354 | // notify that rescale operation has to be done | |
310 | emit rangeChanged(selectedVariable, dateTime); |
|
355 | emit rangeChanged(selectedVariable, dateTime); | |
|
356 | ||||
|
357 | auto synchro = impl->m_VariableIdGroupIdMap.find(itVar->second) | |||
|
358 | != impl->m_VariableIdGroupIdMap.cend(); | |||
|
359 | ||||
|
360 | this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{selectedVariable}, | |||
|
361 | dateTime, synchro); | |||
311 | } |
|
362 | } | |
312 | } |
|
363 | } | |
313 |
|
364 | else if (selectedRows.size() > 1) { | ||
314 | if (!variables.isEmpty()) { |
|
365 | qCCritical(LOG_VariableController()) | |
315 | this->onRequestDataLoading(variables, dateTime, true); |
|
366 | << tr("Impossible to set time for more than 1 variable in the same time"); | |
|
367 | } | |||
|
368 | else { | |||
|
369 | qCWarning(LOG_VariableController()) | |||
|
370 | << tr("There is no variable selected to set the time one"); | |||
316 | } |
|
371 | } | |
317 | } |
|
372 | } | |
318 |
|
373 | |||
@@ -320,10 +375,11 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &range | |||||
320 | const SqpRange &cacheRangeRequested, |
|
375 | const SqpRange &cacheRangeRequested, | |
321 | QVector<AcquisitionDataPacket> dataAcquired) |
|
376 | QVector<AcquisitionDataPacket> dataAcquired) | |
322 | { |
|
377 | { | |
|
378 | qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread(); | |||
323 | auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired); |
|
379 | auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired); | |
324 | auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries); |
|
380 | auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries); | |
325 | if (!varRequestId.isNull()) { |
|
381 | if (!varRequestId.isNull()) { | |
326 |
impl->updateVariable |
|
382 | impl->updateVariables(varRequestId); | |
327 | } |
|
383 | } | |
328 | } |
|
384 | } | |
329 |
|
385 | |||
@@ -343,30 +399,30 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, doub | |||||
343 |
|
399 | |||
344 | void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable) |
|
400 | void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable) | |
345 | { |
|
401 | { | |
346 | auto it = impl->m_VariableToIdentifierMap.find(variable); |
|
402 | qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested" | |
347 | if (it != impl->m_VariableToIdentifierMap.cend()) { |
|
403 | << QThread::currentThread()->objectName() << variable->name(); | |
348 | impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second); |
|
|||
349 |
|
404 | |||
350 | QUuid varRequestId; |
|
405 | auto itVar = impl->m_VariableToIdentifierMap.find(variable); | |
351 | auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second); |
|
406 | if (itVar == impl->m_VariableToIdentifierMap.cend()) { | |
352 | if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) { |
|
407 | qCCritical(LOG_VariableController()) | |
353 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
408 | << tr("Impossible to onAbortProgressRequested request for unknown variable"); | |
354 | varRequestId = varRequestIdQueue.front(); |
|
409 | return; | |
355 | impl->cancelVariableRequest(varRequestId); |
|
|||
356 |
|
||||
357 | // Finish the progression for the request |
|
|||
358 | impl->m_VariableModel->setDataProgress(variable, 0.0); |
|
|||
359 | } |
|
|||
360 | else { |
|
|||
361 | qCWarning(LOG_VariableController()) |
|
|||
362 | << tr("Aborting progression of inexistant variable request detected !!!") |
|
|||
363 | << QThread::currentThread()->objectName(); |
|
|||
364 |
|
|
410 | } | |
|
411 | ||||
|
412 | auto varId = itVar->second; | |||
|
413 | ||||
|
414 | auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId); | |||
|
415 | if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) { | |||
|
416 | qCCritical(LOG_VariableController()) | |||
|
417 | << tr("Impossible to onAbortProgressRequested for variable with unknown handler"); | |||
|
418 | return; | |||
365 | } |
|
419 | } | |
366 | else { |
|
420 | ||
367 | qCWarning(LOG_VariableController()) |
|
421 | auto varHandler = itVarHandler->second.get(); | |
368 | << tr("Aborting progression of inexistant variable detected !!!") |
|
422 | ||
369 | << QThread::currentThread()->objectName(); |
|
423 | // case where a variable has a running request | |
|
424 | if (varHandler->m_State != VariableRequestHandlerState::OFF) { | |||
|
425 | impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId); | |||
370 | } |
|
426 | } | |
371 | } |
|
427 | } | |
372 |
|
428 | |||
@@ -460,58 +516,59 void VariableController::desynchronize(std::shared_ptr<Variable> variable, | |||||
460 | void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, |
|
516 | void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, | |
461 | const SqpRange &range, bool synchronise) |
|
517 | const SqpRange &range, bool synchronise) | |
462 | { |
|
518 | { | |
463 | // NOTE: oldRange isn't really necessary since oldRange == variable->range(). |
|
519 | // variables is assumed synchronized | |
464 |
|
520 | // TODO: Asser variables synchronization | ||
465 | // we want to load data of the variable for the dateTime. |
|
521 | // we want to load data of the variable for the dateTime. | |
466 | // First we check if the cache contains some of them. |
|
522 | if (variables.isEmpty()) { | |
467 | // For the other, we ask the provider to give them. |
|
523 | return; | |
|
524 | } | |||
468 |
|
525 | |||
469 | auto varRequestId = QUuid::createUuid(); |
|
526 | auto varRequestId = QUuid::createUuid(); | |
470 | qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading" |
|
527 | qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading" | |
471 |
<< QThread::currentThread()->objectName() << varRequestId |
|
528 | << QThread::currentThread()->objectName() << varRequestId | |
|
529 | << range << synchronise; | |||
472 |
|
530 | |||
|
531 | if (!synchronise) { | |||
|
532 | auto varIds = std::list<QUuid>{}; | |||
473 | for (const auto &var : variables) { |
|
533 | for (const auto &var : variables) { | |
474 | qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId; |
|
534 | auto vId = impl->m_VariableToIdentifierMap.at(var); | |
475 | impl->processRequest(var, range, varRequestId); |
|
535 | varIds.push_back(vId); | |
476 | } |
|
536 | } | |
477 |
|
537 | impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds)); | ||
478 | if (synchronise) { |
|
|||
479 | // Get the group ids |
|
|||
480 | qCDebug(LOG_VariableController()) |
|
|||
481 | << "TORM VariableController::onRequestDataLoading for synchro var ENABLE"; |
|
|||
482 | auto groupIds = std::set<QUuid>{}; |
|
|||
483 | auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{}; |
|
|||
484 | for (const auto &var : variables) { |
|
538 | for (const auto &var : variables) { | |
485 | auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var); |
|
539 | qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId | |
486 | if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) { |
|
540 | << varIds.size(); | |
487 | auto vId = varToVarIdIt->second; |
|
541 | impl->processRequest(var, range, varRequestId); | |
488 | auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId); |
|
|||
489 | if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) { |
|
|||
490 | auto gId = varIdToGroupIdIt->second; |
|
|||
491 | groupIdToOldRangeMap.insert(std::make_pair(gId, var->range())); |
|
|||
492 | if (groupIds.find(gId) == groupIds.cend()) { |
|
|||
493 | qCDebug(LOG_VariableController()) << "Synchro detect group " << gId; |
|
|||
494 | groupIds.insert(gId); |
|
|||
495 | } |
|
|||
496 | } |
|
|||
497 |
|
|
542 | } | |
498 |
|
|
543 | } | |
|
544 | else { | |||
|
545 | auto vId = impl->m_VariableToIdentifierMap.at(variables.first()); | |||
|
546 | auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId); | |||
|
547 | if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) { | |||
|
548 | auto groupId = varIdToGroupIdIt->second; | |||
499 |
|
549 | |||
500 | // We assume here all group ids exist |
|
550 | auto vSynchronizationGroup | |
501 | for (const auto &gId : groupIds) { |
|
551 | = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId); | |
502 | auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId); |
|
|||
503 | auto vSyncIds = vSynchronizationGroup->getIds(); |
|
552 | auto vSyncIds = vSynchronizationGroup->getIds(); | |
504 | qCDebug(LOG_VariableController()) << "Var in synchro group "; |
|
553 | ||
|
554 | auto varIds = std::list<QUuid>{}; | |||
|
555 | for (auto vId : vSyncIds) { | |||
|
556 | varIds.push_back(vId); | |||
|
557 | } | |||
|
558 | impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds)); | |||
|
559 | ||||
505 | for (auto vId : vSyncIds) { |
|
560 | for (auto vId : vSyncIds) { | |
506 | auto var = impl->findVariable(vId); |
|
561 | auto var = impl->findVariable(vId); | |
507 |
|
562 | |||
508 | // Don't process already processed var |
|
563 | // Don't process already processed var | |
509 | if (!variables.contains(var)) { |
|
|||
510 |
|
|
564 | if (var != nullptr) { | |
511 |
|
|
565 | qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name() | |
512 |
|
|
566 | << varRequestId; | |
513 |
|
|
567 | auto vSyncRangeRequested | |
514 | var->range(), range, groupIdToOldRangeMap.at(gId)); |
|
568 | = variables.contains(var) | |
|
569 | ? range | |||
|
570 | : computeSynchroRangeRequested(var->range(), range, | |||
|
571 | variables.first()->range()); | |||
515 |
|
|
572 | qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested; | |
516 |
|
|
573 | impl->processRequest(var, vSyncRangeRequested, varRequestId); | |
517 |
|
|
574 | } | |
@@ -523,9 +580,8 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> | |||||
523 |
|
|
580 | } | |
524 |
|
|
581 | } | |
525 |
|
|
582 | } | |
526 | } |
|
|||
527 |
|
583 | |||
528 |
impl->updateVariable |
|
584 | impl->updateVariables(varRequestId); | |
529 | } |
|
585 | } | |
530 |
|
586 | |||
531 |
|
587 | |||
@@ -576,66 +632,70 void VariableController::VariableControllerPrivate::processRequest(std::shared_p | |||||
576 | const SqpRange &rangeRequested, |
|
632 | const SqpRange &rangeRequested, | |
577 | QUuid varRequestId) |
|
633 | QUuid varRequestId) | |
578 | { |
|
634 | { | |
579 | auto varRequest = VariableRequest{}; |
|
635 | auto itVar = m_VariableToIdentifierMap.find(var); | |
|
636 | if (itVar == m_VariableToIdentifierMap.cend()) { | |||
|
637 | qCCritical(LOG_VariableController()) | |||
|
638 | << tr("Impossible to process request for unknown variable"); | |||
|
639 | return; | |||
|
640 | } | |||
580 |
|
641 | |||
581 | auto it = m_VariableToIdentifierMap.find(var); |
|
642 | auto varId = itVar->second; | |
582 | if (it != m_VariableToIdentifierMap.cend()) { |
|
|||
583 |
|
643 | |||
584 | auto varId = it->second; |
|
644 | auto itVarHandler = m_VarIdToVarRequestHandler.find(varId); | |
|
645 | if (itVarHandler == m_VarIdToVarRequestHandler.cend()) { | |||
|
646 | qCCritical(LOG_VariableController()) | |||
|
647 | << tr("Impossible to process request for variable with unknown handler"); | |||
|
648 | return; | |||
|
649 | } | |||
|
650 | ||||
|
651 | auto oldRange = var->range(); | |||
585 |
|
652 | |||
586 | auto oldRange = getLastRequestedRange(varId); |
|
653 | auto varHandler = itVarHandler->second.get(); | |
587 |
|
654 | |||
588 | // check for update oldRange to the last request range. |
|
655 | if (varHandler->m_State != VariableRequestHandlerState::OFF) { | |
589 | if (oldRange == INVALID_RANGE) { |
|
656 | oldRange = varHandler->m_RunningVarRequest.m_RangeRequested; | |
590 | oldRange = var->range(); |
|
|||
591 |
|
|
657 | } | |
592 |
|
658 | |||
|
659 | auto varRequest = VariableRequest{}; | |||
|
660 | varRequest.m_VariableGroupId = varRequestId; | |||
593 |
|
|
661 | auto varStrategyRangesRequested | |
594 |
|
|
662 | = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested); | |
595 |
|
||||
596 | auto notInCacheRangeList |
|
|||
597 | = Variable::provideNotInCacheRangeList(oldRange, varStrategyRangesRequested.second); |
|
|||
598 | auto inCacheRangeList |
|
|||
599 | = Variable::provideInCacheRangeList(oldRange, varStrategyRangesRequested.second); |
|
|||
600 |
|
||||
601 | if (!notInCacheRangeList.empty()) { |
|
|||
602 |
|
|
663 | varRequest.m_RangeRequested = varStrategyRangesRequested.first; | |
603 |
|
|
664 | varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second; | |
604 |
|
665 | |||
605 | // store VarRequest |
|
666 | switch (varHandler->m_State) { | |
606 | storeVariableRequest(varId, varRequestId, varRequest); |
|
667 | case VariableRequestHandlerState::OFF: { | |
607 |
|
668 | qCDebug(LOG_VariableController()) << tr("Process Request OFF") | ||
608 | auto varProvider = m_VariableToProviderMap.at(var); |
|
669 | << varRequest.m_RangeRequested | |
609 | if (varProvider != nullptr) { |
|
670 | << varRequest.m_CacheRangeRequested; | |
610 | auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest( |
|
671 | varHandler->m_RunningVarRequest = varRequest; | |
611 | varRequestId, varId, varStrategyRangesRequested.first, |
|
672 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |
612 | varStrategyRangesRequested.second, |
|
673 | executeVarRequest(var, varRequest); | |
613 | DataProviderParameters{std::move(notInCacheRangeList), var->metadata()}, |
|
674 | break; | |
614 | varProvider); |
|
|||
615 |
|
||||
616 | if (!varRequestIdCanceled.isNull()) { |
|
|||
617 | qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ") |
|
|||
618 | << varRequestIdCanceled; |
|
|||
619 | cancelVariableRequest(varRequestIdCanceled); |
|
|||
620 | } |
|
|||
621 |
|
|
675 | } | |
622 | else { |
|
676 | case VariableRequestHandlerState::RUNNING: { | |
623 |
|
|
677 | qCDebug(LOG_VariableController()) << tr("Process Request RUNNING") | |
624 | << "Impossible to provide data with a null provider"; |
|
678 | << varRequest.m_RangeRequested | |
|
679 | << varRequest.m_CacheRangeRequested; | |||
|
680 | varHandler->m_State = VariableRequestHandlerState::PENDING; | |||
|
681 | varHandler->m_PendingVarRequest = varRequest; | |||
|
682 | break; | |||
625 |
|
|
683 | } | |
|
684 | case VariableRequestHandlerState::PENDING: { | |||
|
685 | qCDebug(LOG_VariableController()) << tr("Process Request PENDING") | |||
|
686 | << varRequest.m_RangeRequested | |||
|
687 | << varRequest.m_CacheRangeRequested; | |||
|
688 | auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId; | |||
|
689 | cancelVariableRequest(variableGroupIdToCancel); | |||
|
690 | // Cancel variable can make state downgrade | |||
|
691 | varHandler->m_State = VariableRequestHandlerState::PENDING; | |||
|
692 | varHandler->m_PendingVarRequest = varRequest; | |||
626 |
|
693 | |||
627 | if (!inCacheRangeList.empty()) { |
|
694 | break; | |
628 | emit q->updateVarDisplaying(var, inCacheRangeList.first()); |
|
|||
629 | } |
|
|||
630 | } |
|
|||
631 | else { |
|
|||
632 | varRequest.m_RangeRequested = varStrategyRangesRequested.first; |
|
|||
633 | varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second; |
|
|||
634 | // store VarRequest |
|
|||
635 | storeVariableRequest(varId, varRequestId, varRequest); |
|
|||
636 | acceptVariableRequest( |
|
|||
637 | varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second)); |
|
|||
638 | } |
|
695 | } | |
|
696 | default: | |||
|
697 | qCCritical(LOG_VariableController()) | |||
|
698 | << QObject::tr("Unknown VariableRequestHandlerState"); | |||
639 | } |
|
699 | } | |
640 | } |
|
700 | } | |
641 |
|
701 | |||
@@ -696,105 +756,63 void VariableController::VariableControllerPrivate::registerProvider( | |||||
696 | } |
|
756 | } | |
697 | } |
|
757 | } | |
698 |
|
758 | |||
699 | void VariableController::VariableControllerPrivate::storeVariableRequest( |
|
|||
700 | QUuid varId, QUuid varRequestId, const VariableRequest &varRequest) |
|
|||
701 | { |
|
|||
702 | // First request for the variable. we can create an entry for it |
|
|||
703 | auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId); |
|
|||
704 | if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) { |
|
|||
705 | auto varRequestIdQueue = std::deque<QUuid>{}; |
|
|||
706 | qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE"); |
|
|||
707 | varRequestIdQueue.push_back(varRequestId); |
|
|||
708 | m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue))); |
|
|||
709 | } |
|
|||
710 | else { |
|
|||
711 | qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE"); |
|
|||
712 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
713 | varRequestIdQueue.push_back(varRequestId); |
|
|||
714 | } |
|
|||
715 |
|
||||
716 | auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
|||
717 | if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
718 | auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{}; |
|
|||
719 | varIdToVarRequestMap.insert(std::make_pair(varId, varRequest)); |
|
|||
720 | qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP"); |
|
|||
721 | m_VarRequestIdToVarIdVarRequestMap.insert( |
|
|||
722 | std::make_pair(varRequestId, std::move(varIdToVarRequestMap))); |
|
|||
723 | } |
|
|||
724 | else { |
|
|||
725 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
726 | qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP"); |
|
|||
727 | varIdToVarRequestMap.insert(std::make_pair(varId, varRequest)); |
|
|||
728 | } |
|
|||
729 | } |
|
|||
730 |
|
||||
731 | QUuid VariableController::VariableControllerPrivate::acceptVariableRequest( |
|
759 | QUuid VariableController::VariableControllerPrivate::acceptVariableRequest( | |
732 | QUuid varId, std::shared_ptr<IDataSeries> dataSeries) |
|
760 | QUuid varId, std::shared_ptr<IDataSeries> dataSeries) | |
733 | { |
|
761 | { | |
734 | QUuid varRequestId; |
|
762 | auto itVarHandler = m_VarIdToVarRequestHandler.find(varId); | |
735 | auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId); |
|
763 | if (itVarHandler == m_VarIdToVarRequestHandler.cend()) { | |
736 | if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) { |
|
764 | return QUuid(); | |
737 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
|||
738 | varRequestId = varRequestIdQueue.front(); |
|
|||
739 | auto varRequestIdToVarIdVarRequestMapIt |
|
|||
740 | = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
|||
741 | if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
742 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
743 | auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId); |
|
|||
744 | if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) { |
|
|||
745 | qCDebug(LOG_VariableController()) << tr("acceptVariableRequest"); |
|
|||
746 | auto &varRequest = varIdToVarRequestMapIt->second; |
|
|||
747 | varRequest.m_DataSeries = dataSeries; |
|
|||
748 | varRequest.m_CanUpdate = true; |
|
|||
749 | } |
|
|||
750 | else { |
|
|||
751 | qCDebug(LOG_VariableController()) |
|
|||
752 | << tr("Impossible to acceptVariableRequest of a unknown variable id attached " |
|
|||
753 | "to a variableRequestId") |
|
|||
754 | << varRequestId << varId; |
|
|||
755 | } |
|
|||
756 | } |
|
|||
757 | else { |
|
|||
758 | qCCritical(LOG_VariableController()) |
|
|||
759 | << tr("Impossible to acceptVariableRequest of a unknown variableRequestId") |
|
|||
760 | << varRequestId; |
|
|||
761 |
|
|
765 | } | |
762 |
|
766 | |||
763 | varRequestIdQueue.pop_front(); |
|
767 | auto varHandler = itVarHandler->second.get(); | |
764 | if (varRequestIdQueue.empty()) { |
|
768 | if (varHandler->m_State == VariableRequestHandlerState::OFF) { | |
765 | qCDebug(LOG_VariableController()) |
|
|||
766 | << tr("TORM Erase REQUEST because it has been accepted") << varId; |
|
|||
767 | m_VarIdToVarRequestIdQueueMap.erase(varId); |
|
|||
768 | } |
|
|||
769 | } |
|
|||
770 | else { |
|
|||
771 | qCCritical(LOG_VariableController()) |
|
769 | qCCritical(LOG_VariableController()) | |
772 |
<< tr(" |
|
770 | << tr("acceptVariableRequest impossible on a variable with OFF state"); | |
773 | } |
|
771 | } | |
774 |
|
772 | |||
775 | return varRequestId; |
|
773 | varHandler->m_RunningVarRequest.m_DataSeries = dataSeries; | |
|
774 | varHandler->m_CanUpdate = true; | |||
|
775 | ||||
|
776 | // Element traitΓ©, on a dΓ©jΓ toutes les donnΓ©es necessaires | |||
|
777 | auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId; | |||
|
778 | qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId | |||
|
779 | << m_VarGroupIdToVarIds.size(); | |||
|
780 | ||||
|
781 | return varHandler->m_RunningVarRequest.m_VariableGroupId; | |||
776 | } |
|
782 | } | |
777 |
|
783 | |||
778 |
void VariableController::VariableControllerPrivate::updateVariable |
|
784 | void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId) | |
779 | { |
|
785 | { | |
|
786 | qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables" | |||
|
787 | << QThread::currentThread()->objectName() << varRequestId; | |||
780 |
|
788 | |||
781 |
auto var |
|
789 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |
782 |
if (var |
|
790 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |
|
791 | qCWarning(LOG_VariableController()) | |||
|
792 | << tr("Impossible to updateVariables of unknown variables") << varRequestId; | |||
|
793 | return; | |||
|
794 | } | |||
|
795 | ||||
|
796 | auto &varIds = varGroupIdToVarIdsIt->second; | |||
|
797 | auto varIdsEnd = varIds.end(); | |||
783 |
|
|
798 | bool processVariableUpdate = true; | |
784 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
799 | qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables" | |
785 | for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin(); |
|
800 | << varRequestId << varIds.size(); | |
786 |
|
|
801 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate; | |
787 |
|
|
802 | ++varIdsIt) { | |
788 | processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate; |
|
803 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |
789 | qCDebug(LOG_VariableController()) << tr("updateVariableRequest") |
|
804 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |
790 | << processVariableUpdate; |
|
805 | processVariableUpdate &= itVarHandler->second->m_CanUpdate; | |
|
806 | } | |||
791 |
|
|
807 | } | |
792 |
|
808 | |||
793 |
|
|
809 | if (processVariableUpdate) { | |
794 | for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin(); |
|
810 | qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size(); | |
795 | varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) { |
|
811 | for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) { | |
796 | if (auto var = findVariable(varIdToVarRequestMapIt->first)) { |
|
812 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |
797 | auto &varRequest = varIdToVarRequestMapIt->second; |
|
813 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |
|
814 | if (auto var = findVariable(*varIdsIt)) { | |||
|
815 | auto &varRequest = itVarHandler->second->m_RunningVarRequest; | |||
798 | var->setRange(varRequest.m_RangeRequested); |
|
816 | var->setRange(varRequest.m_RangeRequested); | |
799 | var->setCacheRange(varRequest.m_CacheRangeRequested); |
|
817 | var->setCacheRange(varRequest.m_CacheRangeRequested); | |
800 | qCDebug(LOG_VariableController()) << tr("1: onDataProvided") |
|
818 | qCDebug(LOG_VariableController()) << tr("1: onDataProvided") | |
@@ -808,82 +826,187 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid | |||||
808 | << var->nbPoints(); |
|
826 | << var->nbPoints(); | |
809 |
|
827 | |||
810 | emit var->updated(); |
|
828 | emit var->updated(); | |
|
829 | qCDebug(LOG_VariableController()) << tr("Update OK"); | |||
811 | } |
|
830 | } | |
812 | else { |
|
831 | else { | |
813 | qCCritical(LOG_VariableController()) |
|
832 | qCCritical(LOG_VariableController()) | |
814 | << tr("Impossible to update data to a null variable"); |
|
833 | << tr("Impossible to update data to a null variable"); | |
815 | } |
|
834 | } | |
816 | } |
|
835 | } | |
|
836 | } | |||
|
837 | updateVariableRequest(varRequestId); | |||
|
838 | ||||
817 |
|
|
839 | // cleaning varRequestId | |
818 |
|
|
840 | qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId; | |
819 | << m_VarRequestIdToVarIdVarRequestMap.size(); |
|
841 | m_VarGroupIdToVarIds.erase(varRequestId); | |
820 | m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId); |
|
|||
821 | qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?") |
|
|||
822 | << m_VarRequestIdToVarIdVarRequestMap.size(); |
|
|||
823 |
|
|
842 | } | |
824 | } |
|
843 | } | |
825 | else { |
|
844 | ||
|
845 | ||||
|
846 | void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId) | |||
|
847 | { | |||
|
848 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |||
|
849 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |||
|
850 | qCCritical(LOG_VariableController()) << QObject::tr( | |||
|
851 | "Impossible to updateVariableRequest since varGroupdId isn't here anymore"); | |||
|
852 | ||||
|
853 | return; | |||
|
854 | } | |||
|
855 | ||||
|
856 | auto &varIds = varGroupIdToVarIdsIt->second; | |||
|
857 | auto varIdsEnd = varIds.end(); | |||
|
858 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) { | |||
|
859 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
860 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
861 | ||||
|
862 | auto varHandler = itVarHandler->second.get(); | |||
|
863 | varHandler->m_CanUpdate = false; | |||
|
864 | ||||
|
865 | ||||
|
866 | switch (varHandler->m_State) { | |||
|
867 | case VariableRequestHandlerState::OFF: { | |||
|
868 | qCCritical(LOG_VariableController()) | |||
|
869 | << QObject::tr("Impossible to update a variable with handler in OFF state"); | |||
|
870 | } break; | |||
|
871 | case VariableRequestHandlerState::RUNNING: { | |||
|
872 | varHandler->m_State = VariableRequestHandlerState::OFF; | |||
|
873 | varHandler->m_RunningVarRequest = VariableRequest{}; | |||
|
874 | break; | |||
|
875 | } | |||
|
876 | case VariableRequestHandlerState::PENDING: { | |||
|
877 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |||
|
878 | varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest; | |||
|
879 | varHandler->m_PendingVarRequest = VariableRequest{}; | |||
|
880 | auto var = findVariable(itVarHandler->first); | |||
|
881 | executeVarRequest(var, varHandler->m_RunningVarRequest); | |||
|
882 | break; | |||
|
883 | } | |||
|
884 | default: | |||
826 | qCCritical(LOG_VariableController()) |
|
885 | qCCritical(LOG_VariableController()) | |
827 | << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId; |
|
886 | << QObject::tr("Unknown VariableRequestHandlerState"); | |
|
887 | } | |||
|
888 | } | |||
828 | } |
|
889 | } | |
829 | } |
|
890 | } | |
830 |
|
891 | |||
|
892 | ||||
831 | void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId) |
|
893 | void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId) | |
832 | { |
|
894 | { | |
833 | // cleaning varRequestId |
|
895 | qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId; | |
834 | m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId); |
|
|||
835 |
|
896 | |||
836 | for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin(); |
|
897 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |
837 |
|
|
898 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |
838 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
899 | qCCritical(LOG_VariableController()) | |
839 | varRequestIdQueue.erase( |
|
900 | << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId; | |
840 | std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId), |
|
901 | return; | |
841 | varRequestIdQueue.end()); |
|
902 | } | |
842 | if (varRequestIdQueue.empty()) { |
|
|||
843 | varIdToVarRequestIdQueueMapIt |
|
|||
844 | = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt); |
|
|||
845 |
|
903 | |||
846 | // Recompute if there is any next request based on the removed request. |
|
904 | auto &varIds = varGroupIdToVarIdsIt->second; | |
|
905 | auto varIdsEnd = varIds.end(); | |||
|
906 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) { | |||
|
907 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
908 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
909 | ||||
|
910 | auto varHandler = itVarHandler->second.get(); | |||
|
911 | varHandler->m_VarId = QUuid{}; | |||
|
912 | switch (varHandler->m_State) { | |||
|
913 | case VariableRequestHandlerState::OFF: { | |||
|
914 | qCWarning(LOG_VariableController()) | |||
|
915 | << QObject::tr("Impossible to cancel a variable with no running request"); | |||
|
916 | break; | |||
|
917 | } | |||
|
918 | case VariableRequestHandlerState::RUNNING: { | |||
|
919 | ||||
|
920 | if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) { | |||
|
921 | auto var = findVariable(itVarHandler->first); | |||
|
922 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
923 | if (varProvider != nullptr) { | |||
|
924 | m_VariableAcquisitionWorker->abortProgressRequested( | |||
|
925 | itVarHandler->first); | |||
|
926 | } | |||
|
927 | m_VariableModel->setDataProgress(var, 0.0); | |||
|
928 | varHandler->m_CanUpdate = false; | |||
|
929 | varHandler->m_State = VariableRequestHandlerState::OFF; | |||
|
930 | varHandler->m_RunningVarRequest = VariableRequest{}; | |||
847 | } |
|
931 | } | |
848 | else { |
|
932 | else { | |
849 | ++varIdToVarRequestIdQueueMapIt; |
|
933 | // TODO: log Impossible to cancel the running variable request beacause its | |
|
934 | // varRequestId isn't not the canceled one | |||
850 | } |
|
935 | } | |
|
936 | break; | |||
851 | } |
|
937 | } | |
|
938 | case VariableRequestHandlerState::PENDING: { | |||
|
939 | if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) { | |||
|
940 | auto var = findVariable(itVarHandler->first); | |||
|
941 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
942 | if (varProvider != nullptr) { | |||
|
943 | m_VariableAcquisitionWorker->abortProgressRequested( | |||
|
944 | itVarHandler->first); | |||
852 | } |
|
945 | } | |
853 |
|
946 | m_VariableModel->setDataProgress(var, 0.0); | ||
854 | SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId) |
|
947 | varHandler->m_CanUpdate = false; | |
855 | { |
|
948 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |
856 | auto lastRangeRequested = SqpRange{INVALID_RANGE}; |
|
949 | varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest; | |
857 | auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId); |
|
950 | varHandler->m_PendingVarRequest = VariableRequest{}; | |
858 | if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) { |
|
951 | executeVarRequest(var, varHandler->m_RunningVarRequest); | |
859 | auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second; |
|
952 | } | |
860 | auto varRequestId = varRequestIdQueue.back(); |
|
953 | else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) { | |
861 | auto varRequestIdToVarIdVarRequestMapIt |
|
954 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |
862 | = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId); |
|
955 | varHandler->m_PendingVarRequest = VariableRequest{}; | |
863 | if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) { |
|
|||
864 | auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second; |
|
|||
865 | auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId); |
|
|||
866 | if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) { |
|
|||
867 | auto &varRequest = varIdToVarRequestMapIt->second; |
|
|||
868 | lastRangeRequested = varRequest.m_RangeRequested; |
|
|||
869 | } |
|
956 | } | |
870 | else { |
|
957 | else { | |
871 | qCDebug(LOG_VariableController()) |
|
958 | // TODO: log Impossible to cancel the variable request beacause its | |
872 | << tr("Impossible to getLastRequestedRange of a unknown variable id attached " |
|
959 | // varRequestId isn't not the canceled one | |
873 | "to a variableRequestId") |
|
|||
874 | << varRequestId << varId; |
|
|||
875 | } |
|
960 | } | |
|
961 | break; | |||
876 | } |
|
962 | } | |
877 | else { |
|
963 | default: | |
878 | qCCritical(LOG_VariableController()) |
|
964 | qCCritical(LOG_VariableController()) | |
879 | << tr("Impossible to getLastRequestedRange of a unknown variableRequestId") |
|
965 | << QObject::tr("Unknown VariableRequestHandlerState"); | |
880 | << varRequestId; |
|
|||
881 | } |
|
966 | } | |
882 | } |
|
967 | } | |
|
968 | } | |||
|
969 | qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId; | |||
|
970 | m_VarGroupIdToVarIds.erase(varRequestId); | |||
|
971 | } | |||
|
972 | ||||
|
973 | void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var, | |||
|
974 | VariableRequest &varRequest) | |||
|
975 | { | |||
|
976 | qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest"); | |||
|
977 | ||||
|
978 | auto varId = m_VariableToIdentifierMap.at(var); | |||
|
979 | ||||
|
980 | auto varCacheRange = var->cacheRange(); | |||
|
981 | auto varCacheRangeRequested = varRequest.m_CacheRangeRequested; | |||
|
982 | auto notInCacheRangeList | |||
|
983 | = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested); | |||
|
984 | auto inCacheRangeList | |||
|
985 | = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested); | |||
|
986 | ||||
|
987 | if (!notInCacheRangeList.empty()) { | |||
|
988 | ||||
|
989 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
990 | if (varProvider != nullptr) { | |||
|
991 | qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested | |||
|
992 | << varRequest.m_CacheRangeRequested; | |||
|
993 | m_VariableAcquisitionWorker->pushVariableRequest( | |||
|
994 | varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested, | |||
|
995 | varRequest.m_CacheRangeRequested, | |||
|
996 | DataProviderParameters{std::move(notInCacheRangeList), var->metadata()}, | |||
|
997 | varProvider); | |||
|
998 | } | |||
883 | else { |
|
999 | else { | |
884 |
|
|
1000 | qCCritical(LOG_VariableController()) | |
885 | << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId; |
|
1001 | << "Impossible to provide data with a null provider"; | |
886 | } |
|
1002 | } | |
887 |
|
1003 | |||
888 | return lastRangeRequested; |
|
1004 | if (!inCacheRangeList.empty()) { | |
|
1005 | emit q->updateVarDisplaying(var, inCacheRangeList.first()); | |||
|
1006 | } | |||
|
1007 | } | |||
|
1008 | else { | |||
|
1009 | acceptVariableRequest(varId, | |||
|
1010 | var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested)); | |||
|
1011 | } | |||
889 | } |
|
1012 | } |
@@ -302,7 +302,7 void TestVariable::testNbPoints_data() | |||||
302 |
|
302 | |||
303 | // Doubles cache but don't add data series (expected nb points don't change) |
|
303 | // Doubles cache but don't add data series (expected nb points don't change) | |
304 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; |
|
304 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |
305 |
operations.push_back({cacheRange, |
|
305 | operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 20}); | |
306 |
|
306 | |||
307 | // Doubles cache and data series (expected nb points change) |
|
307 | // Doubles cache and data series (expected nb points change) | |
308 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; |
|
308 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |
@@ -310,7 +310,7 void TestVariable::testNbPoints_data() | |||||
310 |
|
310 | |||
311 | // Decreases cache (expected nb points decreases as the series is purged) |
|
311 | // Decreases cache (expected nb points decreases as the series is purged) | |
312 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)}; |
|
312 | cacheRange = SqpRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)}; | |
313 |
operations.push_back({cacheRange, |
|
313 | operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 10}); | |
314 |
|
314 | |||
315 | QTest::newRow("nbPoints1") << operations; |
|
315 | QTest::newRow("nbPoints1") << operations; | |
316 | } |
|
316 | } |
@@ -37,6 +37,36 std::vector<double> values(const SqpRange &range) | |||||
37 | return result; |
|
37 | return result; | |
38 | } |
|
38 | } | |
39 |
|
39 | |||
|
40 | void validateRanges(VariableController &variableController, | |||
|
41 | const std::map<int, SqpRange> &expectedRanges) | |||
|
42 | { | |||
|
43 | for (const auto &expectedRangeEntry : expectedRanges) { | |||
|
44 | auto variableIndex = expectedRangeEntry.first; | |||
|
45 | auto expectedRange = expectedRangeEntry.second; | |||
|
46 | ||||
|
47 | // Gets the variable in the controller | |||
|
48 | auto variable = variableController.variableModel()->variable(variableIndex); | |||
|
49 | ||||
|
50 | // Compares variable's range to the expected range | |||
|
51 | QVERIFY(variable != nullptr); | |||
|
52 | auto range = variable->range(); | |||
|
53 | qInfo() << "range vs expected range" << range << expectedRange; | |||
|
54 | QCOMPARE(range, expectedRange); | |||
|
55 | ||||
|
56 | // Compares variable's data with values expected for its range | |||
|
57 | auto dataSeries = variable->dataSeries(); | |||
|
58 | QVERIFY(dataSeries != nullptr); | |||
|
59 | ||||
|
60 | auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd); | |||
|
61 | auto expectedValues = values(range); | |||
|
62 | qInfo() << std::distance(it.first, it.second) << expectedValues.size(); | |||
|
63 | QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(), | |||
|
64 | [](const auto &dataSeriesIt, const auto &expectedValue) { | |||
|
65 | return dataSeriesIt.value() == expectedValue; | |||
|
66 | })); | |||
|
67 | } | |||
|
68 | } | |||
|
69 | ||||
40 | /// Provider used for the tests |
|
70 | /// Provider used for the tests | |
41 | class TestProvider : public IDataProvider { |
|
71 | class TestProvider : public IDataProvider { | |
42 | std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); } |
|
72 | std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); } | |
@@ -97,8 +127,8 struct Create : public IOperation { | |||||
97 | * Variable move/shift operation in the controller |
|
127 | * Variable move/shift operation in the controller | |
98 | */ |
|
128 | */ | |
99 | struct Move : public IOperation { |
|
129 | struct Move : public IOperation { | |
100 | explicit Move(int index, const SqpRange &newRange, bool shift = false) |
|
130 | explicit Move(int index, const SqpRange &newRange, bool shift = false, int delayMS = 10) | |
101 | : m_Index{index}, m_NewRange{newRange}, m_Shift{shift} |
|
131 | : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}, m_DelayMs{delayMS} | |
102 | { |
|
132 | { | |
103 | } |
|
133 | } | |
104 |
|
134 | |||
@@ -106,12 +136,14 struct Move : public IOperation { | |||||
106 | { |
|
136 | { | |
107 | if (auto variable = variableController.variableModel()->variable(m_Index)) { |
|
137 | if (auto variable = variableController.variableModel()->variable(m_Index)) { | |
108 | variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift); |
|
138 | variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift); | |
|
139 | QTest::qWait(m_DelayMs); | |||
109 | } |
|
140 | } | |
110 | } |
|
141 | } | |
111 |
|
142 | |||
112 | int m_Index; ///< The index of the variable to move |
|
143 | int m_Index; ///< The index of the variable to move | |
113 | SqpRange m_NewRange; ///< The new range of the variable |
|
144 | SqpRange m_NewRange; ///< The new range of the variable | |
114 | bool m_Shift; ///< Performs a shift ( |
|
145 | bool m_Shift; ///< Performs a shift ( | |
|
146 | int m_DelayMs; ///< wait the delay after running the request ( | |||
115 | }; |
|
147 | }; | |
116 |
|
148 | |||
117 | /** |
|
149 | /** | |
@@ -166,8 +198,14 private slots: | |||||
166 | /// Input data for @sa testSync() |
|
198 | /// Input data for @sa testSync() | |
167 | void testSync_data(); |
|
199 | void testSync_data(); | |
168 |
|
200 | |||
|
201 | /// Input data for @sa testSyncOneVar() | |||
|
202 | void testSyncOneVar_data(); | |||
|
203 | ||||
169 | /// Tests synchronization between variables through several operations |
|
204 | /// Tests synchronization between variables through several operations | |
170 | void testSync(); |
|
205 | void testSync(); | |
|
206 | ||||
|
207 | /// Tests synchronization between variables through several operations | |||
|
208 | void testSyncOneVar(); | |||
171 | }; |
|
209 | }; | |
172 |
|
210 | |||
173 | namespace { |
|
211 | namespace { | |
@@ -234,6 +272,7 void testSyncCase1() | |||||
234 | iterations.push_back( |
|
272 | iterations.push_back( | |
235 | {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}}); |
|
273 | {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}}); | |
236 | }; |
|
274 | }; | |
|
275 | ||||
237 | // Pan left |
|
276 | // Pan left | |
238 | moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30})); |
|
277 | moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30})); | |
239 | // Pan right |
|
278 | // Pan right | |
@@ -241,7 +280,7 void testSyncCase1() | |||||
241 | // Zoom in |
|
280 | // Zoom in | |
242 | moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45})); |
|
281 | moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45})); | |
243 | // Zoom out |
|
282 | // Zoom out | |
244 |
moveVar0(range({1 |
|
283 | moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0})); | |
245 |
|
284 | |||
246 | QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200; |
|
285 | QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200; | |
247 | } |
|
286 | } | |
@@ -304,6 +343,64 void testSyncCase2() | |||||
304 | QTest::newRow("sync2") << syncId << initialRange << iterations << 4000; |
|
343 | QTest::newRow("sync2") << syncId << initialRange << iterations << 4000; | |
305 | // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000; |
|
344 | // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000; | |
306 | } |
|
345 | } | |
|
346 | ||||
|
347 | void testSyncOnVarCase1() | |||
|
348 | { | |||
|
349 | // Id used to synchronize variables in the controller | |||
|
350 | auto syncId = QUuid::createUuid(); | |||
|
351 | ||||
|
352 | /// Generates a range according to a start time and a end time (the date is the same) | |||
|
353 | auto range = [](const QTime &startTime, const QTime &endTime) { | |||
|
354 | return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}), | |||
|
355 | DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})}; | |||
|
356 | }; | |||
|
357 | ||||
|
358 | auto initialRange = range({12, 0}, {13, 0}); | |||
|
359 | ||||
|
360 | Iterations creations{}; | |||
|
361 | // Creates variables var0, var1 and var2 | |||
|
362 | creations.push_back({std::make_shared<Create>(0), {{0, initialRange}}}); | |||
|
363 | ||||
|
364 | Iterations synchronization{}; | |||
|
365 | // Adds variables into the sync group (ranges don't need to be tested here) | |||
|
366 | synchronization.push_back({std::make_shared<Synchronize>(0, syncId)}); | |||
|
367 | ||||
|
368 | Iterations iterations{}; | |||
|
369 | ||||
|
370 | // Moves var0 through several operations | |||
|
371 | auto moveOp = [&iterations](const auto &requestedRange, const auto &expectedRange, auto delay) { | |||
|
372 | iterations.push_back( | |||
|
373 | {std::make_shared<Move>(0, requestedRange, true, delay), {{0, expectedRange}}}); | |||
|
374 | }; | |||
|
375 | ||||
|
376 | // we assume here 300 ms is enough to finsh a operation | |||
|
377 | int delayToFinish = 300; | |||
|
378 | // jump to right, let's the operation time to finish | |||
|
379 | moveOp(range({14, 30}, {15, 30}), range({14, 30}, {15, 30}), delayToFinish); | |||
|
380 | // pan to right, let's the operation time to finish | |||
|
381 | moveOp(range({14, 45}, {15, 45}), range({14, 45}, {15, 45}), delayToFinish); | |||
|
382 | // jump to left, let's the operation time to finish | |||
|
383 | moveOp(range({03, 30}, {04, 30}), range({03, 30}, {04, 30}), delayToFinish); | |||
|
384 | // Pan to left, let's the operation time to finish | |||
|
385 | moveOp(range({03, 10}, {04, 10}), range({03, 10}, {04, 10}), delayToFinish); | |||
|
386 | // Zoom in, let's the operation time to finish | |||
|
387 | moveOp(range({03, 30}, {04, 00}), range({03, 30}, {04, 00}), delayToFinish); | |||
|
388 | // Zoom out left, let's the operation time to finish | |||
|
389 | moveOp(range({01, 10}, {18, 10}), range({01, 10}, {18, 10}), delayToFinish); | |||
|
390 | // Go back to initial range | |||
|
391 | moveOp(initialRange, initialRange, delayToFinish); | |||
|
392 | ||||
|
393 | ||||
|
394 | // jump to right, let's the operation time to finish | |||
|
395 | // moveOp(range({14, 30}, {15, 30}), initialRange, delayToFinish); | |||
|
396 | // Zoom out left, let's the operation time to finish | |||
|
397 | moveOp(range({01, 10}, {18, 10}), initialRange, delayToFinish); | |||
|
398 | // Go back to initial range | |||
|
399 | moveOp(initialRange, initialRange, 300); | |||
|
400 | ||||
|
401 | QTest::newRow("syncOnVarCase1") << syncId << initialRange << std::move(creations) | |||
|
402 | << std::move(iterations); | |||
|
403 | } | |||
307 | } |
|
404 | } | |
308 |
|
405 | |||
309 | void TestVariableSync::testSync_data() |
|
406 | void TestVariableSync::testSync_data() | |
@@ -325,6 +422,24 void TestVariableSync::testSync_data() | |||||
325 | testSyncCase2(); |
|
422 | testSyncCase2(); | |
326 | } |
|
423 | } | |
327 |
|
424 | |||
|
425 | void TestVariableSync::testSyncOneVar_data() | |||
|
426 | { | |||
|
427 | // ////////////// // | |||
|
428 | // Test structure // | |||
|
429 | // ////////////// // | |||
|
430 | ||||
|
431 | QTest::addColumn<QUuid>("syncId"); | |||
|
432 | QTest::addColumn<SqpRange>("initialRange"); | |||
|
433 | QTest::addColumn<Iterations>("creations"); | |||
|
434 | QTest::addColumn<Iterations>("iterations"); | |||
|
435 | ||||
|
436 | // ////////// // | |||
|
437 | // Test cases // | |||
|
438 | // ////////// // | |||
|
439 | ||||
|
440 | testSyncOnVarCase1(); | |||
|
441 | } | |||
|
442 | ||||
328 | void TestVariableSync::testSync() |
|
443 | void TestVariableSync::testSync() | |
329 | { |
|
444 | { | |
330 | // Inits controllers |
|
445 | // Inits controllers | |
@@ -339,50 +454,51 void TestVariableSync::testSync() | |||||
339 | // Synchronization group used |
|
454 | // Synchronization group used | |
340 | variableController.onAddSynchronizationGroupId(syncId); |
|
455 | variableController.onAddSynchronizationGroupId(syncId); | |
341 |
|
456 | |||
342 | auto validateRanges = [&variableController](const auto &expectedRanges) { |
|
457 | // For each iteration: | |
343 | for (const auto &expectedRangeEntry : expectedRanges) { |
|
458 | // - execute operation | |
344 | auto variableIndex = expectedRangeEntry.first; |
|
459 | // - compare the variables' state to the expected states | |
345 | auto expectedRange = expectedRangeEntry.second; |
|
460 | QFETCH(Iterations, iterations); | |
|
461 | QFETCH(int, operationDelay); | |||
|
462 | for (const auto &iteration : iterations) { | |||
|
463 | iteration.m_Operation->exec(variableController); | |||
|
464 | QTest::qWait(operationDelay); | |||
346 |
|
465 | |||
347 | // Gets the variable in the controller |
|
466 | validateRanges(variableController, iteration.m_ExpectedRanges); | |
348 | auto variable = variableController.variableModel()->variable(variableIndex); |
|
467 | } | |
|
468 | } | |||
349 |
|
469 | |||
350 | // Compares variable's range to the expected range |
|
470 | void TestVariableSync::testSyncOneVar() | |
351 | QVERIFY(variable != nullptr); |
|
471 | { | |
352 | auto range = variable->range(); |
|
472 | // Inits controllers | |
353 | QCOMPARE(range, expectedRange); |
|
473 | TimeController timeController{}; | |
|
474 | VariableController variableController{}; | |||
|
475 | variableController.setTimeController(&timeController); | |||
354 |
|
476 | |||
355 | // Compares variable's data with values expected for its range |
|
477 | QFETCH(QUuid, syncId); | |
356 | auto dataSeries = variable->dataSeries(); |
|
478 | QFETCH(SqpRange, initialRange); | |
357 | QVERIFY(dataSeries != nullptr); |
|
479 | timeController.onTimeToUpdate(initialRange); | |
358 |
|
480 | |||
359 | auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd); |
|
481 | // Synchronization group used | |
360 | auto expectedValues = values(range); |
|
482 | variableController.onAddSynchronizationGroupId(syncId); | |
361 | qInfo() << std::distance(it.first, it.second) << expectedValues.size(); |
|
|||
362 | QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(), |
|
|||
363 | [](const auto &dataSeriesIt, const auto &expectedValue) { |
|
|||
364 | return dataSeriesIt.value() == expectedValue; |
|
|||
365 | })); |
|
|||
366 | } |
|
|||
367 | }; |
|
|||
368 |
|
483 | |||
369 | // For each iteration: |
|
484 | // For each iteration: | |
370 | // - execute operation |
|
485 | // - execute operation | |
371 | // - compare the variables' state to the expected states |
|
486 | // - compare the variables' state to the expected states | |
372 | QFETCH(Iterations, iterations); |
|
487 | QFETCH(Iterations, iterations); | |
373 |
QFETCH( |
|
488 | QFETCH(Iterations, creations); | |
374 | for (const auto &iteration : iterations) { |
|
|||
375 | iteration.m_Operation->exec(variableController); |
|
|||
376 | QTest::qWait(operationDelay); |
|
|||
377 |
|
489 | |||
378 | validateRanges(iteration.m_ExpectedRanges); |
|
490 | for (const auto &creation : creations) { | |
|
491 | creation.m_Operation->exec(variableController); | |||
|
492 | QTest::qWait(300); | |||
379 | } |
|
493 | } | |
380 |
|
494 | |||
381 | for (const auto &iteration : iterations) { |
|
495 | for (const auto &iteration : iterations) { | |
382 | iteration.m_Operation->exec(variableController); |
|
496 | iteration.m_Operation->exec(variableController); | |
383 | } |
|
497 | } | |
384 | QTest::qWait(operationDelay); |
|
498 | ||
385 | validateRanges(iterations.back().m_ExpectedRanges); |
|
499 | if (!iterations.empty()) { | |
|
500 | validateRanges(variableController, iterations.back().m_ExpectedRanges); | |||
|
501 | } | |||
386 | } |
|
502 | } | |
387 |
|
503 | |||
388 | QTEST_MAIN(TestVariableSync) |
|
504 | QTEST_MAIN(TestVariableSync) |
@@ -203,8 +203,6 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVa | |||||
203 | emit dataProvidedFailed(dataId); |
|
203 | emit dataProvidedFailed(dataId); | |
204 | } |
|
204 | } | |
205 | } |
|
205 | } | |
206 | qCDebug(LOG_AmdaProvider()) << tr("acquisition requests erase because of finishing") |
|
|||
207 | << dataId; |
|
|||
208 | m_AcqIdToRequestProgressMap.erase(dataId); |
|
206 | m_AcqIdToRequestProgressMap.erase(dataId); | |
209 | } |
|
207 | } | |
210 | else { |
|
208 | else { | |
@@ -237,8 +235,6 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVa | |||||
237 | } |
|
235 | } | |
238 | } |
|
236 | } | |
239 | else { |
|
237 | else { | |
240 | qCDebug(LOG_AmdaProvider()) |
|
|||
241 | << tr("acquisition requests erase because of aborting") << dataId; |
|
|||
242 | qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR"); |
|
238 | qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR"); | |
243 | m_AcqIdToRequestProgressMap.erase(dataId); |
|
239 | m_AcqIdToRequestProgressMap.erase(dataId); | |
244 | emit dataProvidedFailed(dataId); |
|
240 | emit dataProvidedFailed(dataId); | |
@@ -259,6 +255,7 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVa | |||||
259 | void AmdaProvider::updateRequestProgress(QUuid acqIdentifier, |
|
255 | void AmdaProvider::updateRequestProgress(QUuid acqIdentifier, | |
260 | std::shared_ptr<QNetworkRequest> request, double progress) |
|
256 | std::shared_ptr<QNetworkRequest> request, double progress) | |
261 | { |
|
257 | { | |
|
258 | qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get(); | |||
262 | auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier); |
|
259 | auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier); | |
263 | if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) { |
|
260 | if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) { | |
264 | auto &requestProgressMap = acqIdToRequestProgressMapIt->second; |
|
261 | auto &requestProgressMap = acqIdToRequestProgressMapIt->second; |
@@ -211,6 +211,9 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath, | |||||
211 | // Reads x-axis unit |
|
211 | // Reads x-axis unit | |
212 | stream.seek(0); // returns to the beginning of the file |
|
212 | stream.seek(0); // returns to the beginning of the file | |
213 | auto xAxisUnit = readXAxisUnit(stream); |
|
213 | auto xAxisUnit = readXAxisUnit(stream); | |
|
214 | if (xAxisUnit.m_Name.isEmpty()) { | |||
|
215 | return nullptr; | |||
|
216 | } | |||
214 |
|
217 | |||
215 | // Reads results |
|
218 | // Reads results | |
216 | // AMDA V2: remove line |
|
219 | // AMDA V2: remove line |
@@ -21,7 +21,7 | |||||
21 | // Frame : GSE - Mission : ACE - |
|
21 | // Frame : GSE - Mission : ACE - | |
22 | // Instrument : MFI - Dataset : mfi_final-prelim |
|
22 | // Instrument : MFI - Dataset : mfi_final-prelim | |
23 | // REFERENCE DOWNLOAD FILE = |
|
23 | // REFERENCE DOWNLOAD FILE = | |
24 | // http://amda.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00¶meterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0 |
|
24 | // http://amdatest.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00¶meterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0 | |
25 |
|
25 | |||
26 | namespace { |
|
26 | namespace { | |
27 |
|
27 | |||
@@ -29,7 +29,8 namespace { | |||||
29 | const auto TESTS_RESOURCES_PATH |
|
29 | const auto TESTS_RESOURCES_PATH | |
30 | = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath(); |
|
30 | = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath(); | |
31 |
|
31 | |||
32 | const auto TESTS_AMDA_REF_FILE = QString{"AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"}; |
|
32 | /// Delay after each operation on the variable before validating it (in ms) | |
|
33 | const auto OPERATION_DELAY = 10000; | |||
33 |
|
34 | |||
34 | template <typename T> |
|
35 | template <typename T> | |
35 | bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange, |
|
36 | bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange, | |
@@ -49,15 +50,6 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidat | |||||
49 | qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend()) |
|
50 | qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend()) | |
50 | << std::distance(itRefs.first, itRefs.second); |
|
51 | << std::distance(itRefs.first, itRefs.second); | |
51 |
|
52 | |||
52 | // auto xcValue = candidateDS->valuesData()->data(); |
|
|||
53 | // auto dist = std::distance(itRefs.first, itRefs.second); |
|
|||
54 | // auto it = itRefs.first; |
|
|||
55 | // for (auto i = 0; i < dist - 1; ++i) { |
|
|||
56 | // ++it; |
|
|||
57 | // qInfo() << "END:" << it->value(); |
|
|||
58 | // } |
|
|||
59 | // qDebug() << "END:" << it->value() << xcValue.last(); |
|
|||
60 |
|
||||
61 | return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second, |
|
53 | return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second, | |
62 | compareLambda); |
|
54 | compareLambda); | |
63 | } |
|
55 | } | |
@@ -71,115 +63,91 class TestAmdaAcquisition : public QObject { | |||||
71 | Q_OBJECT |
|
63 | Q_OBJECT | |
72 |
|
64 | |||
73 | private slots: |
|
65 | private slots: | |
|
66 | /// Input data for @sa testAcquisition() | |||
|
67 | void testAcquisition_data(); | |||
74 | void testAcquisition(); |
|
68 | void testAcquisition(); | |
75 | }; |
|
69 | }; | |
76 |
|
70 | |||
77 | void TestAmdaAcquisition::testAcquisition() |
|
71 | void TestAmdaAcquisition::testAcquisition_data() | |
78 | { |
|
72 | { | |
79 | /// @todo: update test to be compatible with AMDA v2 |
|
73 | // ////////////// // | |
80 |
|
74 | // Test structure // | ||
81 | // READ the ref file: |
|
75 | // ////////////// // | |
82 | auto filePath = QFileInfo{TESTS_RESOURCES_PATH, TESTS_AMDA_REF_FILE}.absoluteFilePath(); |
|
|||
83 | auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR); |
|
|||
84 |
|
||||
85 | auto provider = std::make_shared<AmdaProvider>(); |
|
|||
86 | auto timeController = std::make_unique<TimeController>(); |
|
|||
87 |
|
||||
88 | auto varRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 3, 0, 0}}; |
|
|||
89 | auto varRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}}; |
|
|||
90 |
|
||||
91 | auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)}; |
|
|||
92 |
|
||||
93 | timeController->onTimeToUpdate(sqpR); |
|
|||
94 |
|
||||
95 | QVariantHash metaData; |
|
|||
96 | metaData.insert("dataType", "scalar"); |
|
|||
97 | metaData.insert("xml:id", "imf(0)"); |
|
|||
98 |
|
||||
99 | VariableController vc; |
|
|||
100 | vc.setTimeController(timeController.get()); |
|
|||
101 |
|
||||
102 | auto var = vc.createVariable("bx_gse", metaData, provider); |
|
|||
103 |
|
||||
104 | // 1 : Variable creation |
|
|||
105 |
|
||||
106 | qDebug() << " 1: TIMECONTROLLER" << timeController->dateTime(); |
|
|||
107 | qDebug() << " 1: RANGE " << var->range(); |
|
|||
108 | qDebug() << " 1: CACHERANGE" << var->cacheRange(); |
|
|||
109 |
|
||||
110 | // wait for 10 sec before asking next request toi permit asynchrone process to finish. |
|
|||
111 | auto timeToWaitMs = 10000; |
|
|||
112 |
|
76 | |||
113 | QEventLoop loop; |
|
77 | QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions | |
114 | QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit); |
|
78 | QTest::addColumn<SqpRange>("initialRange"); // First acquisition | |
115 | loop.exec(); |
|
79 | QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make | |
116 |
|
80 | |||
117 | // Tests on acquisition operation |
|
81 | // ////////// // | |
118 |
|
82 | // Test cases // | ||
119 | int count = 1; |
|
83 | // ////////// // | |
120 |
|
||||
121 | auto requestDataLoading = [&vc, var, timeToWaitMs, results, &count](auto tStart, auto tEnd) { |
|
|||
122 | ++count; |
|
|||
123 |
|
||||
124 | auto nextSqpR |
|
|||
125 | = SqpRange{DateUtils::secondsSinceEpoch(tStart), DateUtils::secondsSinceEpoch(tEnd)}; |
|
|||
126 | vc.onRequestDataLoading(QVector<std::shared_ptr<Variable> >{} << var, nextSqpR, true); |
|
|||
127 |
|
||||
128 | QEventLoop loop; |
|
|||
129 | QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit); |
|
|||
130 | loop.exec(); |
|
|||
131 |
|
||||
132 | qInfo() << count << "RANGE " << var->range(); |
|
|||
133 | qInfo() << count << "CACHERANGE" << var->cacheRange(); |
|
|||
134 |
|
||||
135 | QCOMPARE(var->range().m_TStart, nextSqpR.m_TStart); |
|
|||
136 | QCOMPARE(var->range().m_TEnd, nextSqpR.m_TEnd); |
|
|||
137 |
|
||||
138 | // Verify dataserie |
|
|||
139 | QVERIFY(compareDataSeries<ScalarSeries>(var->dataSeries(), var->cacheRange(), results)); |
|
|||
140 |
|
84 | |||
|
85 | auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) { | |||
|
86 | return DateUtils::secondsSinceEpoch( | |||
|
87 | QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC}); | |||
141 | }; |
|
88 | }; | |
142 |
|
89 | |||
143 | // 2 : pan (jump) left for one hour |
|
|||
144 | auto nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 1, 0, 0}}; |
|
|||
145 | auto nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 2, 0, 0}}; |
|
|||
146 | // requestDataLoading(nextVarRS, nextVarRE); |
|
|||
147 |
|
90 | |||
|
91 | QTest::newRow("amda") | |||
|
92 | << "AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt" | |||
|
93 | << SqpRange{dateTime(2012, 1, 2, 2, 3, 0), dateTime(2012, 1, 2, 2, 4, 0)} | |||
|
94 | << std::vector<SqpRange>{ | |||
|
95 | // 2 : pan (jump) left for two min | |||
|
96 | SqpRange{dateTime(2012, 1, 2, 2, 1, 0), dateTime(2012, 1, 2, 2, 2, 0)}, | |||
|
97 | // 3 : pan (jump) right for four min | |||
|
98 | SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)}, | |||
|
99 | // 4 : pan (overlay) right for 30 sec | |||
|
100 | /*SqpRange{dateTime(2012, 1, 2, 2, 5, 30), dateTime(2012, 1, 2, 2, 6, 30)}, | |||
|
101 | // 5 : pan (overlay) left for 30 sec | |||
|
102 | SqpRange{dateTime(2012, 1, 2, 2, 5, 0), dateTime(2012, 1, 2, 2, 6, 0)}, | |||
|
103 | // 6 : pan (overlay) left for 30 sec - BIS | |||
|
104 | SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}, | |||
|
105 | // 7 : Zoom in Inside 20 sec range | |||
|
106 | SqpRange{dateTime(2012, 1, 2, 2, 4, 50), dateTime(2012, 1, 2, 2, 5, 10)}, | |||
|
107 | // 8 : Zoom out Inside 20 sec range | |||
|
108 | SqpRange{dateTime(2012, 1, 2, 2, 4, 30), dateTime(2012, 1, 2, 2, 5, 30)}*/}; | |||
|
109 | } | |||
148 |
|
110 | |||
149 | // 3 : pan (jump) right for one hour |
|
111 | void TestAmdaAcquisition::testAcquisition() | |
150 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}}; |
|
112 | { | |
151 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}}; |
|
113 | /// @todo: update test to be compatible with AMDA v2 | |
152 | // requestDataLoading(nextVarRS, nextVarRE); |
|
|||
153 |
|
114 | |||
154 | // 4 : pan (overlay) right for 30 min |
|
115 | // Retrieves data file | |
155 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}}; |
|
116 | QFETCH(QString, dataFilename); | |
156 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 30, 0}}; |
|
117 | auto filePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath(); | |
157 | // requestDataLoading(nextVarRS, nextVarRE); |
|
118 | auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR); | |
158 |
|
119 | |||
159 | // 5 : pan (overlay) left for 30 min |
|
120 | /// Lambda used to validate a variable at each step | |
160 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}}; |
|
121 | auto validateVariable = [results](std::shared_ptr<Variable> variable, const SqpRange &range) { | |
161 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}}; |
|
122 | // Checks that the variable's range has changed | |
162 | // requestDataLoading(nextVarRS, nextVarRE); |
|
123 | qInfo() << tr("Compare var range vs range") << variable->range() << range; | |
|
124 | QCOMPARE(variable->range(), range); | |||
163 |
|
125 | |||
164 | // 6 : pan (overlay) left for 30 min - BIS |
|
126 | // Checks the variable's data series | |
165 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 30, 0}}; |
|
127 | QVERIFY(compareDataSeries<ScalarSeries>(variable->dataSeries(), variable->cacheRange(), | |
166 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}}; |
|
128 | results)); | |
167 | // requestDataLoading(nextVarRS, nextVarRE); |
|
129 | qInfo() << "\n"; | |
|
130 | }; | |||
168 |
|
131 | |||
169 | // 7 : Zoom in Inside 20 min range |
|
132 | // Creates variable | |
170 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 50, 0}}; |
|
133 | QFETCH(SqpRange, initialRange); | |
171 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 10, 0}}; |
|
134 | sqpApp->timeController().onTimeToUpdate(initialRange); | |
172 | // requestDataLoading(nextVarRS, nextVarRE); |
|
135 | auto provider = std::make_shared<AmdaProvider>(); | |
|
136 | auto variable = sqpApp->variableController().createVariable( | |||
|
137 | "bx_gse", {{"dataType", "scalar"}, {"xml:id", "imf(0)"}}, provider); | |||
173 |
|
138 | |||
174 | // 8 : Zoom out Inside 2 hours range |
|
139 | QTest::qWait(OPERATION_DELAY); | |
175 | nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}}; |
|
140 | validateVariable(variable, initialRange); | |
176 | nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}}; |
|
|||
177 | // requestDataLoading(nextVarRS, nextVarRE); |
|
|||
178 |
|
141 | |||
|
142 | // Makes operations on the variable | |||
|
143 | QFETCH(std::vector<SqpRange>, operations); | |||
|
144 | for (const auto &operation : operations) { | |||
|
145 | // Asks request on the variable and waits during its execution | |||
|
146 | sqpApp->variableController().onRequestDataLoading({variable}, operation, false); | |||
179 |
|
147 | |||
180 | // Close the app after 10 sec |
|
148 | QTest::qWait(OPERATION_DELAY); | |
181 | QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit); |
|
149 | validateVariable(variable, operation); | |
182 | loop.exec(); |
|
150 | } | |
183 | } |
|
151 | } | |
184 |
|
152 | |||
185 | int main(int argc, char *argv[]) |
|
153 | int main(int argc, char *argv[]) |
@@ -55,7 +55,12 struct ExpectedResults { | |||||
55 | { |
|
55 | { | |
56 | if (m_ParsingOK) { |
|
56 | if (m_ParsingOK) { | |
57 | auto dataSeries = dynamic_cast<T *>(results.get()); |
|
57 | auto dataSeries = dynamic_cast<T *>(results.get()); | |
58 |
|
|
58 | if (dataSeries == nullptr) { | |
|
59 | ||||
|
60 | // No unit detected, parsink ok but data is nullptr | |||
|
61 | // TODO, improve the test to verify that the data is null | |||
|
62 | return; | |||
|
63 | } | |||
59 |
|
64 | |||
60 | // Checks units |
|
65 | // Checks units | |
61 | QVERIFY(dataSeries->xAxisUnit() == m_XAxisUnit); |
|
66 | QVERIFY(dataSeries->xAxisUnit() == m_XAxisUnit); |
@@ -144,6 +144,7 void TestCosinusAcquisition::testAcquisition() | |||||
144 | auto validateVariable |
|
144 | auto validateVariable | |
145 | = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) { |
|
145 | = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) { | |
146 | // Checks that the variable's range has changed |
|
146 | // Checks that the variable's range has changed | |
|
147 | qInfo() << "range vs expected range" << variable->range() << range; | |||
147 | QCOMPARE(variable->range(), range); |
|
148 | QCOMPARE(variable->range(), range); | |
148 |
|
149 | |||
149 | // Checks the variable's data series |
|
150 | // Checks the variable's data series | |
@@ -157,15 +158,17 void TestCosinusAcquisition::testAcquisition() | |||||
157 | auto variable = sqpApp->variableController().createVariable( |
|
158 | auto variable = sqpApp->variableController().createVariable( | |
158 | "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider); |
|
159 | "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider); | |
159 |
|
160 | |||
|
161 | ||||
160 | QFETCH(int, operationDelay); |
|
162 | QFETCH(int, operationDelay); | |
161 | QTest::qWait(operationDelay); |
|
163 | QTest::qWait(operationDelay); | |
162 | validateVariable(variable, initialRange); |
|
164 | validateVariable(variable, initialRange); | |
163 |
|
165 | |||
|
166 | QTest::qWait(operationDelay); | |||
164 | // Makes operations on the variable |
|
167 | // Makes operations on the variable | |
165 | QFETCH(std::vector<SqpRange>, operations); |
|
168 | QFETCH(std::vector<SqpRange>, operations); | |
166 | for (const auto &operation : operations) { |
|
169 | for (const auto &operation : operations) { | |
167 | // Asks request on the variable and waits during its execution |
|
170 | // Asks request on the variable and waits during its execution | |
168 |
sqpApp->variableController().onRequestDataLoading({variable}, operation, |
|
171 | sqpApp->variableController().onRequestDataLoading({variable}, operation, false); | |
169 |
|
172 | |||
170 | QTest::qWait(operationDelay); |
|
173 | QTest::qWait(operationDelay); | |
171 | validateVariable(variable, operation); |
|
174 | validateVariable(variable, operation); | |
@@ -174,7 +177,7 void TestCosinusAcquisition::testAcquisition() | |||||
174 |
|
177 | |||
175 | for (const auto &operation : operations) { |
|
178 | for (const auto &operation : operations) { | |
176 | // Asks request on the variable and waits during its execution |
|
179 | // Asks request on the variable and waits during its execution | |
177 |
sqpApp->variableController().onRequestDataLoading({variable}, operation, |
|
180 | sqpApp->variableController().onRequestDataLoading({variable}, operation, false); | |
178 | } |
|
181 | } | |
179 | QTest::qWait(operationDelay); |
|
182 | QTest::qWait(operationDelay); | |
180 | validateVariable(variable, operations.back()); |
|
183 | validateVariable(variable, operations.back()); |
General Comments 0
You need to be logged in to leave comments.
Login now