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