##// END OF EJS Templates
Merge branch 'feature/NetworkController2' into develop
perrinel -
r390:1d8a5cf19c4c merge
parent child
Show More
@@ -24,7 +24,7 INCLUDE_DIRECTORIES(${SCIQLOP-PLUGIN_INCLUDE_DIR})
24 #
24 #
25 # Find Qt modules
25 # Find Qt modules
26 #
26 #
27 SCIQLOP_FIND_QT(Core)
27 SCIQLOP_FIND_QT(Core Network)
28
28
29 #
29 #
30 # Compile the library library
30 # Compile the library library
@@ -39,7 +39,7 ADD_LIBRARY(${SQPCORE_LIBRARY_NAME} ${MODULE_SOURCES})
39 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
39 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
40 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
40 set_property(TARGET ${SQPCORE_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
41 TARGET_LINK_LIBRARIES(${SQPCORE_LIBRARY_NAME})
41 TARGET_LINK_LIBRARIES(${SQPCORE_LIBRARY_NAME})
42 qt5_use_modules(${SQPCORE_LIBRARY_NAME} Core)
42 qt5_use_modules(${SQPCORE_LIBRARY_NAME} Core Network)
43
43
44 INSTALL(TARGETS ${SQPCORE_LIBRARY_NAME}
44 INSTALL(TARGETS ${SQPCORE_LIBRARY_NAME}
45 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
45 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
@@ -12,6 +12,8
12
12
13 class DataProviderParameters;
13 class DataProviderParameters;
14 class IDataSeries;
14 class IDataSeries;
15 class QNetworkReply;
16 class QNetworkRequest;
15
17
16 /**
18 /**
17 * @brief The IDataProvider interface aims to declare a data provider.
19 * @brief The IDataProvider interface aims to declare a data provider.
@@ -27,14 +29,32 class IDataProvider : public QObject {
27 public:
29 public:
28 virtual ~IDataProvider() noexcept = default;
30 virtual ~IDataProvider() noexcept = default;
29
31
30 virtual void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) = 0;
32 /**
33 * @brief requestDataLoading provide datas for the data identified by identifier for all
34 * SqpDateTime of dateTimeList
35 */
36 virtual void requestDataLoading(QUuid identifier, const QVector<SqpDateTime> &dateTimeList) = 0;
31
37
32 signals:
38 signals:
33 void dataProvided(QUuid token, std::shared_ptr<IDataSeries> dateSerie,
39 /**
40 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
41 * identified by identifier
42 */
43 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
34 const SqpDateTime &dateTime);
44 const SqpDateTime &dateTime);
45
46
47 /**
48 * @brief requestConstructed send a request for the data identified by identifier
49 * @callback is the methode call by the reply of the request when it is finished.
50 */
51 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
52 std::function<void(QNetworkReply *, QUuid)> callback);
35 };
53 };
36
54
37 // Required for using shared_ptr in signals/slots
55 // Required for using shared_ptr in signals/slots
38 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
56 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
57 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
58 std::function<void(QNetworkReply *, QUuid)>)
39
59
40 #endif // SCIQLOP_IDATAPROVIDER_H
60 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -3,11 +3,16
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5 #include <QObject>
5 #include <QObject>
6 #include <QUuid>
6
7
7 #include <Common/spimpl.h>
8 #include <Common/spimpl.h>
9 #include <functional>
8
10
9 Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController)
10
12
13 class QNetworkReply;
14 class QNetworkRequest;
15
11 /**
16 /**
12 * @brief The NetworkController class aims to handle all network connection of SciQlop.
17 * @brief The NetworkController class aims to handle all network connection of SciQlop.
13 */
18 */
@@ -16,10 +21,18 class NetworkController : public QObject {
16 public:
21 public:
17 explicit NetworkController(QObject *parent = 0);
22 explicit NetworkController(QObject *parent = 0);
18
23
19
20 void initialize();
24 void initialize();
21 void finalize();
25 void finalize();
22
26
27 public slots:
28 void onProcessRequested(const QNetworkRequest &request, QUuid identifier,
29 std::function<void(QNetworkReply *, QUuid)> callback);
30 void onReplyCanceled(QUuid identifier);
31
32 signals:
33 void replyFinished(QNetworkReply *reply, QUuid identifier);
34 void replyDownloadProgress(QUuid identifier);
35
23 private:
36 private:
24 void waitForFinish();
37 void waitForFinish();
25
38
@@ -1,13 +1,21
1 #include "Network/NetworkController.h"
1 #include "Network/NetworkController.h"
2
2
3 #include <QMutex>
3 #include <QMutex>
4 #include <QNetworkAccessManager>
5 #include <QNetworkReply>
6 #include <QNetworkRequest>
4 #include <QThread>
7 #include <QThread>
5
8
9 #include <unordered_map>
10
6 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
11 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
7
12
8 struct NetworkController::NetworkControllerPrivate {
13 struct NetworkController::NetworkControllerPrivate {
9 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
14 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
10 QMutex m_WorkingMutex;
15 QMutex m_WorkingMutex;
16
17 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
18 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
11 };
19 };
12
20
13 NetworkController::NetworkController(QObject *parent)
21 NetworkController::NetworkController(QObject *parent)
@@ -15,10 +23,46 NetworkController::NetworkController(QObject *parent)
15 {
23 {
16 }
24 }
17
25
26 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
27 std::function<void(QNetworkReply *, QUuid)> callback)
28 {
29 qCDebug(LOG_NetworkController()) << tr("NetworkController registered")
30 << QThread::currentThread();
31 auto reply = impl->m_AccessManager->get(request);
32
33 // Store the couple reply id
34 impl->m_NetworkReplyToVariableId[reply] = identifier;
35
36 auto onReplyFinished = [reply, this, identifier, callback]() {
37
38 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
39 << QThread::currentThread();
40 auto it = impl->m_NetworkReplyToVariableId.find(reply);
41 if (it != impl->m_NetworkReplyToVariableId.cend()) {
42 callback(reply, identifier);
43 }
44 };
45
46 auto onReplyDownloadProgress = [reply, this]() {
47
48 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyDownloadProgress")
49 << QThread::currentThread();
50 auto it = impl->m_NetworkReplyToVariableId.find(reply);
51 if (it != impl->m_NetworkReplyToVariableId.cend()) {
52 emit this->replyDownloadProgress(it->second);
53 }
54 };
55
56
57 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
58 connect(reply, &QNetworkReply::downloadProgress, this, onReplyDownloadProgress);
59 }
60
18 void NetworkController::initialize()
61 void NetworkController::initialize()
19 {
62 {
20 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
63 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
21 impl->m_WorkingMutex.lock();
64 impl->m_WorkingMutex.lock();
65 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
22 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
66 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
23 }
67 }
24
68
@@ -27,6 +71,17 void NetworkController::finalize()
27 impl->m_WorkingMutex.unlock();
71 impl->m_WorkingMutex.unlock();
28 }
72 }
29
73
74 void NetworkController::onReplyCanceled(QUuid identifier)
75 {
76 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
77
78 auto end = impl->m_NetworkReplyToVariableId.cend();
79 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
80 if (it != end) {
81 it->first->abort();
82 }
83 }
84
30 void NetworkController::waitForFinish()
85 void NetworkController::waitForFinish()
31 {
86 {
32 QMutexLocker locker{&impl->m_WorkingMutex};
87 QMutexLocker locker{&impl->m_WorkingMutex};
@@ -38,7 +38,7 struct VariableController::VariableControllerPrivate {
38
38
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 m_VariableToProviderMap;
40 m_VariableToProviderMap;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToToken;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
42 };
42 };
43
43
44 VariableController::VariableController(QObject *parent)
44 VariableController::VariableController(QObject *parent)
@@ -120,18 +120,18 void VariableController::createVariable(const QString &name,
120 /// in sciqlop
120 /// in sciqlop
121 auto dateTime = impl->m_TimeController->dateTime();
121 auto dateTime = impl->m_TimeController->dateTime();
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
123 auto token = QUuid::createUuid();
123 auto identifier = QUuid::createUuid();
124
124
125 // store the provider
125 // store the provider
126 impl->m_VariableToProviderMap[newVariable] = provider;
126 impl->m_VariableToProviderMap[newVariable] = provider;
127 impl->m_VariableToToken[newVariable] = token;
127 impl->m_VariableToIdentifier[newVariable] = identifier;
128
128
129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
130 QUuid token, auto dataSeriesAcquired, auto dateTimeToPutInCache)
130 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
131 {
131 {
132 if (auto variable = varW.lock()) {
132 if (auto variable = varW.lock()) {
133 auto varToken = impl->m_VariableToToken.at(variable);
133 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
134 if (varToken == token) {
134 if (varIdentifier == identifier) {
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 variable->setDataSeries(dataSeriesAcquired);
136 variable->setDataSeries(dataSeriesAcquired);
137 }
137 }
@@ -173,9 +173,9 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable
173
173
174 if (!dateTimeListNotInCache.empty()) {
174 if (!dateTimeListNotInCache.empty()) {
175 // Ask the provider for each data on the dateTimeListNotInCache
175 // Ask the provider for each data on the dateTimeListNotInCache
176 auto token = impl->m_VariableToToken.at(variable);
176 auto identifier = impl->m_VariableToIdentifier.at(variable);
177 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
177 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
178 token, std::move(dateTimeListNotInCache));
178 identifier, std::move(dateTimeListNotInCache));
179 }
179 }
180 else {
180 else {
181 emit variable->updated();
181 emit variable->updated();
@@ -78,7 +78,7 public:
78 SqpApplication::SqpApplication(int &argc, char **argv)
78 SqpApplication::SqpApplication(int &argc, char **argv)
79 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
79 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
80 {
80 {
81 qCInfo(LOG_SqpApplication()) << tr("SqpApplication construction");
81 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
82
82
83 connect(&impl->m_DataSourceControllerThread, &QThread::started,
83 connect(&impl->m_DataSourceControllerThread, &QThread::started,
84 impl->m_DataSourceController.get(), &DataSourceController::initialize);
84 impl->m_DataSourceController.get(), &DataSourceController::initialize);
@@ -12,6 +12,8
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
14
14
15 class QNetworkReply;
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 */
@@ -22,15 +24,15 public:
22 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
24 void requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList) override;
23
25
24 private:
26 private:
25 void retrieveData(QUuid token, const DataProviderParameters &parameters) const;
27 void retrieveData(QUuid token, const DataProviderParameters &parameters);
26
28
27 class AmdaProviderPrivate;
29 class AmdaProviderPrivate;
28 spimpl::unique_impl_ptr<AmdaProviderPrivate> impl;
30 spimpl::unique_impl_ptr<AmdaProviderPrivate> impl;
29
31
30 private slots:
32 // private slots:
31 void httpFinished() noexcept;
33 // void httpFinished(QNetworkReply *reply, QUuid dataId) noexcept;
32 void httpDownloadFinished() noexcept;
34 // void httpDownloadFinished(QNetworkReply *reply, QUuid dataId) noexcept;
33 void httpDownloadReadyRead() noexcept;
35 // void httpDownloadReadyRead(QNetworkReply *reply, QUuid dataId) noexcept;
34 };
36 };
35
37
36 #endif // SCIQLOP_AMDAPROVIDER_H
38 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -2,10 +2,14
2 #include "AmdaResultParser.h"
2 #include "AmdaResultParser.h"
3
3
4 #include <Data/DataProviderParameters.h>
4 #include <Data/DataProviderParameters.h>
5 #include <Network/NetworkController.h>
6 #include <SqpApplication.h>
7 #include <Variable/Variable.h>
5
8
6 #include <QNetworkAccessManager>
9 #include <QNetworkAccessManager>
7 #include <QNetworkReply>
10 #include <QNetworkReply>
8 #include <QTemporaryFile>
11 #include <QTemporaryFile>
12 #include <QThread>
9
13
10 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
14 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
11
15
@@ -30,18 +34,26 QString dateFormat(double sqpDateTime) noexcept
30 return dateTime.toString(AMDA_TIME_FORMAT);
34 return dateTime.toString(AMDA_TIME_FORMAT);
31 }
35 }
32
36
37
33 } // namespace
38 } // namespace
34
39
35 struct AmdaProvider::AmdaProviderPrivate {
40 struct AmdaProvider::AmdaProviderPrivate {
36 DataProviderParameters m_Params{};
41 DataProviderParameters m_Params{};
37 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
42 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
38 QNetworkReply *m_Reply{nullptr};
43 QNetworkReply *m_Reply{nullptr};
39 std::unique_ptr<QTemporaryFile> m_File{nullptr};
44 // std::unique_ptr<QTemporaryFile> m_File{nullptr};
40 QUuid m_Token;
45 QUuid m_Token;
41 };
46 };
42
47
43 AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()}
48 AmdaProvider::AmdaProvider() : impl{spimpl::make_unique_impl<AmdaProviderPrivate>()}
44 {
49 {
50 qCDebug(LOG_NetworkController()) << tr("AmdaProvider::AmdaProvider")
51 << QThread::currentThread();
52 if (auto app = sqpApp) {
53 auto &networkController = app->networkController();
54 connect(this, &AmdaProvider::requestConstructed, &networkController,
55 &NetworkController::onProcessRequested);
56 }
45 }
57 }
46
58
47 void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
59 void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &dateTimeList)
@@ -52,7 +64,7 void AmdaProvider::requestDataLoading(QUuid token, const QVector<SqpDateTime> &d
52 }
64 }
53 }
65 }
54
66
55 void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters &parameters) const
67 void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters &parameters)
56 {
68 {
57 // /////////// //
69 // /////////// //
58 // Creates URL //
70 // Creates URL //
@@ -64,71 +76,53 void AmdaProvider::retrieveData(QUuid token, const DataProviderParameters &param
64
76
65 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
77 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
66
78
67 // //////////////// //
79 auto tempFile = std::make_shared<QTemporaryFile>();
68 // Executes request //
69 // //////////////// //
70
71 impl->m_Token = token;
72 impl->m_Params = parameters;
73 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
74 impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{url});
75 connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpFinished);
76 }
77
80
78 void AmdaProvider::httpFinished() noexcept
79 {
80 // ////////////////////// //
81 // Gets download file url //
82 // ////////////////////// //
83
81
84 auto downloadFileUrl = QUrl{QString{impl->m_Reply->readAll()}};
82 // LAMBDA
83 auto httpDownloadFinished = [this, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
85
84
86 // ///////////////////////////////////// //
85 if (tempFile) {
87 // Executes request for downloading file //
86 auto replyReadAll = reply->readAll();
88 // ///////////////////////////////////// //
87 if (!replyReadAll.isEmpty()) {
89
88 tempFile->write(replyReadAll);
90 // Deletes old reply
91 impl->m_Reply->deleteLater();
92 impl->m_Reply = nullptr;
93
94 // Creates destination file
95 impl->m_File = std::make_unique<QTemporaryFile>();
96 if (impl->m_File->open()) {
97 qCDebug(LOG_AmdaProvider()) << "Temp file: " << impl->m_File->fileName();
98
99 // Executes request
100 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
101 impl->m_Reply = impl->m_AccessManager->get(QNetworkRequest{downloadFileUrl});
102 connect(impl->m_Reply, &QNetworkReply::finished, this,
103 &AmdaProvider::httpDownloadReadyRead);
104 connect(impl->m_Reply, &QNetworkReply::finished, this, &AmdaProvider::httpDownloadFinished);
105 }
89 }
106 }
90 tempFile->close();
107
108 void AmdaProvider::httpDownloadFinished() noexcept
109 {
110 if (impl->m_File) {
111 impl->m_File->close();
112
91
113 // Parse results file
92 // Parse results file
114 if (auto dataSeries = AmdaResultParser::readTxt(impl->m_File->fileName())) {
93 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
115 emit dataProvided(impl->m_Token, dataSeries, impl->m_Params.m_Time);
94 emit dataProvided(impl->m_Token, dataSeries, impl->m_Params.m_Time);
116 }
95 }
117 else {
96 else {
118 /// @todo ALX : debug
97 /// @todo ALX : debug
119 }
98 }
120
121 impl->m_File = nullptr;
122 }
99 }
123
100
124 // Deletes reply
101 // Deletes reply
125 impl->m_Reply->deleteLater();
102 reply->deleteLater();
126 impl->m_Reply = nullptr;
103 reply = nullptr;
127 }
104 };
105 auto httpFinishedLambda = [this, httpDownloadFinished, tempFile](QNetworkReply *reply,
106 QUuid dataId) noexcept {
128
107
129 void AmdaProvider::httpDownloadReadyRead() noexcept
108 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
130 {
109 // Deletes old reply
131 if (impl->m_File) {
110 reply->deleteLater();
132 impl->m_File->write(impl->m_Reply->readAll());
111
112 // Executes request for downloading file //
113
114 // Creates destination file
115 if (tempFile->open()) {
116 // Executes request
117 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId, httpDownloadFinished);
133 }
118 }
119 };
120
121 // //////////////// //
122 // Executes request //
123 // //////////////// //
124
125 impl->m_Token = token;
126 impl->m_Params = parameters;
127 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
134 }
128 }
General Comments 0
You need to be logged in to leave comments. Login now