##// END OF EJS Templates
Adds "hybrid" server mode...
Alexandre Leroux -
r1151:7dc72cc510ff
parent child
Show More
@@ -1,72 +1,73
1
1
2 if(BUILD_TESTS)
2 if(BUILD_TESTS)
3 INCLUDE ("cmake/sciqlop_code_coverage.cmake")
3 INCLUDE ("cmake/sciqlop_code_coverage.cmake")
4 APPEND_COVERAGE_COMPILER_FLAGS()
4 APPEND_COVERAGE_COMPILER_FLAGS()
5 endif(BUILD_TESTS)
5 endif(BUILD_TESTS)
6
6
7 #
7 #
8 # Compile the diffents modules
8 # Compile the diffents modules
9 #
9 #
10 set(sciqlop-plugin_DIR "${CMAKE_SOURCE_DIR}/plugin/cmake")
10 set(sciqlop-plugin_DIR "${CMAKE_SOURCE_DIR}/plugin/cmake")
11 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-plugin_DIR}")
11 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-plugin_DIR}")
12 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugin")
12 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugin")
13
13
14 set(sciqlop-core_DIR "${CMAKE_SOURCE_DIR}/core/cmake")
14 set(sciqlop-core_DIR "${CMAKE_SOURCE_DIR}/core/cmake")
15 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-core_DIR}")
15 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-core_DIR}")
16 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
16 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
17
17
18 set(sciqlop-gui_DIR "${CMAKE_SOURCE_DIR}/gui/cmake")
18 set(sciqlop-gui_DIR "${CMAKE_SOURCE_DIR}/gui/cmake")
19 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-gui_DIR}")
19 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-gui_DIR}")
20 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/gui")
20 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/gui")
21
21
22 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/app")
22 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/app")
23
23
24 OPTION (BUILD_PLUGINS "Build the plugins" OFF)
24 OPTION (BUILD_PLUGINS "Build the plugins" OFF)
25 IF(BUILD_PLUGINS)
25 IF(BUILD_PLUGINS)
26 set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake")
26 set(sciqlop-mockplugin_DIR "${CMAKE_SOURCE_DIR}/plugins/mockplugin/cmake")
27 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}")
27 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-mockplugin_DIR}")
28 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin")
28 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/mockplugin")
29
29
30 # Sets AMDA server that will be used during execution.
30 # Sets AMDA server that will be used during execution.
31 # Available values are:
31 # Available values are:
32 # - "default": default AMDA server
32 # - "default": default AMDA server
33 # - "amdatest": AMDA test server
33 # - "amdatest": AMDA test server
34 # - "hybrid": use both the default server and the test server (the server used is relative to each product, according to its "server" property in the JSON file)
34 # Any other value will lead to the use of the default server
35 # Any other value will lead to the use of the default server
35 ADD_DEFINITIONS(-DSCIQLOP_AMDA_SERVER="default")
36 ADD_DEFINITIONS(-DSCIQLOP_AMDA_SERVER="hybrid")
36
37
37 set(sciqlop-amda_DIR "${CMAKE_SOURCE_DIR}/plugins/amda/cmake")
38 set(sciqlop-amda_DIR "${CMAKE_SOURCE_DIR}/plugins/amda/cmake")
38 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-amda_DIR}")
39 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${sciqlop-amda_DIR}")
39 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/amda")
40 ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/plugins/amda")
40
41
41 # Temporary target to copy to plugins dir
42 # Temporary target to copy to plugins dir
42 find_package(sciqlop-mockplugin)
43 find_package(sciqlop-mockplugin)
43 find_package(sciqlop-amda)
44 find_package(sciqlop-amda)
44 ADD_CUSTOM_TARGET(plugins
45 ADD_CUSTOM_TARGET(plugins
45 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}"
46 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-MOCKPLUGIN_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-MOCKPLUGIN_LIBRARIES_NAME}"
46 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-AMDA_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-AMDA_LIBRARIES_NAME}"
47 COMMAND ${CMAKE_COMMAND} -E copy ${SCIQLOP-AMDA_LIBRARIES} "${LIBRARY_OUTPUT_PATH}/plugins/${SCIQLOP-AMDA_LIBRARIES_NAME}"
47 )
48 )
48 ENDIF(BUILD_PLUGINS)
49 ENDIF(BUILD_PLUGINS)
49
50
50 # LOGGER
51 # LOGGER
51 set(QTLOGGING_INI_FILE "${CMAKE_SOURCE_DIR}/config/QtProject/qtlogging.ini")
52 set(QTLOGGING_INI_FILE "${CMAKE_SOURCE_DIR}/config/QtProject/qtlogging.ini")
52 FILE(COPY ${QTLOGGING_INI_FILE} DESTINATION ${CONFIG_OUTPUT_PATH})
53 FILE(COPY ${QTLOGGING_INI_FILE} DESTINATION ${CONFIG_OUTPUT_PATH})
53
54
54
55
55 #
56 #
56 # Code formatting
57 # Code formatting
57 #
58 #
58 # Vera++ exclusion files
59 # Vera++ exclusion files
59 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/formatting/vera-exclusions/exclusions.txt)
60 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/formatting/vera-exclusions/exclusions.txt)
60 #SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
61 #SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
61 INCLUDE ("cmake/sciqlop_formatting.cmake")
62 INCLUDE ("cmake/sciqlop_formatting.cmake")
62
63
63 #
64 #
64 # Documentation generation
65 # Documentation generation
65 #
66 #
66 INCLUDE ("cmake/sciqlop_doxygen.cmake")
67 INCLUDE ("cmake/sciqlop_doxygen.cmake")
67
68
68 #
69 #
69 # Source code analysis
70 # Source code analysis
70 #
71 #
71 INCLUDE ("cmake/sciqlop_code_analysis.cmake")
72 INCLUDE ("cmake/sciqlop_code_analysis.cmake")
72 INCLUDE ("cmake/sciqlop_code_cppcheck.cmake")
73 INCLUDE ("cmake/sciqlop_code_cppcheck.cmake")
@@ -1,44 +1,45
1 project('SciQLOP', 'cpp',default_options : ['cpp_std=c++14'])
1 project('SciQLOP', 'cpp',default_options : ['cpp_std=c++14'])
2
2
3 qt5 = import('qt5')
3 qt5 = import('qt5')
4 qt5core = dependency('qt5', modules : 'Core')
4 qt5core = dependency('qt5', modules : 'Core')
5 qt5widgets = dependency('qt5', modules : 'Widgets')
5 qt5widgets = dependency('qt5', modules : 'Widgets')
6 qt5gui = dependency('qt5', modules : 'Gui')
6 qt5gui = dependency('qt5', modules : 'Gui')
7 qt5svg = dependency('qt5', modules : 'Svg')
7 qt5svg = dependency('qt5', modules : 'Svg')
8 qt5xml = dependency('qt5', modules : 'Xml')
8 qt5xml = dependency('qt5', modules : 'Xml')
9 qt5network = dependency('qt5', modules : 'Network')
9 qt5network = dependency('qt5', modules : 'Network')
10 qt5printsupport = dependency('qt5', modules : 'PrintSupport')
10 qt5printsupport = dependency('qt5', modules : 'PrintSupport')
11 qt5test = dependency('qt5', modules : 'Test')
11 qt5test = dependency('qt5', modules : 'Test')
12
12
13 moc = find_program('moc-qt5','moc')
13 moc = find_program('moc-qt5','moc')
14 rcc = find_program('rcc-qt5','rcc')
14 rcc = find_program('rcc-qt5','rcc')
15
15
16 if build_machine.system()=='darwin'
16 if build_machine.system()=='darwin'
17 add_global_link_arguments('-headerpad_max_install_names', language : 'cpp')
17 add_global_link_arguments('-headerpad_max_install_names', language : 'cpp')
18 install_data('build_cfg/mac/sciqlopLOGO.icns', install_dir : 'Contents/Resources')
18 install_data('build_cfg/mac/sciqlopLOGO.icns', install_dir : 'Contents/Resources')
19 install_data('build_cfg/mac/Info.plist', install_dir : 'Contents')
19 install_data('build_cfg/mac/Info.plist', install_dir : 'Contents')
20 meson.add_install_script('build_cfg/mac/install_script.sh')
20 meson.add_install_script('build_cfg/mac/install_script.sh')
21 elif host_machine.system()=='windows'
21 elif host_machine.system()=='windows'
22 meson.add_install_script('build_cfg/windows/install_script.sh')
22 meson.add_install_script('build_cfg/windows/install_script.sh')
23 endif
23 endif
24
24
25 # Sets AMDA server that will be used during execution.
25 # Sets AMDA server that will be used during execution.
26 # Available values are:
26 # Available values are:
27 # - "default": default AMDA server
27 # - "default": default AMDA server
28 # - "amdatest": AMDA test server
28 # - "amdatest": AMDA test server
29 # - "hybrid": use both the default server and the test server (the server used is relative to each product, according to its "server" property in the JSON file)
29 # Any other value will lead to the use of the default server
30 # Any other value will lead to the use of the default server
30 add_project_arguments('-DSCIQLOP_AMDA_SERVER="default"', language : 'cpp')
31 add_project_arguments('-DSCIQLOP_AMDA_SERVER="hybrid"', language : 'cpp')
31
32
32 subdir('core')
33 subdir('core')
33 subdir('gui')
34 subdir('gui')
34 subdir('app')
35 subdir('app')
35 subdir('plugins')
36 subdir('plugins')
36
37
37 cppcheck = find_program('cppcheck', required : false)
38 cppcheck = find_program('cppcheck', required : false)
38
39
39 if cppcheck.found()
40 if cppcheck.found()
40 run_target('cppcheck',
41 run_target('cppcheck',
41 command : [cppcheck, '--enable=all',
42 command : [cppcheck, '--enable=all',
42 '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]
43 '--project=' + join_paths(meson.build_root(), 'compile_commands.json')]
43 )
44 )
44 endif
45 endif
@@ -1,33 +1,35
1 #ifndef SCIQLOP_AMDASERVER_H
1 #ifndef SCIQLOP_AMDASERVER_H
2 #define SCIQLOP_AMDASERVER_H
2 #define SCIQLOP_AMDASERVER_H
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5
5
6 #include <memory>
6 #include <memory>
7
7
8 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaServer)
8 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaServer)
9
9
10 // Directive used to determine the active AMDA server
10 // Directive used to determine the active AMDA server
11 #ifndef SCIQLOP_AMDA_SERVER
11 #ifndef SCIQLOP_AMDA_SERVER
12 #define SCIQLOP_AMDA_SERVER "default"
12 #define SCIQLOP_AMDA_SERVER "default"
13 #endif
13 #endif
14
14
15 /**
15 /**
16 * @brief The AmdaServer class represents the server used to retrieve AMDA data (singleton).
16 * @brief The AmdaServer class represents the server used to retrieve AMDA data (singleton).
17 *
17 *
18 * The server instance is initialized at compile time, as defined by the AMDA_SERVER value.
18 * The server instance is initialized at compile time, as defined by the AMDA_SERVER value.
19 */
19 */
20 class AmdaServer {
20 class AmdaServer {
21 public:
21 public:
22 /// @return the unique instance of the AMDA server
22 /// @return the unique instance of the AMDA server
23 static AmdaServer &instance();
23 static AmdaServer &instance();
24
24
25 virtual ~AmdaServer() noexcept = default;
25 virtual ~AmdaServer() noexcept = default;
26
26
27 /// @return the name of the server
27 /// @return the name of the server
28 virtual QString name() const = 0;
28 virtual QString name() const = 0;
29
30 /// @param properties used to generate url
29 /// @return the url of the server (used to retrieve data)
31 /// @return the url of the server (used to retrieve data)
30 virtual QString url() const = 0;
32 virtual QString url(const QVariantHash &properties = {}) const = 0;
31 };
33 };
32
34
33 #endif // SCIQLOP_AMDASERVER_H
35 #endif // SCIQLOP_AMDASERVER_H
@@ -1,287 +1,288
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 #include "AmdaServer.h"
4 #include "AmdaServer.h"
5
5
6 #include <Common/DateUtils.h>
6 #include <Common/DateUtils.h>
7 #include <Data/DataProviderParameters.h>
7 #include <Data/DataProviderParameters.h>
8 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
9 #include <SqpApplication.h>
9 #include <SqpApplication.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11
11
12 #include <QNetworkAccessManager>
12 #include <QNetworkAccessManager>
13 #include <QNetworkReply>
13 #include <QNetworkReply>
14 #include <QTemporaryFile>
14 #include <QTemporaryFile>
15 #include <QThread>
15 #include <QThread>
16
16
17 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
18
18
19 namespace {
19 namespace {
20
20
21 /// URL format for a request on AMDA server. The parameters are as follows:
21 /// URL format for a request on AMDA server. The parameters are as follows:
22 /// - %1: server URL
22 /// - %1: server URL
23 /// - %2: start date
23 /// - %2: start date
24 /// - %3: end date
24 /// - %3: end date
25 /// - %4: parameter id
25 /// - %4: parameter id
26 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
26 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
27 const auto AMDA_URL_FORMAT = QStringLiteral(
27 const auto AMDA_URL_FORMAT = QStringLiteral(
28 "http://%1/php/rest/"
28 "http://%1/php/rest/"
29 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
29 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
30 "timeFormat=ISO8601&gzip=0");
30 "timeFormat=ISO8601&gzip=0");
31
31
32 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
32 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
33 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
33 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
34
34
35 /// Formats a time to a date that can be passed in URL
35 /// Formats a time to a date that can be passed in URL
36 QString dateFormat(double sqpRange) noexcept
36 QString dateFormat(double sqpRange) noexcept
37 {
37 {
38 auto dateTime = DateUtils::dateTime(sqpRange);
38 auto dateTime = DateUtils::dateTime(sqpRange);
39 return dateTime.toString(AMDA_TIME_FORMAT);
39 return dateTime.toString(AMDA_TIME_FORMAT);
40 }
40 }
41
41
42 AmdaResultParser::ValueType valueType(const QString &valueType)
42 AmdaResultParser::ValueType valueType(const QString &valueType)
43 {
43 {
44 if (valueType == QStringLiteral("scalar")) {
44 if (valueType == QStringLiteral("scalar")) {
45 return AmdaResultParser::ValueType::SCALAR;
45 return AmdaResultParser::ValueType::SCALAR;
46 }
46 }
47 else if (valueType == QStringLiteral("spectrogram")) {
47 else if (valueType == QStringLiteral("spectrogram")) {
48 return AmdaResultParser::ValueType::SPECTROGRAM;
48 return AmdaResultParser::ValueType::SPECTROGRAM;
49 }
49 }
50 else if (valueType == QStringLiteral("vector")) {
50 else if (valueType == QStringLiteral("vector")) {
51 return AmdaResultParser::ValueType::VECTOR;
51 return AmdaResultParser::ValueType::VECTOR;
52 }
52 }
53 else {
53 else {
54 return AmdaResultParser::ValueType::UNKNOWN;
54 return AmdaResultParser::ValueType::UNKNOWN;
55 }
55 }
56 }
56 }
57
57
58 } // namespace
58 } // namespace
59
59
60 AmdaProvider::AmdaProvider()
60 AmdaProvider::AmdaProvider()
61 {
61 {
62 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
62 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
63 if (auto app = sqpApp) {
63 if (auto app = sqpApp) {
64 auto &networkController = app->networkController();
64 auto &networkController = app->networkController();
65 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
65 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
66 std::function<void(QNetworkReply *, QUuid)>)),
66 std::function<void(QNetworkReply *, QUuid)>)),
67 &networkController,
67 &networkController,
68 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
68 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
69 std::function<void(QNetworkReply *, QUuid)>)));
69 std::function<void(QNetworkReply *, QUuid)>)));
70
70
71
71
72 connect(&sqpApp->networkController(),
72 connect(&sqpApp->networkController(),
73 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
73 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
74 this,
74 this,
75 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
75 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
76 }
76 }
77 }
77 }
78
78
79 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
79 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
80 {
80 {
81 // No copy is made in the clone
81 // No copy is made in the clone
82 return std::make_shared<AmdaProvider>();
82 return std::make_shared<AmdaProvider>();
83 }
83 }
84
84
85 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
85 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
86 {
86 {
87 // NOTE: Try to use multithread if possible
87 // NOTE: Try to use multithread if possible
88 const auto times = parameters.m_Times;
88 const auto times = parameters.m_Times;
89 const auto data = parameters.m_Data;
89 const auto data = parameters.m_Data;
90 for (const auto &dateTime : qAsConst(times)) {
90 for (const auto &dateTime : qAsConst(times)) {
91 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
91 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::requestDataLoading ") << acqIdentifier
92 << dateTime;
92 << dateTime;
93 this->retrieveData(acqIdentifier, dateTime, data);
93 this->retrieveData(acqIdentifier, dateTime, data);
94
94
95
95
96 // TORM when AMDA will support quick asynchrone request
96 // TORM when AMDA will support quick asynchrone request
97 QThread::msleep(1000);
97 QThread::msleep(1000);
98 }
98 }
99 }
99 }
100
100
101 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
101 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
102 {
102 {
103 if (auto app = sqpApp) {
103 if (auto app = sqpApp) {
104 auto &networkController = app->networkController();
104 auto &networkController = app->networkController();
105 networkController.onReplyCanceled(acqIdentifier);
105 networkController.onReplyCanceled(acqIdentifier);
106 }
106 }
107 }
107 }
108
108
109 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
109 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
110 std::shared_ptr<QNetworkRequest> networkRequest,
110 std::shared_ptr<QNetworkRequest> networkRequest,
111 double progress)
111 double progress)
112 {
112 {
113 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
113 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
114 << networkRequest.get() << progress;
114 << networkRequest.get() << progress;
115 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
115 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
116 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
116 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
117
117
118 // Update the progression for the current request
118 // Update the progression for the current request
119 auto requestPtr = networkRequest;
119 auto requestPtr = networkRequest;
120 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
120 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
121
121
122 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
122 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
123 auto requestProgressMapEnd = requestProgressMap.end();
123 auto requestProgressMapEnd = requestProgressMap.end();
124 auto requestProgressMapIt
124 auto requestProgressMapIt
125 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
125 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
126
126
127 if (requestProgressMapIt != requestProgressMapEnd) {
127 if (requestProgressMapIt != requestProgressMapEnd) {
128 requestProgressMapIt->second = progress;
128 requestProgressMapIt->second = progress;
129 }
129 }
130 else {
130 else {
131 // This case can happened when a progression is send after the request has been
131 // This case can happened when a progression is send after the request has been
132 // finished.
132 // finished.
133 // Generaly the case when aborting a request
133 // Generaly the case when aborting a request
134 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
134 qCDebug(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress") << acqIdentifier
135 << networkRequest.get() << progress;
135 << networkRequest.get() << progress;
136 }
136 }
137
137
138 // Compute the current final progress and notify it
138 // Compute the current final progress and notify it
139 double finalProgress = 0.0;
139 double finalProgress = 0.0;
140
140
141 auto fraq = requestProgressMap.size();
141 auto fraq = requestProgressMap.size();
142
142
143 for (auto requestProgress : requestProgressMap) {
143 for (auto requestProgress : requestProgressMap) {
144 finalProgress += requestProgress.second;
144 finalProgress += requestProgress.second;
145 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
145 qCDebug(LOG_AmdaProvider()) << tr("Current final progress without fraq:")
146 << finalProgress << requestProgress.second;
146 << finalProgress << requestProgress.second;
147 }
147 }
148
148
149 if (fraq > 0) {
149 if (fraq > 0) {
150 finalProgress = finalProgress / fraq;
150 finalProgress = finalProgress / fraq;
151 }
151 }
152
152
153 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
153 qCDebug(LOG_AmdaProvider()) << tr("Current final progress: ") << fraq << finalProgress;
154 emit dataProvidedProgress(acqIdentifier, finalProgress);
154 emit dataProvidedProgress(acqIdentifier, finalProgress);
155 }
155 }
156 else {
156 else {
157 // This case can happened when a progression is send after the request has been finished.
157 // This case can happened when a progression is send after the request has been finished.
158 // Generaly the case when aborting a request
158 // Generaly the case when aborting a request
159 emit dataProvidedProgress(acqIdentifier, 100.0);
159 emit dataProvidedProgress(acqIdentifier, 100.0);
160 }
160 }
161 }
161 }
162
162
163 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
163 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
164 {
164 {
165 // Retrieves product ID from data: if the value is invalid, no request is made
165 // Retrieves product ID from data: if the value is invalid, no request is made
166 auto productId = data.value(AMDA_XML_ID_KEY).toString();
166 auto productId = data.value(AMDA_XML_ID_KEY).toString();
167 if (productId.isNull()) {
167 if (productId.isNull()) {
168 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
168 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
169 return;
169 return;
170 }
170 }
171
171
172 // Retrieves the data type that determines whether the expected format for the result file is
172 // Retrieves the data type that determines whether the expected format for the result file is
173 // scalar, vector...
173 // scalar, vector...
174 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
174 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
175
175
176 // /////////// //
176 // /////////// //
177 // Creates URL //
177 // Creates URL //
178 // /////////// //
178 // /////////// //
179
179
180 auto startDate = dateFormat(dateTime.m_TStart);
180 auto startDate = dateFormat(dateTime.m_TStart);
181 auto endDate = dateFormat(dateTime.m_TEnd);
181 auto endDate = dateFormat(dateTime.m_TEnd);
182
182
183 auto url = QUrl{
183 QVariantHash urlProperties{{AMDA_SERVER_KEY, data.value(AMDA_SERVER_KEY)}};
184 QString{AMDA_URL_FORMAT}.arg(AmdaServer::instance().url(), startDate, endDate, productId)};
184 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties),
185 startDate, endDate, productId)};
185 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
186 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
186 auto tempFile = std::make_shared<QTemporaryFile>();
187 auto tempFile = std::make_shared<QTemporaryFile>();
187
188
188 // LAMBDA
189 // LAMBDA
189 auto httpDownloadFinished = [this, dateTime, tempFile,
190 auto httpDownloadFinished = [this, dateTime, tempFile,
190 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
191 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
191
192
192 // Don't do anything if the reply was abort
193 // Don't do anything if the reply was abort
193 if (reply->error() == QNetworkReply::NoError) {
194 if (reply->error() == QNetworkReply::NoError) {
194
195
195 if (tempFile) {
196 if (tempFile) {
196 auto replyReadAll = reply->readAll();
197 auto replyReadAll = reply->readAll();
197 if (!replyReadAll.isEmpty()) {
198 if (!replyReadAll.isEmpty()) {
198 tempFile->write(replyReadAll);
199 tempFile->write(replyReadAll);
199 }
200 }
200 tempFile->close();
201 tempFile->close();
201
202
202 // Parse results file
203 // Parse results file
203 if (auto dataSeries
204 if (auto dataSeries
204 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
205 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
205 emit dataProvided(dataId, dataSeries, dateTime);
206 emit dataProvided(dataId, dataSeries, dateTime);
206 }
207 }
207 else {
208 else {
208 /// @todo ALX : debug
209 /// @todo ALX : debug
209 emit dataProvidedFailed(dataId);
210 emit dataProvidedFailed(dataId);
210 }
211 }
211 }
212 }
212 m_AcqIdToRequestProgressMap.erase(dataId);
213 m_AcqIdToRequestProgressMap.erase(dataId);
213 }
214 }
214 else {
215 else {
215 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
216 qCCritical(LOG_AmdaProvider()) << tr("httpDownloadFinished ERROR");
216 emit dataProvidedFailed(dataId);
217 emit dataProvidedFailed(dataId);
217 }
218 }
218
219
219 };
220 };
220 auto httpFinishedLambda
221 auto httpFinishedLambda
221 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
222 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
222
223
223 // Don't do anything if the reply was abort
224 // Don't do anything if the reply was abort
224 if (reply->error() == QNetworkReply::NoError) {
225 if (reply->error() == QNetworkReply::NoError) {
225 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
226 auto downloadFileUrl = QUrl{QString{reply->readAll()}.trimmed()};
226
227
227 qCInfo(LOG_AmdaProvider())
228 qCInfo(LOG_AmdaProvider())
228 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
229 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
229 // Executes request for downloading file //
230 // Executes request for downloading file //
230
231
231 // Creates destination file
232 // Creates destination file
232 if (tempFile->open()) {
233 if (tempFile->open()) {
233 // Executes request and store the request for progression
234 // Executes request and store the request for progression
234 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
235 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
235 updateRequestProgress(dataId, request, 0.0);
236 updateRequestProgress(dataId, request, 0.0);
236 emit requestConstructed(request, dataId, httpDownloadFinished);
237 emit requestConstructed(request, dataId, httpDownloadFinished);
237 }
238 }
238 else {
239 else {
239 emit dataProvidedFailed(dataId);
240 emit dataProvidedFailed(dataId);
240 }
241 }
241 }
242 }
242 else {
243 else {
243 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
244 qCCritical(LOG_AmdaProvider()) << tr("httpFinishedLambda ERROR");
244 m_AcqIdToRequestProgressMap.erase(dataId);
245 m_AcqIdToRequestProgressMap.erase(dataId);
245 emit dataProvidedFailed(dataId);
246 emit dataProvidedFailed(dataId);
246 }
247 }
247 };
248 };
248
249
249 // //////////////// //
250 // //////////////// //
250 // Executes request //
251 // Executes request //
251 // //////////////// //
252 // //////////////// //
252
253
253 auto request = std::make_shared<QNetworkRequest>(url);
254 auto request = std::make_shared<QNetworkRequest>(url);
254 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
255 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
255 updateRequestProgress(token, request, 0.0);
256 updateRequestProgress(token, request, 0.0);
256
257
257 emit requestConstructed(request, token, httpFinishedLambda);
258 emit requestConstructed(request, token, httpFinishedLambda);
258 }
259 }
259
260
260 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
261 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
261 std::shared_ptr<QNetworkRequest> request, double progress)
262 std::shared_ptr<QNetworkRequest> request, double progress)
262 {
263 {
263 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
264 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress request") << request.get();
264 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
265 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
265 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
266 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
266 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
267 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
267 auto requestProgressMapIt = requestProgressMap.find(request);
268 auto requestProgressMapIt = requestProgressMap.find(request);
268 if (requestProgressMapIt != requestProgressMap.end()) {
269 if (requestProgressMapIt != requestProgressMap.end()) {
269 requestProgressMapIt->second = progress;
270 requestProgressMapIt->second = progress;
270 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
271 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
271 << acqIdentifier << request.get() << progress;
272 << acqIdentifier << request.get() << progress;
272 }
273 }
273 else {
274 else {
274 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
275 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
275 << request.get() << progress;
276 << request.get() << progress;
276 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
277 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
277 }
278 }
278 }
279 }
279 else {
280 else {
280 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
281 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
281 << acqIdentifier << request.get() << progress;
282 << acqIdentifier << request.get() << progress;
282 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
283 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
283 requestProgressMap.insert(std::make_pair(request, progress));
284 requestProgressMap.insert(std::make_pair(request, progress));
284 m_AcqIdToRequestProgressMap.insert(
285 m_AcqIdToRequestProgressMap.insert(
285 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
286 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
286 }
287 }
287 }
288 }
@@ -1,45 +1,78
1 #include "AmdaServer.h"
1 #include "AmdaServer.h"
2
2
3 #include "AmdaDefs.h"
4
3 Q_LOGGING_CATEGORY(LOG_AmdaServer, "AmdaServer")
5 Q_LOGGING_CATEGORY(LOG_AmdaServer, "AmdaServer")
4
6
5 namespace {
7 namespace {
6
8
9 /// URL of the default AMDA server
10 const auto AMDA_DEFAULT_SERVER_URL = QStringLiteral("amda.irap.omp.eu");
11
12 /// URL of the AMDA test server
13 const auto AMDA_TEST_SERVER_URL = QStringLiteral("amdatest.irap.omp.eu");
14
7 /// Default AMDA server
15 /// Default AMDA server
8 struct AmdaDefaultServer : public AmdaServer {
16 struct AmdaDefaultServer : public AmdaServer {
9 public:
17 public:
10 QString name() const override { return QStringLiteral("AMDA (default)"); }
18 QString name() const override { return QStringLiteral("AMDA (default)"); }
11 QString url() const override { return QStringLiteral("amda.irap.omp.eu"); }
19 QString url(const QVariantHash &properties) const override
20 {
21 Q_UNUSED(properties);
22 return AMDA_DEFAULT_SERVER_URL;
23 }
12 };
24 };
13
25
14 /// Alternative AMDA server (tests)
26 /// Alternative AMDA server (tests)
15 struct AmdaTestServer : public AmdaServer {
27 struct AmdaTestServer : public AmdaServer {
16 public:
28 public:
17 QString name() const override { return QStringLiteral("AMDA (test)"); }
29 QString name() const override { return QStringLiteral("AMDA (test)"); }
18 QString url() const override { return QStringLiteral("amdatest.irap.omp.eu"); }
30 QString url(const QVariantHash &properties) const override
31 {
32 Q_UNUSED(properties);
33 return AMDA_TEST_SERVER_URL;
34 }
35 };
36
37 /// Hybrid AMDA server: use both of default and test server.
38 /// The server used is relative to each product for which to retrieve url, according to its "server"
39 /// property
40 struct AmdaHybridServer : public AmdaServer {
41 public:
42 QString name() const override { return QStringLiteral("AMDA (hybrid)"); }
43 QString url(const QVariantHash &properties) const override
44 {
45 // Reads "server" property to determine which server url to use
46 auto server = properties.value(AMDA_SERVER_KEY).toString();
47 return server == QString{"amdatest"} ? AMDA_TEST_SERVER_URL : AMDA_DEFAULT_SERVER_URL;
48 }
19 };
49 };
20
50
21 /// @return an AMDA server instance created from the name of the server passed in parameter. If the
51 /// @return an AMDA server instance created from the name of the server passed in parameter. If the
22 /// name does not match any known server, a default server instance is created
52 /// name does not match any known server, a default server instance is created
23 std::unique_ptr<AmdaServer> createInstance(const QString &server)
53 std::unique_ptr<AmdaServer> createInstance(const QString &server)
24 {
54 {
25 if (server == QString{"amdatest"}) {
55 if (server == QString{"amdatest"}) {
26 return std::make_unique<AmdaTestServer>();
56 return std::make_unique<AmdaTestServer>();
27 }
57 }
58 else if (server == QString{"hybrid"}) {
59 return std::make_unique<AmdaHybridServer>();
60 }
28 else {
61 else {
29 if (server != QString{"default"}) {
62 if (server != QString{"default"}) {
30 qCWarning(LOG_AmdaServer())
63 qCWarning(LOG_AmdaServer())
31 << QObject::tr("Unknown server '%1': default AMDA server will be used").arg(server);
64 << QObject::tr("Unknown server '%1': default AMDA server will be used").arg(server);
32 }
65 }
33
66
34 return std::make_unique<AmdaDefaultServer>();
67 return std::make_unique<AmdaDefaultServer>();
35 }
68 }
36 }
69 }
37
70
38 } // namespace
71 } // namespace
39
72
40 AmdaServer &AmdaServer::instance()
73 AmdaServer &AmdaServer::instance()
41 {
74 {
42 // Creates instance depending on the SCIQLOP_AMDA_SERVER value at compile time
75 // Creates instance depending on the SCIQLOP_AMDA_SERVER value at compile time
43 static auto instance = createInstance(SCIQLOP_AMDA_SERVER);
76 static auto instance = createInstance(SCIQLOP_AMDA_SERVER);
44 return *instance;
77 return *instance;
45 }
78 }
General Comments 0
You need to be logged in to leave comments. Login now