##// END OF EJS Templates
Fix progression bug when aborting a request for Amda plugin
perrinel -
r701:87c4dffdd5b8
parent child
Show More
@@ -1,321 +1,300
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>
15 #include <cmath>
16
16
17 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
17 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
18
18
19 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
19 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
20
20
21 explicit VariableAcquisitionWorkerPrivate(VariableAcquisitionWorker *parent)
21 explicit VariableAcquisitionWorkerPrivate(VariableAcquisitionWorker *parent)
22 : m_Lock{QReadWriteLock::Recursive}, q{parent}
22 : m_Lock{QReadWriteLock::Recursive}, q{parent}
23 {
23 {
24 }
24 }
25
25
26 void lockRead() { m_Lock.lockForRead(); }
26 void lockRead() { m_Lock.lockForRead(); }
27 void lockWrite() { m_Lock.lockForWrite(); }
27 void lockWrite() { m_Lock.lockForWrite(); }
28 void unlock() { m_Lock.unlock(); }
28 void unlock() { m_Lock.unlock(); }
29
29
30 void removeVariableRequest(QUuid vIdentifier);
30 void removeVariableRequest(QUuid vIdentifier);
31
31
32 /// Remove the current request and execute the next one if exist
32 /// Remove the current request and execute the next one if exist
33 void updateToNextRequest(QUuid vIdentifier);
33 void updateToNextRequest(QUuid vIdentifier);
34
34
35 QMutex m_WorkingMutex;
35 QMutex m_WorkingMutex;
36 QReadWriteLock m_Lock;
36 QReadWriteLock m_Lock;
37
37
38 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
38 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
39 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
39 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
40 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
40 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
41 VariableAcquisitionWorker *q;
41 VariableAcquisitionWorker *q;
42 };
42 };
43
43
44
44
45 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
45 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
46 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>(this)}
46 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>(this)}
47 {
47 {
48 }
48 }
49
49
50 VariableAcquisitionWorker::~VariableAcquisitionWorker()
50 VariableAcquisitionWorker::~VariableAcquisitionWorker()
51 {
51 {
52 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
52 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
53 << QThread::currentThread();
53 << QThread::currentThread();
54 this->waitForFinish();
54 this->waitForFinish();
55 }
55 }
56
56
57
57
58 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
58 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
59 SqpRange rangeRequested,
59 SqpRange rangeRequested,
60 SqpRange cacheRangeRequested,
60 SqpRange cacheRangeRequested,
61 DataProviderParameters parameters,
61 DataProviderParameters parameters,
62 std::shared_ptr<IDataProvider> provider)
62 std::shared_ptr<IDataProvider> provider)
63 {
63 {
64 qCDebug(LOG_VariableAcquisitionWorker())
64 qCDebug(LOG_VariableAcquisitionWorker())
65 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
65 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
66 auto varRequestIdCanceled = QUuid();
66 auto varRequestIdCanceled = QUuid();
67
67
68 // Request creation
68 // Request creation
69 auto acqRequest = AcquisitionRequest{};
69 auto acqRequest = AcquisitionRequest{};
70 acqRequest.m_VarRequestId = varRequestId;
70 acqRequest.m_VarRequestId = varRequestId;
71 acqRequest.m_vIdentifier = vIdentifier;
71 acqRequest.m_vIdentifier = vIdentifier;
72 acqRequest.m_DataProviderParameters = parameters;
72 acqRequest.m_DataProviderParameters = parameters;
73 acqRequest.m_RangeRequested = rangeRequested;
73 acqRequest.m_RangeRequested = rangeRequested;
74 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
74 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
75 acqRequest.m_Size = parameters.m_Times.size();
75 acqRequest.m_Size = parameters.m_Times.size();
76 acqRequest.m_Provider = provider;
76 acqRequest.m_Provider = provider;
77
77
78
78
79 // Register request
79 // Register request
80 impl->lockWrite();
80 impl->lockWrite();
81 impl->m_AcqIdentifierToAcqRequestMap.insert(
81 impl->m_AcqIdentifierToAcqRequestMap.insert(
82 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
82 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
83
83
84 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
84 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
85 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
85 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
86 // A current request already exists, we can replace the next one
86 // A current request already exists, we can replace the next one
87 auto nextAcqId = it->second.second;
87 auto nextAcqId = it->second.second;
88 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
88 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
89 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
89 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
90 auto request = acqIdentifierToAcqRequestMapIt->second;
90 auto request = acqIdentifierToAcqRequestMapIt->second;
91 varRequestIdCanceled = request.m_VarRequestId;
91 varRequestIdCanceled = request.m_VarRequestId;
92 }
92 }
93
93
94 it->second.second = acqRequest.m_AcqIdentifier;
94 it->second.second = acqRequest.m_AcqIdentifier;
95 impl->unlock();
95 impl->unlock();
96 }
96 }
97 else {
97 else {
98 // First request for the variable, it must be stored and executed
98 // First request for the variable, it must be stored and executed
99 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
99 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
100 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
100 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
101 impl->unlock();
101 impl->unlock();
102
102
103 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
103 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
104 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
104 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
105 }
105 }
106
106
107 return varRequestIdCanceled;
107 return varRequestIdCanceled;
108 }
108 }
109
109
110 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
110 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
111 {
111 {
112 // TODO
113 impl->lockRead();
112 impl->lockRead();
114
113
115 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
114 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
116 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
115 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
117 auto currentAcqId = it->second.first;
116 auto currentAcqId = it->second.first;
118
117
119 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(currentAcqId);
118 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(currentAcqId);
120 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
119 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
121 auto request = it->second;
120 auto request = it->second;
122 impl->unlock();
121 impl->unlock();
123
122
124 // Remove the current request from the worker
123 // Remove the current request from the worker
125
124
126 impl->lockWrite();
125 impl->lockWrite();
127 impl->updateToNextRequest(vIdentifier);
126 impl->updateToNextRequest(vIdentifier);
128 impl->unlock();
127 impl->unlock();
129
128
130 // notify the request aborting to the provider
129 // notify the request aborting to the provider
131 request.m_Provider->requestDataAborting(currentAcqId);
130 request.m_Provider->requestDataAborting(currentAcqId);
132 }
131 }
133 else {
132 else {
134 impl->unlock();
133 impl->unlock();
135 qCWarning(LOG_VariableAcquisitionWorker())
134 qCWarning(LOG_VariableAcquisitionWorker())
136 << tr("Impossible to abort an unknown acquisition request") << currentAcqId;
135 << tr("Impossible to abort an unknown acquisition request") << currentAcqId;
137 }
136 }
138 }
137 }
139 else {
138 else {
140 impl->unlock();
139 impl->unlock();
141 }
140 }
142 }
141 }
143
142
144 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
143 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
145 double progress)
144 double progress)
146 {
145 {
146 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableRetrieveDataInProgress ")
147 << acqIdentifier << progress;
147 impl->lockRead();
148 impl->lockRead();
148 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
149 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
149 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
150 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
150 auto currentPartSize = (aIdToARit->second.m_Size != 0) ? 100 / aIdToARit->second.m_Size : 0;
151 auto currentPartSize = (aIdToARit->second.m_Size != 0) ? 100 / aIdToARit->second.m_Size : 0;
151
152
152 auto currentPartProgress
153 auto currentPartProgress
153 = std::isnan(progress) ? 0.0 : (progress * currentPartSize) / 100.0;
154 = std::isnan(progress) ? 0.0 : (progress * currentPartSize) / 100.0;
154 auto currentAlreadyProgress = aIdToARit->second.m_Progression * currentPartSize;
155 auto currentAlreadyProgress = aIdToARit->second.m_Progression * currentPartSize;
155
156
156 auto finalProgression = currentAlreadyProgress + currentPartProgress;
157 auto finalProgression = currentAlreadyProgress + currentPartProgress;
157 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, finalProgression);
158 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, finalProgression);
158
159 qCDebug(LOG_VariableAcquisitionWorker())
160 << tr("TORM: onVariableRetrieveDataInProgress ") << aIdToARit->second.m_vIdentifier
161 << currentPartSize << currentAlreadyProgress << currentPartProgress << finalProgression;
159 if (finalProgression == 100.0) {
162 if (finalProgression == 100.0) {
160 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, 0.0);
163 emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, 0.0);
161 }
164 }
162 }
165 }
163 impl->unlock();
166 impl->unlock();
164 }
167 }
165
168
166 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
169 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
167 std::shared_ptr<IDataSeries> dataSeries,
170 std::shared_ptr<IDataSeries> dataSeries,
168 SqpRange dataRangeAcquired)
171 SqpRange dataRangeAcquired)
169 {
172 {
170 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableDataAcquired on range ")
173 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableDataAcquired on range ")
171 << acqIdentifier << dataRangeAcquired;
174 << acqIdentifier << dataRangeAcquired;
172 impl->lockWrite();
175 impl->lockWrite();
173 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
176 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
174 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
177 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
175 // Store the result
178 // Store the result
176 auto dataPacket = AcquisitionDataPacket{};
179 auto dataPacket = AcquisitionDataPacket{};
177 dataPacket.m_Range = dataRangeAcquired;
180 dataPacket.m_Range = dataRangeAcquired;
178 dataPacket.m_DateSeries = dataSeries;
181 dataPacket.m_DateSeries = dataSeries;
179
182
180 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
183 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
181 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
184 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
182 // A current request result already exists, we can update it
185 // A current request result already exists, we can update it
183 aIdToADPVit->second.push_back(dataPacket);
186 aIdToADPVit->second.push_back(dataPacket);
184 }
187 }
185 else {
188 else {
186 // First request result for the variable, it must be stored
189 // First request result for the variable, it must be stored
187 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
190 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
188 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
191 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
189 }
192 }
190
193
191
194
192 // Decrement the counter of the request
195 // Decrement the counter of the request
193 auto &acqRequest = aIdToARit->second;
196 auto &acqRequest = aIdToARit->second;
194 acqRequest.m_Progression = acqRequest.m_Progression + 1;
197 acqRequest.m_Progression = acqRequest.m_Progression + 1;
195
198
196 // if the counter is 0, we can return data then run the next request if it exists and
199 // if the counter is 0, we can return data then run the next request if it exists and
197 // removed the finished request
200 // removed the finished request
198 if (acqRequest.m_Size == acqRequest.m_Progression) {
201 if (acqRequest.m_Size == acqRequest.m_Progression) {
199 // Return the data
202 // Return the data
200 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
203 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
201 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
204 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
202 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
205 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
203 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
206 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
204 }
207 }
205
208
206 // Execute the next one
209 // Update to the next request
207 auto it
210 impl->updateToNextRequest(acqRequest.m_vIdentifier);
208 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
209
210 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
211 if (it->second.second.isNull()) {
212 // There is no next request, we can remove the variable request
213 impl->removeVariableRequest(acqRequest.m_vIdentifier);
214 }
215 else {
216 auto acqIdentifierToRemove = it->second.first;
217 // Move the next request to the current request
218 it->second.first = it->second.second;
219 it->second.second = QUuid();
220 // Remove AcquisitionRequest and results;
221 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
222 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
223 // Execute the current request
224 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
225 Q_ARG(QUuid, it->second.first));
226 }
227 }
228 else {
229 qCCritical(LOG_VariableAcquisitionWorker())
230 << tr("Impossible to execute the acquisition on an unfound variable ");
231 }
232 }
211 }
233 }
212 }
234 else {
213 else {
235 qCWarning(LOG_VariableAcquisitionWorker())
214 qCWarning(LOG_VariableAcquisitionWorker())
236 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
215 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
237 }
216 }
238 impl->unlock();
217 impl->unlock();
239 }
218 }
240
219
241 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
220 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
242 {
221 {
243 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
222 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
244 impl->lockRead();
223 impl->lockRead();
245 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
224 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
246 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
225 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
247 auto request = it->second;
226 auto request = it->second;
248 impl->unlock();
227 impl->unlock();
249 emit variableRequestInProgress(request.m_vIdentifier, 0.1);
228 emit variableRequestInProgress(request.m_vIdentifier, 0.1);
250 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
229 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
251 }
230 }
252 else {
231 else {
253 impl->unlock();
232 impl->unlock();
254 // TODO log no acqIdentifier recognized
233 // TODO log no acqIdentifier recognized
255 }
234 }
256 }
235 }
257
236
258 void VariableAcquisitionWorker::initialize()
237 void VariableAcquisitionWorker::initialize()
259 {
238 {
260 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
239 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
261 << QThread::currentThread();
240 << QThread::currentThread();
262 impl->m_WorkingMutex.lock();
241 impl->m_WorkingMutex.lock();
263 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
242 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
264 }
243 }
265
244
266 void VariableAcquisitionWorker::finalize()
245 void VariableAcquisitionWorker::finalize()
267 {
246 {
268 impl->m_WorkingMutex.unlock();
247 impl->m_WorkingMutex.unlock();
269 }
248 }
270
249
271 void VariableAcquisitionWorker::waitForFinish()
250 void VariableAcquisitionWorker::waitForFinish()
272 {
251 {
273 QMutexLocker locker{&impl->m_WorkingMutex};
252 QMutexLocker locker{&impl->m_WorkingMutex};
274 }
253 }
275
254
276 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
255 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
277 QUuid vIdentifier)
256 QUuid vIdentifier)
278 {
257 {
279 lockWrite();
258 lockWrite();
280 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
259 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
281
260
282 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
261 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
283 // A current request already exists, we can replace the next one
262 // A current request already exists, we can replace the next one
284
263
285 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
264 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
286 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
265 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
287
266
288 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
267 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
289 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
268 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
290 }
269 }
291 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
270 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
292 unlock();
271 unlock();
293 }
272 }
294
273
295 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
274 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
296 QUuid vIdentifier)
275 QUuid vIdentifier)
297 {
276 {
298 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
277 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
299 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
278 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
300 if (it->second.second.isNull()) {
279 if (it->second.second.isNull()) {
301 // There is no next request, we can remove the variable request
280 // There is no next request, we can remove the variable request
302 removeVariableRequest(vIdentifier);
281 removeVariableRequest(vIdentifier);
303 }
282 }
304 else {
283 else {
305 auto acqIdentifierToRemove = it->second.first;
284 auto acqIdentifierToRemove = it->second.first;
306 // Move the next request to the current request
285 // Move the next request to the current request
307 it->second.first = it->second.second;
286 it->second.first = it->second.second;
308 it->second.second = QUuid();
287 it->second.second = QUuid();
309 // Remove AcquisitionRequest and results;
288 // Remove AcquisitionRequest and results;
310 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
289 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
311 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
290 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
312 // Execute the current request
291 // Execute the current request
313 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
292 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
314 Q_ARG(QUuid, it->second.first));
293 Q_ARG(QUuid, it->second.first));
315 }
294 }
316 }
295 }
317 else {
296 else {
318 qCCritical(LOG_VariableAcquisitionWorker())
297 qCCritical(LOG_VariableAcquisitionWorker())
319 << tr("Impossible to execute the acquisition on an unfound variable ");
298 << tr("Impossible to execute the acquisition on an unfound variable ");
320 }
299 }
321 }
300 }
@@ -1,265 +1,274
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 /// Formats a time to a date that can be passed in URL
32 /// Formats a time to a date that can be passed in URL
33 QString dateFormat(double sqpRange) noexcept
33 QString dateFormat(double sqpRange) noexcept
34 {
34 {
35 auto dateTime = DateUtils::dateTime(sqpRange);
35 auto dateTime = DateUtils::dateTime(sqpRange);
36 return dateTime.toString(AMDA_TIME_FORMAT);
36 return dateTime.toString(AMDA_TIME_FORMAT);
37 }
37 }
38
38
39 AmdaResultParser::ValueType valueType(const QString &valueType)
39 AmdaResultParser::ValueType valueType(const QString &valueType)
40 {
40 {
41 if (valueType == QStringLiteral("scalar")) {
41 if (valueType == QStringLiteral("scalar")) {
42 return AmdaResultParser::ValueType::SCALAR;
42 return AmdaResultParser::ValueType::SCALAR;
43 }
43 }
44 else if (valueType == QStringLiteral("vector")) {
44 else if (valueType == QStringLiteral("vector")) {
45 return AmdaResultParser::ValueType::VECTOR;
45 return AmdaResultParser::ValueType::VECTOR;
46 }
46 }
47 else {
47 else {
48 return AmdaResultParser::ValueType::UNKNOWN;
48 return AmdaResultParser::ValueType::UNKNOWN;
49 }
49 }
50 }
50 }
51
51
52 } // namespace
52 } // namespace
53
53
54 AmdaProvider::AmdaProvider()
54 AmdaProvider::AmdaProvider()
55 {
55 {
56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
57 if (auto app = sqpApp) {
57 if (auto app = sqpApp) {
58 auto &networkController = app->networkController();
58 auto &networkController = app->networkController();
59 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
59 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
60 std::function<void(QNetworkReply *, QUuid)>)),
60 std::function<void(QNetworkReply *, QUuid)>)),
61 &networkController,
61 &networkController,
62 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
62 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
63 std::function<void(QNetworkReply *, QUuid)>)));
63 std::function<void(QNetworkReply *, QUuid)>)));
64
64
65
65
66 connect(&sqpApp->networkController(),
66 connect(&sqpApp->networkController(),
67 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
67 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
68 this,
68 this,
69 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
69 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
70 }
70 }
71 }
71 }
72
72
73 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
73 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
74 {
74 {
75 // No copy is made in the clone
75 // No copy is made in the clone
76 return std::make_shared<AmdaProvider>();
76 return std::make_shared<AmdaProvider>();
77 }
77 }
78
78
79 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
79 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
80 {
80 {
81 // NOTE: Try to use multithread if possible
81 // NOTE: Try to use multithread if possible
82 const auto times = parameters.m_Times;
82 const auto times = parameters.m_Times;
83 const auto data = parameters.m_Data;
83 const auto data = parameters.m_Data;
84 for (const auto &dateTime : qAsConst(times)) {
84 for (const auto &dateTime : qAsConst(times)) {
85 this->retrieveData(acqIdentifier, dateTime, data);
85 this->retrieveData(acqIdentifier, dateTime, data);
86
86
87
87
88 // TORM when AMDA will support quick asynchrone request
88 // TORM when AMDA will support quick asynchrone request
89 QThread::msleep(1000);
89 QThread::msleep(1000);
90 }
90 }
91 }
91 }
92
92
93 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
93 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
94 {
94 {
95 if (auto app = sqpApp) {
95 if (auto app = sqpApp) {
96 auto &networkController = app->networkController();
96 auto &networkController = app->networkController();
97 networkController.onReplyCanceled(acqIdentifier);
97 networkController.onReplyCanceled(acqIdentifier);
98 }
98 }
99 }
99 }
100
100
101 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
101 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
102 std::shared_ptr<QNetworkRequest> networkRequest,
102 std::shared_ptr<QNetworkRequest> networkRequest,
103 double progress)
103 double progress)
104 {
104 {
105 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
105 qCInfo(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
106 << networkRequest.get() << progress;
106 << networkRequest.get() << progress;
107 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
107 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
108 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
108 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
109
109
110 auto requestPtr = networkRequest;
110 auto requestPtr = networkRequest;
111 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
111 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
112
112
113 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
113 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
114 auto requestProgressMapEnd = requestProgressMap.end();
114 auto requestProgressMapEnd = requestProgressMap.end();
115 auto requestProgressMapIt
115 auto requestProgressMapIt
116 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
116 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
117
117
118 if (requestProgressMapIt != requestProgressMapEnd) {
118 if (requestProgressMapIt != requestProgressMapEnd) {
119 requestProgressMapIt->second = progress;
119 requestProgressMapIt->second = progress;
120 }
120 }
121 else {
121 else {
122 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress")
122 // This case can happened when a progression is send after the request has been
123 << acqIdentifier << networkRequest.get() << progress;
123 // finished.
124 // Generaly the case when aborting a request
125 qCWarning(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress")
126 << acqIdentifier << networkRequest.get() << progress;
124 }
127 }
125 }
128 }
126
129
127 acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
130 acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
128 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
131 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
129 double finalProgress = 0.0;
132 double finalProgress = 0.0;
130
133
131 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
134 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
132 auto fraq = requestProgressMap.size();
135 auto fraq = requestProgressMap.size();
133
136
134 for (auto requestProgress : requestProgressMap) {
137 for (auto requestProgress : requestProgressMap) {
135 finalProgress += requestProgress.second;
138 finalProgress += requestProgress.second;
136 qCDebug(LOG_AmdaProvider()) << tr("current final progress without freq:")
139 qCDebug(LOG_AmdaProvider()) << tr("current final progress without freq:")
137 << finalProgress << requestProgress.second;
140 << finalProgress << requestProgress.second;
138 }
141 }
139
142
140 if (fraq > 0) {
143 if (fraq > 0) {
141 finalProgress = finalProgress / fraq;
144 finalProgress = finalProgress / fraq;
142 }
145 }
143
146
144 qCDebug(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress final progress") << fraq
147 qCDebug(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress final progress") << fraq
145 << finalProgress;
148 << finalProgress;
146 emit dataProvidedProgress(acqIdentifier, finalProgress);
149 emit dataProvidedProgress(acqIdentifier, finalProgress);
147 }
150 }
148 else {
151 else {
149 emit dataProvidedProgress(acqIdentifier, 0.0);
152 // This case can happened when a progression is send after the request has been finished.
153 // Generaly the case when aborting a request
154 emit dataProvidedProgress(acqIdentifier, 100.0);
150 }
155 }
151 }
156 }
152
157
153 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
158 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
154 {
159 {
155 // Retrieves product ID from data: if the value is invalid, no request is made
160 // Retrieves product ID from data: if the value is invalid, no request is made
156 auto productId = data.value(AMDA_XML_ID_KEY).toString();
161 auto productId = data.value(AMDA_XML_ID_KEY).toString();
157 if (productId.isNull()) {
162 if (productId.isNull()) {
158 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
163 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
159 return;
164 return;
160 }
165 }
161
166
162 // Retrieves the data type that determines whether the expected format for the result file is
167 // Retrieves the data type that determines whether the expected format for the result file is
163 // scalar, vector...
168 // scalar, vector...
164 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
169 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
165
170
166 // /////////// //
171 // /////////// //
167 // Creates URL //
172 // Creates URL //
168 // /////////// //
173 // /////////// //
169
174
170 auto startDate = dateFormat(dateTime.m_TStart);
175 auto startDate = dateFormat(dateTime.m_TStart);
171 auto endDate = dateFormat(dateTime.m_TEnd);
176 auto endDate = dateFormat(dateTime.m_TEnd);
172
177
173 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
178 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
174 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
179 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
175 auto tempFile = std::make_shared<QTemporaryFile>();
180 auto tempFile = std::make_shared<QTemporaryFile>();
176
181
177 // LAMBDA
182 // LAMBDA
178 auto httpDownloadFinished = [this, dateTime, tempFile,
183 auto httpDownloadFinished = [this, dateTime, tempFile,
179 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
184 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
180
185
181 // Don't do anything if the reply was abort
186 // Don't do anything if the reply was abort
182 if (reply->error() != QNetworkReply::OperationCanceledError) {
187 if (reply->error() != QNetworkReply::OperationCanceledError) {
183
188
184 if (tempFile) {
189 if (tempFile) {
185 auto replyReadAll = reply->readAll();
190 auto replyReadAll = reply->readAll();
186 if (!replyReadAll.isEmpty()) {
191 if (!replyReadAll.isEmpty()) {
187 tempFile->write(replyReadAll);
192 tempFile->write(replyReadAll);
188 }
193 }
189 tempFile->close();
194 tempFile->close();
190
195
191 // Parse results file
196 // Parse results file
192 if (auto dataSeries
197 if (auto dataSeries
193 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
198 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
194 emit dataProvided(dataId, dataSeries, dateTime);
199 emit dataProvided(dataId, dataSeries, dateTime);
195 }
200 }
196 else {
201 else {
197 /// @todo ALX : debug
202 /// @todo ALX : debug
198 }
203 }
199 }
204 }
205 qCDebug(LOG_AmdaProvider()) << tr("acquisition requests erase because of finishing")
206 << dataId;
200 m_AcqIdToRequestProgressMap.erase(dataId);
207 m_AcqIdToRequestProgressMap.erase(dataId);
201 }
208 }
202
209
203 };
210 };
204 auto httpFinishedLambda
211 auto httpFinishedLambda
205 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
212 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
206
213
207 // Don't do anything if the reply was abort
214 // Don't do anything if the reply was abort
208 if (reply->error() != QNetworkReply::OperationCanceledError) {
215 if (reply->error() != QNetworkReply::OperationCanceledError) {
209 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
216 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
210
217
211 qCDebug(LOG_AmdaProvider())
218 qCDebug(LOG_AmdaProvider())
212 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
219 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
213 // Executes request for downloading file //
220 // Executes request for downloading file //
214
221
215 // Creates destination file
222 // Creates destination file
216 if (tempFile->open()) {
223 if (tempFile->open()) {
217 // Executes request and store the request for progression
224 // Executes request and store the request for progression
218 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
225 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
219 updateRequestProgress(dataId, request, 0.0);
226 updateRequestProgress(dataId, request, 0.0);
220 emit requestConstructed(request, dataId, httpDownloadFinished);
227 emit requestConstructed(request, dataId, httpDownloadFinished);
221 }
228 }
222 }
229 }
223 else {
230 else {
231 qCDebug(LOG_AmdaProvider())
232 << tr("acquisition requests erase because of aborting") << dataId;
224 m_AcqIdToRequestProgressMap.erase(dataId);
233 m_AcqIdToRequestProgressMap.erase(dataId);
225 }
234 }
226 };
235 };
227
236
228 // //////////////// //
237 // //////////////// //
229 // Executes request //
238 // Executes request //
230 // //////////////// //
239 // //////////////// //
231
240
232 auto request = std::make_shared<QNetworkRequest>(url);
241 auto request = std::make_shared<QNetworkRequest>(url);
233 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
242 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
234 updateRequestProgress(token, request, 0.0);
243 updateRequestProgress(token, request, 0.0);
235
244
236 emit requestConstructed(request, token, httpFinishedLambda);
245 emit requestConstructed(request, token, httpFinishedLambda);
237 }
246 }
238
247
239 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
248 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
240 std::shared_ptr<QNetworkRequest> request, double progress)
249 std::shared_ptr<QNetworkRequest> request, double progress)
241 {
250 {
242 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
251 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
243 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
252 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
244 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
253 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
245 auto requestProgressMapIt = requestProgressMap.find(request);
254 auto requestProgressMapIt = requestProgressMap.find(request);
246 if (requestProgressMapIt != requestProgressMap.end()) {
255 if (requestProgressMapIt != requestProgressMap.end()) {
247 requestProgressMapIt->second = progress;
256 requestProgressMapIt->second = progress;
248 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
257 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
249 << acqIdentifier << request.get() << progress;
258 << acqIdentifier << request.get() << progress;
250 }
259 }
251 else {
260 else {
252 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
261 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
253 << request.get() << progress;
262 << request.get() << progress;
254 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
263 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
255 }
264 }
256 }
265 }
257 else {
266 else {
258 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
267 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
259 << acqIdentifier << request.get() << progress;
268 << acqIdentifier << request.get() << progress;
260 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
269 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
261 requestProgressMap.insert(std::make_pair(request, progress));
270 requestProgressMap.insert(std::make_pair(request, progress));
262 m_AcqIdToRequestProgressMap.insert(
271 m_AcqIdToRequestProgressMap.insert(
263 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
272 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
264 }
273 }
265 }
274 }
General Comments 2
You need to be logged in to leave comments. Login now