##// END OF EJS Templates
Implement progression for AmdaProvider.
perrinel -
r695:22c6ca1df132
parent child
Show More
@@ -1,42 +1,44
1 1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 2 #define SCIQLOP_AMDAPROVIDER_H
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 #include <map>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
13 13
14 14 class QNetworkReply;
15 15 class QNetworkRequest;
16 16
17 17 /**
18 18 * @brief The AmdaProvider class is an example of how a data provider can generate data
19 19 */
20 20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
21 Q_OBJECT
21 22 public:
22 23 explicit AmdaProvider();
23 24 std::shared_ptr<IDataProvider> clone() const override;
24 25
25 26 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
26 27
27 28 void requestDataAborting(QUuid acqIdentifier) override;
28 29
29 30 private slots:
30 void onReplyDownloadProgress(QUuid, const QNetworkRequest &, double progress);
31 void onReplyDownloadProgress(QUuid acqIdentifier,
32 std::shared_ptr<QNetworkRequest> networkRequest, double progress);
31 33
32 34 private:
33 35 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
34 36
35 37 void updateRequestProgress(QUuid acqIdentifier, std::shared_ptr<QNetworkRequest> request,
36 38 double progress);
37 39
38 40 std::map<QUuid, std::map<std::shared_ptr<QNetworkRequest>, double> >
39 41 m_AcqIdToRequestProgressMap;
40 42 };
41 43
42 44 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,260 +1,267
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 5 #include <Common/DateUtils.h>
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Network/NetworkController.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10
11 11 #include <QNetworkAccessManager>
12 12 #include <QNetworkReply>
13 13 #include <QTemporaryFile>
14 14 #include <QThread>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 17
18 18 namespace {
19 19
20 20 /// URL format for a request on AMDA server. The parameters are as follows:
21 21 /// - %1: start date
22 22 /// - %2: end date
23 23 /// - %3: parameter id
24 24 const auto AMDA_URL_FORMAT = QStringLiteral(
25 25 "http://amda.irap.omp.eu/php/rest/"
26 26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
27 27 "timeFormat=ISO8601&gzip=0");
28 28
29 29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
30 30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31 31
32 // struct AmdaProgression {
33 // QUuid acqIdentifier;
34 // std::map<QNetworkRequest, double> m_RequestId;
35 //};
36
37 32 /// Formats a time to a date that can be passed in URL
38 33 QString dateFormat(double sqpRange) noexcept
39 34 {
40 35 auto dateTime = DateUtils::dateTime(sqpRange);
41 36 return dateTime.toString(AMDA_TIME_FORMAT);
42 37 }
43 38
44 39 AmdaResultParser::ValueType valueType(const QString &valueType)
45 40 {
46 41 if (valueType == QStringLiteral("scalar")) {
47 42 return AmdaResultParser::ValueType::SCALAR;
48 43 }
49 44 else if (valueType == QStringLiteral("vector")) {
50 45 return AmdaResultParser::ValueType::VECTOR;
51 46 }
52 47 else {
53 48 return AmdaResultParser::ValueType::UNKNOWN;
54 49 }
55 50 }
56 51
57 52 } // namespace
58 53
59 54 AmdaProvider::AmdaProvider()
60 55 {
61 56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
62 57 if (auto app = sqpApp) {
63 58 auto &networkController = app->networkController();
64 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
59 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
65 60 std::function<void(QNetworkReply *, QUuid)>)),
66 61 &networkController,
67 SLOT(onProcessRequested(QNetworkRequest, QUuid,
62 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
68 63 std::function<void(QNetworkReply *, QUuid)>)));
69 64
70 65
71 66 connect(&sqpApp->networkController(),
72 SIGNAL(replyDownloadProgress(QUuid, const QNetworkRequest &, double)), this,
73 SLOT(onReplyDownloadProgress(QUuid, const QNetworkRequest &, double)));
67 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
68 this,
69 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
74 70 }
75 71 }
76 72
77 73 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
78 74 {
79 75 // No copy is made in the clone
80 76 return std::make_shared<AmdaProvider>();
81 77 }
82 78
83 79 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
84 80 {
85 81 // NOTE: Try to use multithread if possible
86 82 const auto times = parameters.m_Times;
87 83 const auto data = parameters.m_Data;
88 84 for (const auto &dateTime : qAsConst(times)) {
89 85 this->retrieveData(acqIdentifier, dateTime, data);
90 86
91 87
92 88 // TORM when AMDA will support quick asynchrone request
93 89 QThread::msleep(1000);
94 90 }
95 91 }
96 92
97 93 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
98 94 {
99 95 if (auto app = sqpApp) {
100 96 auto &networkController = app->networkController();
101 97 networkController.onReplyCanceled(acqIdentifier);
102 98 }
103 99 }
104 100
105 101 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
106 const QNetworkRequest &networkRequest, double progress)
102 std::shared_ptr<QNetworkRequest> networkRequest,
103 double progress)
107 104 {
108 qCCritical(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << progress;
105 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
106 << networkRequest.get() << progress;
109 107 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
110 108 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
111 109
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(); };
110 qCDebug(LOG_AmdaProvider()) << tr("1 onReplyDownloadProgress found") << progress;
111 auto requestPtr = networkRequest;
112 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
116 113
117 114 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
118 115 auto requestProgressMapEnd = requestProgressMap.end();
119 116 auto requestProgressMapIt
120 117 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
121 118
122 119 if (requestProgressMapIt != requestProgressMapEnd) {
123 120 requestProgressMapIt->second = progress;
124 121 }
125 122 else {
126 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress");
123 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress")
124 << acqIdentifier << networkRequest.get() << progress;
127 125 }
128 126 }
129 127
130 128 acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
131 129 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
132 qCCritical(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress") << progress;
133 130 double finalProgress = 0.0;
134 131
135 132 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
136 133 auto fraq = requestProgressMap.size();
137 134
138 135 for (auto requestProgress : requestProgressMap) {
139 136 finalProgress += requestProgress.second;
137 qCDebug(LOG_AmdaProvider()) << tr("current final progress without freq:")
138 << finalProgress << requestProgress.second;
140 139 }
141 140
142 141 if (fraq > 0) {
143 142 finalProgress = finalProgress / fraq;
144 143 }
145 144
146 qCCritical(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress") << finalProgress;
145 qCDebug(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress final progress") << fraq
146 << finalProgress;
147 147 emit dataProvidedProgress(acqIdentifier, finalProgress);
148 148 }
149 149 else {
150 150 emit dataProvidedProgress(acqIdentifier, 0.0);
151 151 }
152 152 }
153 153
154 154 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
155 155 {
156 156 // Retrieves product ID from data: if the value is invalid, no request is made
157 157 auto productId = data.value(AMDA_XML_ID_KEY).toString();
158 158 if (productId.isNull()) {
159 159 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
160 160 return;
161 161 }
162 162 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
163 163
164 164 // Retrieves the data type that determines whether the expected format for the result file is
165 165 // scalar, vector...
166 166 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
167 167
168 168 // /////////// //
169 169 // Creates URL //
170 170 // /////////// //
171 171
172 172 auto startDate = dateFormat(dateTime.m_TStart);
173 173 auto endDate = dateFormat(dateTime.m_TEnd);
174 174
175 175 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
176 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
176 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
177 177 auto tempFile = std::make_shared<QTemporaryFile>();
178 178
179 179 // LAMBDA
180 180 auto httpDownloadFinished = [this, dateTime, tempFile,
181 181 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
182 182
183 183 // Don't do anything if the reply was abort
184 184 if (reply->error() != QNetworkReply::OperationCanceledError) {
185 185
186 186 if (tempFile) {
187 187 auto replyReadAll = reply->readAll();
188 188 if (!replyReadAll.isEmpty()) {
189 189 tempFile->write(replyReadAll);
190 190 }
191 191 tempFile->close();
192 192
193 193 // Parse results file
194 194 if (auto dataSeries
195 195 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
196 196 emit dataProvided(dataId, dataSeries, dateTime);
197 197 }
198 198 else {
199 199 /// @todo ALX : debug
200 200 }
201 201 }
202 202 m_AcqIdToRequestProgressMap.erase(dataId);
203 203 }
204 204
205 205 };
206 206 auto httpFinishedLambda
207 207 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
208 208
209 209 // Don't do anything if the reply was abort
210 210 if (reply->error() != QNetworkReply::OperationCanceledError) {
211 211 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
212 212
213 213 qCInfo(LOG_AmdaProvider())
214 214 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
215 215 // Executes request for downloading file //
216 216
217 217 // Creates destination file
218 218 if (tempFile->open()) {
219 // Executes request
219 // Executes request and store the request for progression
220 220 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
221 221 updateRequestProgress(dataId, request, 0.0);
222 emit requestConstructed(*request.get(), dataId, httpDownloadFinished);
222 emit requestConstructed(request, dataId, httpDownloadFinished);
223 223 }
224 224 }
225 225 else {
226 226 m_AcqIdToRequestProgressMap.erase(dataId);
227 227 }
228 228 };
229 229
230 230 // //////////////// //
231 231 // Executes request //
232 232 // //////////////// //
233 233
234 234 auto request = std::make_shared<QNetworkRequest>(url);
235 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
235 236 updateRequestProgress(token, request, 0.0);
236 237
237 emit requestConstructed(*request.get(), token, httpFinishedLambda);
238 emit requestConstructed(request, token, httpFinishedLambda);
238 239 }
239 240
240 241 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
241 242 std::shared_ptr<QNetworkRequest> request, double progress)
242 243 {
243 244 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
244 245 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
245 246 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
246 247 auto requestProgressMapIt = requestProgressMap.find(request);
247 248 if (requestProgressMapIt != requestProgressMap.end()) {
248 249 requestProgressMapIt->second = progress;
250 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
251 << acqIdentifier << request.get() << progress;
249 252 }
250 253 else {
254 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
255 << request.get() << progress;
251 256 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
252 257 }
253 258 }
254 259 else {
260 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
261 << acqIdentifier << request.get() << progress;
255 262 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
256 263 requestProgressMap.insert(std::make_pair(request, progress));
257 264 m_AcqIdToRequestProgressMap.insert(
258 265 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
259 266 }
260 267 }
General Comments 2
You need to be logged in to leave comments. Login now