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