##// END OF EJS Templates
Generates and registers clone provider
Alexandre Leroux -
r712:951cc05bf337
parent child
Show More
@@ -1,76 +1,77
1 1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 2 #define SCIQLOP_IDATAPROVIDER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <memory>
7 7
8 8 #include <QObject>
9 9 #include <QUuid>
10 10
11 11 #include <Common/MetaTypes.h>
12 12
13 13 #include <Data/SqpRange.h>
14 14
15 15 #include <functional>
16 16
17 17 class DataProviderParameters;
18 18 class IDataSeries;
19 19 class QNetworkReply;
20 20 class QNetworkRequest;
21 21
22 22 /**
23 23 * @brief The IDataProvider interface aims to declare a data provider.
24 24 *
25 25 * A data provider is an entity that generates data and returns it according to various parameters
26 26 * (time interval, product to retrieve the data, etc.)
27 27 *
28 28 * @sa IDataSeries
29 29 */
30 30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
31 31
32 32 Q_OBJECT
33 33 public:
34 34 virtual ~IDataProvider() noexcept = default;
35 virtual std::shared_ptr<IDataProvider> clone() const = 0;
35 36
36 37 /**
37 38 * @brief requestDataLoading provide datas for the data identified by acqIdentifier and
38 39 * parameters
39 40 */
40 41 virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
41 42 = 0;
42 43
43 44 /**
44 45 * @brief requestDataAborting stop data loading of the data identified by acqIdentifier
45 46 */
46 47 virtual void requestDataAborting(QUuid acqIdentifier) = 0;
47 48
48 49 signals:
49 50 /**
50 51 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
51 52 * identified by acqIdentifier
52 53 */
53 54 void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired,
54 55 const SqpRange &dataRangeAcquired);
55 56
56 57 /**
57 58 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
58 59 * identified by identifier
59 60 */
60 61 void dataProvidedProgress(QUuid acqIdentifier, double progress);
61 62
62 63
63 64 /**
64 65 * @brief requestConstructed send a request for the data identified by acqIdentifier
65 66 * @callback is the methode call by the reply of the request when it is finished.
66 67 */
67 68 void requestConstructed(const QNetworkRequest &request, QUuid acqIdentifier,
68 69 std::function<void(QNetworkReply *, QUuid)> callback);
69 70 };
70 71
71 72 // Required for using shared_ptr in signals/slots
72 73 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
73 74 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
74 75 std::function<void(QNetworkReply *, QUuid)>)
75 76
76 77 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,766 +1,775
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 3 #include <Variable/VariableCacheStrategy.h>
4 4 #include <Variable/VariableController.h>
5 5 #include <Variable/VariableModel.h>
6 6 #include <Variable/VariableSynchronizationGroup.h>
7 7
8 8 #include <Data/DataProviderParameters.h>
9 9 #include <Data/IDataProvider.h>
10 10 #include <Data/IDataSeries.h>
11 11 #include <Data/VariableRequest.h>
12 12 #include <Time/TimeController.h>
13 13
14 14 #include <QMutex>
15 15 #include <QThread>
16 16 #include <QUuid>
17 17 #include <QtCore/QItemSelectionModel>
18 18
19 19 #include <deque>
20 20 #include <set>
21 21 #include <unordered_map>
22 22
23 23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 24
25 25 namespace {
26 26
27 27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 28 const SqpRange &oldGraphRange)
29 29 {
30 30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 31
32 32 auto varRangeRequested = varRange;
33 33 switch (zoomType) {
34 34 case AcquisitionZoomType::ZoomIn: {
35 35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 37 varRangeRequested.m_TStart += deltaLeft;
38 38 varRangeRequested.m_TEnd -= deltaRight;
39 39 break;
40 40 }
41 41
42 42 case AcquisitionZoomType::ZoomOut: {
43 43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 45 varRangeRequested.m_TStart -= deltaLeft;
46 46 varRangeRequested.m_TEnd += deltaRight;
47 47 break;
48 48 }
49 49 case AcquisitionZoomType::PanRight: {
50 50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 51 varRangeRequested.m_TStart += deltaRight;
52 52 varRangeRequested.m_TEnd += deltaRight;
53 53 break;
54 54 }
55 55 case AcquisitionZoomType::PanLeft: {
56 56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 57 varRangeRequested.m_TStart -= deltaLeft;
58 58 varRangeRequested.m_TEnd -= deltaLeft;
59 59 break;
60 60 }
61 61 case AcquisitionZoomType::Unknown: {
62 62 qCCritical(LOG_VariableController())
63 63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 64 break;
65 65 }
66 66 default:
67 67 qCCritical(LOG_VariableController()) << VariableController::tr(
68 68 "Impossible to synchronize: zoom type not take into account");
69 69 // No action
70 70 break;
71 71 }
72 72
73 73 return varRangeRequested;
74 74 }
75 75 }
76 76
77 77 struct VariableController::VariableControllerPrivate {
78 78 explicit VariableControllerPrivate(VariableController *parent)
79 79 : m_WorkingMutex{},
80 80 m_VariableModel{new VariableModel{parent}},
81 81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
84 84 q{parent}
85 85 {
86 86
87 87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
88 88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
89 89 }
90 90
91 91
92 92 virtual ~VariableControllerPrivate()
93 93 {
94 94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
95 95 m_VariableAcquisitionWorkerThread.quit();
96 96 m_VariableAcquisitionWorkerThread.wait();
97 97 }
98 98
99 99
100 100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
101 101 QUuid varRequestId);
102 102
103 103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
104 104 const SqpRange &dateTime);
105 105
106 106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
107 107 std::shared_ptr<IDataSeries>
108 108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
109 109
110 110 void registerProvider(std::shared_ptr<IDataProvider> provider);
111 111
112 112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
113 113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
114 114 void updateVariableRequest(QUuid varRequestId);
115 115 void cancelVariableRequest(QUuid varRequestId);
116 116
117 117 QMutex m_WorkingMutex;
118 118 /// Variable model. The VariableController has the ownership
119 119 VariableModel *m_VariableModel;
120 120 QItemSelectionModel *m_VariableSelectionModel;
121 121
122 122
123 123 TimeController *m_TimeController{nullptr};
124 124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
125 125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
126 126 QThread m_VariableAcquisitionWorkerThread;
127 127
128 128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
129 129 m_VariableToProviderMap;
130 130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
131 131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
132 132 m_GroupIdToVariableSynchronizationGroupMap;
133 133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
134 134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
135 135
136 136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
137 137
138 138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
139 139
140 140
141 141 VariableController *q;
142 142 };
143 143
144 144
145 145 VariableController::VariableController(QObject *parent)
146 146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
147 147 {
148 148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
149 149 << QThread::currentThread();
150 150
151 151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
152 152 &VariableController::onAbortProgressRequested);
153 153
154 154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
155 155 &VariableController::onDataProvided);
156 156 connect(impl->m_VariableAcquisitionWorker.get(),
157 157 &VariableAcquisitionWorker::variableRequestInProgress, this,
158 158 &VariableController::onVariableRetrieveDataInProgress);
159 159
160 160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
161 161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
162 162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
163 163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
164 164
165 165
166 166 impl->m_VariableAcquisitionWorkerThread.start();
167 167 }
168 168
169 169 VariableController::~VariableController()
170 170 {
171 171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
172 172 << QThread::currentThread();
173 173 this->waitForFinish();
174 174 }
175 175
176 176 VariableModel *VariableController::variableModel() noexcept
177 177 {
178 178 return impl->m_VariableModel;
179 179 }
180 180
181 181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
182 182 {
183 183 return impl->m_VariableSelectionModel;
184 184 }
185 185
186 186 void VariableController::setTimeController(TimeController *timeController) noexcept
187 187 {
188 188 impl->m_TimeController = timeController;
189 189 }
190 190
191 191 std::shared_ptr<Variable>
192 192 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
193 193 {
194 194 if (impl->m_VariableModel->containsVariable(variable)) {
195 195 // Clones variable
196 196 auto duplicate = variable->clone();
197 197
198 198 // Adds clone to model
199 199 impl->m_VariableModel->addVariable(duplicate);
200 200
201 201 // Generates clone identifier
202 202 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
203 203
204 // Registers provider
205 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
206 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
207
208 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
209 if (duplicateProvider) {
210 impl->registerProvider(duplicateProvider);
211 }
212
204 213 return duplicate;
205 214 }
206 215 else {
207 216 qCCritical(LOG_VariableController())
208 217 << tr("Can't create duplicate of variable %1: variable not registered in the model")
209 218 .arg(variable->name());
210 219 return nullptr;
211 220 }
212 221 }
213 222
214 223 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
215 224 {
216 225 if (!variable) {
217 226 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
218 227 return;
219 228 }
220 229
221 230 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
222 231 // make some treatments before the deletion
223 232 emit variableAboutToBeDeleted(variable);
224 233
225 234 // Deletes identifier
226 235 impl->m_VariableToIdentifierMap.erase(variable);
227 236
228 237 // Deletes provider
229 238 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
230 239 qCDebug(LOG_VariableController())
231 240 << tr("Number of providers deleted for variable %1: %2")
232 241 .arg(variable->name(), QString::number(nbProvidersDeleted));
233 242
234 243
235 244 // Deletes from model
236 245 impl->m_VariableModel->deleteVariable(variable);
237 246 }
238 247
239 248 void VariableController::deleteVariables(
240 249 const QVector<std::shared_ptr<Variable> > &variables) noexcept
241 250 {
242 251 for (auto variable : qAsConst(variables)) {
243 252 deleteVariable(variable);
244 253 }
245 254 }
246 255
247 256 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
248 257 {
249 258 }
250 259
251 260 std::shared_ptr<Variable>
252 261 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
253 262 std::shared_ptr<IDataProvider> provider) noexcept
254 263 {
255 264 if (!impl->m_TimeController) {
256 265 qCCritical(LOG_VariableController())
257 266 << tr("Impossible to create variable: The time controller is null");
258 267 return nullptr;
259 268 }
260 269
261 270 auto range = impl->m_TimeController->dateTime();
262 271
263 272 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
264 273 auto identifier = QUuid::createUuid();
265 274
266 275 // store the provider
267 276 impl->registerProvider(provider);
268 277
269 278 // Associate the provider
270 279 impl->m_VariableToProviderMap[newVariable] = provider;
271 280 impl->m_VariableToIdentifierMap[newVariable] = identifier;
272 281
273 282
274 283 auto varRequestId = QUuid::createUuid();
275 284 qCInfo(LOG_VariableController()) << "processRequest for" << name << varRequestId;
276 285 impl->processRequest(newVariable, range, varRequestId);
277 286 impl->updateVariableRequest(varRequestId);
278 287
279 288 return newVariable;
280 289 }
281 290 }
282 291
283 292 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
284 293 {
285 294 // TODO check synchronisation and Rescale
286 295 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
287 296 << QThread::currentThread()->objectName();
288 297 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
289 298 auto varRequestId = QUuid::createUuid();
290 299
291 300 for (const auto &selectedRow : qAsConst(selectedRows)) {
292 301 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
293 302 selectedVariable->setRange(dateTime);
294 303 impl->processRequest(selectedVariable, dateTime, varRequestId);
295 304
296 305 // notify that rescale operation has to be done
297 306 emit rangeChanged(selectedVariable, dateTime);
298 307 }
299 308 }
300 309 impl->updateVariableRequest(varRequestId);
301 310 }
302 311
303 312 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
304 313 const SqpRange &cacheRangeRequested,
305 314 QVector<AcquisitionDataPacket> dataAcquired)
306 315 {
307 316 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
308 317 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
309 318 if (!varRequestId.isNull()) {
310 319 impl->updateVariableRequest(varRequestId);
311 320 }
312 321 }
313 322
314 323 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
315 324 {
316 325 if (auto var = impl->findVariable(identifier)) {
317 326 impl->m_VariableModel->setDataProgress(var, progress);
318 327 }
319 328 else {
320 329 qCCritical(LOG_VariableController())
321 330 << tr("Impossible to notify progression of a null variable");
322 331 }
323 332 }
324 333
325 334 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
326 335 {
327 336 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
328 337 << QThread::currentThread()->objectName();
329 338
330 339 auto it = impl->m_VariableToIdentifierMap.find(variable);
331 340 if (it != impl->m_VariableToIdentifierMap.cend()) {
332 341 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
333 342 }
334 343 else {
335 344 qCWarning(LOG_VariableController())
336 345 << tr("Aborting progression of inexistant variable detected !!!")
337 346 << QThread::currentThread()->objectName();
338 347 }
339 348 }
340 349
341 350 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
342 351 {
343 352 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
344 353 << QThread::currentThread()->objectName()
345 354 << synchronizationGroupId;
346 355 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
347 356 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
348 357 std::make_pair(synchronizationGroupId, vSynchroGroup));
349 358 }
350 359
351 360 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
352 361 {
353 362 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
354 363 }
355 364
356 365 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
357 366 QUuid synchronizationGroupId)
358 367
359 368 {
360 369 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
361 370 << synchronizationGroupId;
362 371 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
363 372 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
364 373 auto groupIdToVSGIt
365 374 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
366 375 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
367 376 impl->m_VariableIdGroupIdMap.insert(
368 377 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
369 378 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
370 379 }
371 380 else {
372 381 qCCritical(LOG_VariableController())
373 382 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
374 383 << variable->name();
375 384 }
376 385 }
377 386 else {
378 387 qCCritical(LOG_VariableController())
379 388 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
380 389 }
381 390 }
382 391
383 392
384 393 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
385 394 const SqpRange &range, const SqpRange &oldRange,
386 395 bool synchronise)
387 396 {
388 397 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
389 398
390 399 // we want to load data of the variable for the dateTime.
391 400 // First we check if the cache contains some of them.
392 401 // For the other, we ask the provider to give them.
393 402
394 403 auto varRequestId = QUuid::createUuid();
395 404 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
396 405 << QThread::currentThread()->objectName() << varRequestId;
397 406
398 407 for (const auto &var : variables) {
399 408 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
400 409 impl->processRequest(var, range, varRequestId);
401 410 }
402 411
403 412 if (synchronise) {
404 413 // Get the group ids
405 414 qCDebug(LOG_VariableController())
406 415 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
407 416 auto groupIds = std::set<QUuid>{};
408 417 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
409 418 for (const auto &var : variables) {
410 419 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
411 420 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
412 421 auto vId = varToVarIdIt->second;
413 422 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
414 423 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
415 424 auto gId = varIdToGroupIdIt->second;
416 425 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
417 426 if (groupIds.find(gId) == groupIds.cend()) {
418 427 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
419 428 groupIds.insert(gId);
420 429 }
421 430 }
422 431 }
423 432 }
424 433
425 434 // We assume here all group ids exist
426 435 for (const auto &gId : groupIds) {
427 436 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
428 437 auto vSyncIds = vSynchronizationGroup->getIds();
429 438 qCDebug(LOG_VariableController()) << "Var in synchro group ";
430 439 for (auto vId : vSyncIds) {
431 440 auto var = impl->findVariable(vId);
432 441
433 442 // Don't process already processed var
434 443 if (!variables.contains(var)) {
435 444 if (var != nullptr) {
436 445 qCDebug(LOG_VariableController()) << "processRequest synchro for"
437 446 << var->name();
438 447 auto vSyncRangeRequested = computeSynchroRangeRequested(
439 448 var->range(), range, groupIdToOldRangeMap.at(gId));
440 449 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
441 450 impl->processRequest(var, vSyncRangeRequested, varRequestId);
442 451 }
443 452 else {
444 453 qCCritical(LOG_VariableController())
445 454
446 455 << tr("Impossible to synchronize a null variable");
447 456 }
448 457 }
449 458 }
450 459 }
451 460 }
452 461
453 462 impl->updateVariableRequest(varRequestId);
454 463 }
455 464
456 465
457 466 void VariableController::initialize()
458 467 {
459 468 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
460 469 impl->m_WorkingMutex.lock();
461 470 qCDebug(LOG_VariableController()) << tr("VariableController init END");
462 471 }
463 472
464 473 void VariableController::finalize()
465 474 {
466 475 impl->m_WorkingMutex.unlock();
467 476 }
468 477
469 478 void VariableController::waitForFinish()
470 479 {
471 480 QMutexLocker locker{&impl->m_WorkingMutex};
472 481 }
473 482
474 483 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
475 484 {
476 485 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
477 486 auto zoomType = AcquisitionZoomType::Unknown;
478 487 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
479 488 zoomType = AcquisitionZoomType::ZoomOut;
480 489 }
481 490 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
482 491 zoomType = AcquisitionZoomType::PanRight;
483 492 }
484 493 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
485 494 zoomType = AcquisitionZoomType::PanLeft;
486 495 }
487 496 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
488 497 zoomType = AcquisitionZoomType::ZoomIn;
489 498 }
490 499 else {
491 500 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
492 501 }
493 502 return zoomType;
494 503 }
495 504
496 505 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
497 506 const SqpRange &rangeRequested,
498 507 QUuid varRequestId)
499 508 {
500 509
501 510 // TODO: protect at
502 511 auto varRequest = VariableRequest{};
503 512 auto varId = m_VariableToIdentifierMap.at(var);
504 513
505 514 auto varStrategyRangesRequested
506 515 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
507 516 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
508 517 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
509 518
510 519 if (!notInCacheRangeList.empty()) {
511 520 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
512 521 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
513 522 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest RR ") << rangeRequested;
514 523 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest R ")
515 524 << varStrategyRangesRequested.first;
516 525 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest CR ")
517 526 << varStrategyRangesRequested.second;
518 527 // store VarRequest
519 528 storeVariableRequest(varId, varRequestId, varRequest);
520 529
521 530 auto varProvider = m_VariableToProviderMap.at(var);
522 531 if (varProvider != nullptr) {
523 532 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
524 533 varRequestId, varId, varStrategyRangesRequested.first,
525 534 varStrategyRangesRequested.second,
526 535 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
527 536 varProvider);
528 537
529 538 if (!varRequestIdCanceled.isNull()) {
530 539 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
531 540 << varRequestIdCanceled;
532 541 cancelVariableRequest(varRequestIdCanceled);
533 542 }
534 543 }
535 544 else {
536 545 qCCritical(LOG_VariableController())
537 546 << "Impossible to provide data with a null provider";
538 547 }
539 548
540 549 if (!inCacheRangeList.empty()) {
541 550 emit q->updateVarDisplaying(var, inCacheRangeList.first());
542 551 }
543 552 }
544 553 else {
545 554
546 555 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
547 556 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
548 557 // store VarRequest
549 558 storeVariableRequest(varId, varRequestId, varRequest);
550 559 acceptVariableRequest(varId,
551 560 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
552 561 }
553 562 }
554 563
555 564 std::shared_ptr<Variable>
556 565 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
557 566 {
558 567 std::shared_ptr<Variable> var;
559 568 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
560 569
561 570 auto end = m_VariableToIdentifierMap.cend();
562 571 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
563 572 if (it != end) {
564 573 var = it->first;
565 574 }
566 575 else {
567 576 qCCritical(LOG_VariableController())
568 577 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
569 578 }
570 579
571 580 return var;
572 581 }
573 582
574 583 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
575 584 const QVector<AcquisitionDataPacket> acqDataPacketVector)
576 585 {
577 586 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
578 587 << acqDataPacketVector.size();
579 588 std::shared_ptr<IDataSeries> dataSeries;
580 589 if (!acqDataPacketVector.isEmpty()) {
581 590 dataSeries = acqDataPacketVector[0].m_DateSeries;
582 591 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
583 592 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
584 593 }
585 594 }
586 595 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
587 596 << acqDataPacketVector.size();
588 597 return dataSeries;
589 598 }
590 599
591 600 void VariableController::VariableControllerPrivate::registerProvider(
592 601 std::shared_ptr<IDataProvider> provider)
593 602 {
594 603 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
595 604 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
596 605 << provider->objectName();
597 606 m_ProviderSet.insert(provider);
598 607 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
599 608 &VariableAcquisitionWorker::onVariableDataAcquired);
600 609 connect(provider.get(), &IDataProvider::dataProvidedProgress,
601 610 m_VariableAcquisitionWorker.get(),
602 611 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
603 612 }
604 613 else {
605 614 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
606 615 }
607 616 }
608 617
609 618 void VariableController::VariableControllerPrivate::storeVariableRequest(
610 619 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
611 620 {
612 621 // First request for the variable. we can create an entry for it
613 622 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
614 623 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
615 624 auto varRequestIdQueue = std::deque<QUuid>{};
616 625 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
617 626 varRequestIdQueue.push_back(varRequestId);
618 627 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
619 628 }
620 629 else {
621 630 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
622 631 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
623 632 varRequestIdQueue.push_back(varRequestId);
624 633 }
625 634
626 635 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
627 636 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
628 637 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
629 638 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
630 639 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
631 640 m_VarRequestIdToVarIdVarRequestMap.insert(
632 641 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
633 642 }
634 643 else {
635 644 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
636 645 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
637 646 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
638 647 }
639 648 }
640 649
641 650 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
642 651 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
643 652 {
644 653 QUuid varRequestId;
645 654 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
646 655 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
647 656 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
648 657 varRequestId = varRequestIdQueue.front();
649 658 auto varRequestIdToVarIdVarRequestMapIt
650 659 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
651 660 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
652 661 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
653 662 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
654 663 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
655 664 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
656 665 auto &varRequest = varIdToVarRequestMapIt->second;
657 666 varRequest.m_DataSeries = dataSeries;
658 667 varRequest.m_CanUpdate = true;
659 668 }
660 669 else {
661 670 qCDebug(LOG_VariableController())
662 671 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
663 672 "to a variableRequestId")
664 673 << varRequestId << varId;
665 674 }
666 675 }
667 676 else {
668 677 qCCritical(LOG_VariableController())
669 678 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
670 679 << varRequestId;
671 680 }
672 681
673 682 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
674 683 << varRequestIdQueue.size();
675 684 varRequestIdQueue.pop_front();
676 685 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
677 686 << varRequestIdQueue.size();
678 687 if (varRequestIdQueue.empty()) {
679 688 m_VarIdToVarRequestIdQueueMap.erase(varId);
680 689 }
681 690 }
682 691 else {
683 692 qCCritical(LOG_VariableController())
684 693 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
685 694 }
686 695
687 696 return varRequestId;
688 697 }
689 698
690 699 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
691 700 {
692 701
693 702 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
694 703 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
695 704 bool processVariableUpdate = true;
696 705 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
697 706 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
698 707 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
699 708 ++varIdToVarRequestMapIt) {
700 709 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
701 710 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
702 711 << processVariableUpdate;
703 712 }
704 713
705 714 if (processVariableUpdate) {
706 715 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
707 716 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
708 717 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
709 718 auto &varRequest = varIdToVarRequestMapIt->second;
710 719 var->setRange(varRequest.m_RangeRequested);
711 720 var->setCacheRange(varRequest.m_CacheRangeRequested);
712 721 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
713 722 << varRequest.m_RangeRequested;
714 723 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
715 724 << varRequest.m_CacheRangeRequested;
716 725 var->mergeDataSeries(varRequest.m_DataSeries);
717 726 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
718 727 << varRequest.m_DataSeries->range();
719 728 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
720 729
721 730 /// @todo MPL: confirm
722 731 // Variable update is notified only if there is no pending request for it
723 732 if (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first) == 0) {
724 733 emit var->updated();
725 734 }
726 735 }
727 736 else {
728 737 qCCritical(LOG_VariableController())
729 738 << tr("Impossible to update data to a null variable");
730 739 }
731 740 }
732 741
733 742 // cleaning varRequestId
734 743 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
735 744 << m_VarRequestIdToVarIdVarRequestMap.size();
736 745 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
737 746 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
738 747 << m_VarRequestIdToVarIdVarRequestMap.size();
739 748 }
740 749 }
741 750 else {
742 751 qCCritical(LOG_VariableController())
743 752 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
744 753 }
745 754 }
746 755
747 756 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
748 757 {
749 758 // cleaning varRequestId
750 759 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
751 760
752 761 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
753 762 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
754 763 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
755 764 varRequestIdQueue.erase(
756 765 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
757 766 varRequestIdQueue.end());
758 767 if (varRequestIdQueue.empty()) {
759 768 varIdToVarRequestIdQueueMapIt
760 769 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
761 770 }
762 771 else {
763 772 ++varIdToVarRequestIdQueueMapIt;
764 773 }
765 774 }
766 775 }
@@ -1,72 +1,74
1 1 #include <QObject>
2 2 #include <QtTest>
3 3
4 4 #include <Data/IDataProvider.h>
5 5 #include <Time/TimeController.h>
6 6 #include <Variable/Variable.h>
7 7 #include <Variable/VariableController.h>
8 8
9 9 #include <memory>
10 10
11 11 namespace {
12 12
13 13 /// Provider used for the tests
14 14 class TestProvider : public IDataProvider {
15 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
16
15 17 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
16 18 {
17 19 // Does nothing
18 20 }
19 21
20 22 void requestDataAborting(QUuid acqIdentifier) override
21 23 {
22 24 // Does nothing
23 25 }
24 26 };
25 27
26 28 /// Generates a time controller for the tests
27 29 std::unique_ptr<TimeController> defaultTimeController()
28 30 {
29 31 auto timeController = std::make_unique<TimeController>();
30 32
31 33 QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}};
32 34 QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}};
33 35 timeController->onTimeToUpdate(
34 36 SqpRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)});
35 37
36 38 return timeController;
37 39 }
38 40
39 41 } // namespace
40 42
41 43 class TestVariableController : public QObject {
42 44 Q_OBJECT
43 45
44 46 private slots:
45 47 /// Test removes variable from controller
46 48 void testDeleteVariable();
47 49 };
48 50
49 51 void TestVariableController::testDeleteVariable()
50 52 {
51 53 // Creates variable controller
52 54 auto timeController = defaultTimeController();
53 55 VariableController variableController{};
54 56 variableController.setTimeController(timeController.get());
55 57
56 58 // Creates a variable from the controller
57 59 auto variable
58 60 = variableController.createVariable("variable", {}, std::make_shared<TestProvider>());
59 61
60 62 qDebug() << QString::number(variable.use_count());
61 63
62 64 // Removes the variable from the controller
63 65 variableController.deleteVariable(variable);
64 66
65 67 // Verifies that the variable has been deleted: this implies that the number of shared_ptr
66 68 // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion
67 69 // is considered invalid since the variable is still referenced in the controller
68 70 QVERIFY(variable.use_count() == 1);
69 71 }
70 72
71 73 QTEST_MAIN(TestVariableController)
72 74 #include "TestVariableController.moc"
@@ -1,30 +1,31
1 1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 2 #define SCIQLOP_AMDAPROVIDER_H
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12 12
13 13 class QNetworkReply;
14 14
15 15 /**
16 16 * @brief The AmdaProvider class is an example of how a data provider can generate data
17 17 */
18 18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
19 19 public:
20 20 explicit AmdaProvider();
21 std::shared_ptr<IDataProvider> clone() const override;
21 22
22 23 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
23 24
24 25 void requestDataAborting(QUuid acqIdentifier) override;
25 26
26 27 private:
27 28 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
28 29 };
29 30
30 31 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,168 +1,174
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 5 #include <Common/DateUtils.h>
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Network/NetworkController.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10
11 11 #include <QNetworkAccessManager>
12 12 #include <QNetworkReply>
13 13 #include <QTemporaryFile>
14 14 #include <QThread>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 17
18 18 namespace {
19 19
20 20 /// URL format for a request on AMDA server. The parameters are as follows:
21 21 /// - %1: start date
22 22 /// - %2: end date
23 23 /// - %3: parameter id
24 24 const auto AMDA_URL_FORMAT = QStringLiteral(
25 25 "http://amda.irap.omp.eu/php/rest/"
26 26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
27 27 "timeFormat=ISO8601&gzip=0");
28 28
29 29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
30 30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31 31
32 32 /// Formats a time to a date that can be passed in URL
33 33 QString dateFormat(double sqpRange) noexcept
34 34 {
35 35 auto dateTime = DateUtils::dateTime(sqpRange);
36 36 return dateTime.toString(AMDA_TIME_FORMAT);
37 37 }
38 38
39 39 AmdaResultParser::ValueType valueType(const QString &valueType)
40 40 {
41 41 if (valueType == QStringLiteral("scalar")) {
42 42 return AmdaResultParser::ValueType::SCALAR;
43 43 }
44 44 else if (valueType == QStringLiteral("vector")) {
45 45 return AmdaResultParser::ValueType::VECTOR;
46 46 }
47 47 else {
48 48 return AmdaResultParser::ValueType::UNKNOWN;
49 49 }
50 50 }
51 51
52 52 } // namespace
53 53
54 54 AmdaProvider::AmdaProvider()
55 55 {
56 56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
57 57 if (auto app = sqpApp) {
58 58 auto &networkController = app->networkController();
59 59 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
60 60 std::function<void(QNetworkReply *, QUuid)>)),
61 61 &networkController,
62 62 SLOT(onProcessRequested(QNetworkRequest, QUuid,
63 63 std::function<void(QNetworkReply *, QUuid)>)));
64 64
65 65
66 66 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
67 67 SIGNAL(dataProvidedProgress(QUuid, double)));
68 68 }
69 69 }
70 70
71 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
72 {
73 // No copy is made in the clone
74 return std::make_shared<AmdaProvider>();
75 }
76
71 77 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
72 78 {
73 79 // NOTE: Try to use multithread if possible
74 80 const auto times = parameters.m_Times;
75 81 const auto data = parameters.m_Data;
76 82 for (const auto &dateTime : qAsConst(times)) {
77 83 this->retrieveData(acqIdentifier, dateTime, data);
78 84
79 85 // TORM when AMDA will support quick asynchrone request
80 86 QThread::msleep(1000);
81 87 }
82 88 }
83 89
84 90 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
85 91 {
86 92 if (auto app = sqpApp) {
87 93 auto &networkController = app->networkController();
88 94 networkController.onReplyCanceled(acqIdentifier);
89 95 }
90 96 }
91 97
92 98 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
93 99 {
94 100 // Retrieves product ID from data: if the value is invalid, no request is made
95 101 auto productId = data.value(AMDA_XML_ID_KEY).toString();
96 102 if (productId.isNull()) {
97 103 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
98 104 return;
99 105 }
100 106 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
101 107
102 108 // Retrieves the data type that determines whether the expected format for the result file is
103 109 // scalar, vector...
104 110 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
105 111
106 112 // /////////// //
107 113 // Creates URL //
108 114 // /////////// //
109 115
110 116 auto startDate = dateFormat(dateTime.m_TStart);
111 117 auto endDate = dateFormat(dateTime.m_TEnd);
112 118
113 119 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
114 120 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
115 121 auto tempFile = std::make_shared<QTemporaryFile>();
116 122
117 123 // LAMBDA
118 124 auto httpDownloadFinished = [this, dateTime, tempFile,
119 125 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
120 126
121 127 // Don't do anything if the reply was abort
122 128 if (reply->error() != QNetworkReply::OperationCanceledError) {
123 129
124 130 if (tempFile) {
125 131 auto replyReadAll = reply->readAll();
126 132 if (!replyReadAll.isEmpty()) {
127 133 tempFile->write(replyReadAll);
128 134 }
129 135 tempFile->close();
130 136
131 137 // Parse results file
132 138 if (auto dataSeries
133 139 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
134 140 emit dataProvided(dataId, dataSeries, dateTime);
135 141 }
136 142 else {
137 143 /// @todo ALX : debug
138 144 }
139 145 }
140 146 }
141 147
142 148 };
143 149 auto httpFinishedLambda
144 150 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
145 151
146 152 // Don't do anything if the reply was abort
147 153 if (reply->error() != QNetworkReply::OperationCanceledError) {
148 154 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
149 155
150 156
151 157 qCInfo(LOG_AmdaProvider())
152 158 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
153 159 // Executes request for downloading file //
154 160
155 161 // Creates destination file
156 162 if (tempFile->open()) {
157 163 // Executes request
158 164 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
159 165 httpDownloadFinished);
160 166 }
161 167 }
162 168 };
163 169
164 170 // //////////////// //
165 171 // Executes request //
166 172 // //////////////// //
167 173 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
168 174 }
@@ -1,34 +1,36
1 1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 2 #define SCIQLOP_COSINUSPROVIDER_H
3 3
4 4 #include "MockPluginGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QUuid>
10 10
11 11 #include <QHash>
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
13 13
14 14 /**
15 15 * @brief The CosinusProvider class is an example of how a data provider can generate data
16 16 */
17 17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
18 18 public:
19 std::shared_ptr<IDataProvider> clone() const override;
20
19 21 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
20 22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
21 23
22 24
23 25 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
24 26 void requestDataAborting(QUuid acqIdentifier) override;
25 27
26 28
27 29 private:
28 30 std::shared_ptr<IDataSeries> retrieveData(QUuid acqIdentifier,
29 31 const SqpRange &dataRangeRequested);
30 32
31 33 QHash<QUuid, bool> m_VariableToEnableProvider;
32 34 };
33 35
34 36 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,103 +1,109
1 1 #include "CosinusProvider.h"
2 2
3 3 #include <Data/DataProviderParameters.h>
4 4 #include <Data/ScalarSeries.h>
5 5
6 6 #include <cmath>
7 7
8 8 #include <QFuture>
9 9 #include <QThread>
10 10 #include <QtConcurrent/QtConcurrent>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13 13
14 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
15 {
16 // No copy is made in clone
17 return std::make_shared<CosinusProvider>();
18 }
19
14 20 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
15 21 const SqpRange &dataRangeRequested)
16 22 {
17 23 // TODO: Add Mutex
18 24 auto dataIndex = 0;
19 25
20 26 // Gets the timerange from the parameters
21 27 double freq = 100.0;
22 28 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
23 29 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
24 30
25 31 // We assure that timerange is valid
26 32 if (end < start) {
27 33 std::swap(start, end);
28 34 }
29 35
30 36 // Generates scalar series containing cosinus values (one value per second)
31 37 auto dataCount = end - start;
32 38
33 39 auto xAxisData = std::vector<double>{};
34 40 xAxisData.resize(dataCount);
35 41
36 42 auto valuesData = std::vector<double>{};
37 43 valuesData.resize(dataCount);
38 44
39 45 int progress = 0;
40 46 auto progressEnd = dataCount;
41 47 for (auto time = start; time < end; ++time, ++dataIndex) {
42 48 auto it = m_VariableToEnableProvider.find(acqIdentifier);
43 49 if (it != m_VariableToEnableProvider.end() && it.value()) {
44 50 const auto timeOnFreq = time / freq;
45 51
46 52 xAxisData[dataIndex] = timeOnFreq;
47 53 valuesData[dataIndex] = std::cos(timeOnFreq);
48 54
49 55 // progression
50 56 int currentProgress = (time - start) * 100.0 / progressEnd;
51 57 if (currentProgress != progress) {
52 58 progress = currentProgress;
53 59
54 60 emit dataProvidedProgress(acqIdentifier, progress);
55 61 }
56 62 }
57 63 else {
58 64 if (!it.value()) {
59 65 qCDebug(LOG_CosinusProvider())
60 66 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
61 67 << end - time;
62 68 }
63 69 }
64 70 }
65 71 emit dataProvidedProgress(acqIdentifier, 0.0);
66 72
67 73 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
68 74 Unit{QStringLiteral("t"), true}, Unit{});
69 75 }
70 76
71 77 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
72 78 const DataProviderParameters &parameters)
73 79 {
74 80 // TODO: Add Mutex
75 81 m_VariableToEnableProvider[acqIdentifier] = true;
76 82 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
77 83 << QThread::currentThread()->objectName();
78 84 // NOTE: Try to use multithread if possible
79 85 const auto times = parameters.m_Times;
80 86
81 87 for (const auto &dateTime : qAsConst(times)) {
82 88 if (m_VariableToEnableProvider[acqIdentifier]) {
83 89 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
84 90 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
85 91 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
86 92 }
87 93 }
88 94 }
89 95
90 96 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
91 97 {
92 98 // TODO: Add Mutex
93 99 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
94 100 << QThread::currentThread()->objectName();
95 101 auto it = m_VariableToEnableProvider.find(acqIdentifier);
96 102 if (it != m_VariableToEnableProvider.end()) {
97 103 it.value() = false;
98 104 }
99 105 else {
100 106 qCWarning(LOG_CosinusProvider())
101 107 << tr("Aborting progression of inexistant identifier detected !!!");
102 108 }
103 109 }
General Comments 0
You need to be logged in to leave comments. Login now