##// END OF EJS Templates
Removed old IDataProvider interface, added small tweak in downloader...
jeandet -
r28:a05b0ab23493
parent child
Show More
@@ -1,112 +1,55
1 #ifndef SCIQLOP_IDATAPROVIDER_H
1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5 #include <Common/deprecate.h>
5 #include <Common/deprecate.h>
6
6
7 #include <memory>
7 #include <memory>
8
8
9 #include <QObject>
9 #include <QObject>
10 #include <QUuid>
10 #include <QUuid>
11
11
12 #include <Common/MetaTypes.h>
12 #include <Common/MetaTypes.h>
13
13
14 #include <Data/DateTimeRange.h>
14 #include <Data/DateTimeRange.h>
15
15
16 #include <functional>
16 #include <functional>
17
17
18 class DataProviderParameters;
18 class DataProviderParameters;
19 class IDataSeries;
19 class IDataSeries;
20 DEPRECATE(
20 DEPRECATE(
21 class QNetworkReply;
21 class QNetworkReply;
22 class QNetworkRequest;
22 class QNetworkRequest;
23 )
23 )
24
24
25 /**
25 /**
26 * @brief The IDataProvider interface aims to declare a data provider.
26 * @brief The IDataProvider interface aims to declare a data provider.
27 *
27 *
28 * A data provider is an entity that generates data and returns it according to various parameters
28 * A data provider is an entity that generates data and returns it according to various parameters
29 * (time interval, product to retrieve the data, etc.)
29 * (time interval, product to retrieve the data, etc.)
30 * Since its client mihgt use it from different threads it has to be either stateless and/or thread safe
30 *
31 *
31 * @sa IDataSeries
32 * @sa IDataSeries
32 */
33 */
33 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
34 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
34
35
35 Q_OBJECT
36 Q_OBJECT
36 public:
37 public:
37 virtual ~IDataProvider() noexcept = default;
38 virtual ~IDataProvider() noexcept = default;
38 virtual std::shared_ptr<IDataProvider> clone() const = 0;
39 virtual std::shared_ptr<IDataProvider> clone() const = 0;
39
40
40 DEPRECATE(
41 /**
42 * @brief requestDataLoading provide datas for the data identified by acqIdentifier and
43 * parameters
44 */
45 virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
46 = 0;
47 )
48
49 // Synchronous call -> asyncGetData may be written for asynchronous get
41 // Synchronous call -> asyncGetData may be written for asynchronous get
50 virtual IDataSeries* getData(const DataProviderParameters &parameters)
42 virtual IDataSeries* getData(const DataProviderParameters &parameters) = 0;
51 {
52 Q_UNUSED(parameters);
53 return nullptr;
54 }
55
56
57 DEPRECATE(
58 /**
59 * @brief requestDataAborting stop data loading of the data identified by acqIdentifier
60 */
61 virtual void requestDataAborting(QUuid acqIdentifier) = 0;
62 )
63
64 virtual void abort(QUuid requestID){Q_UNUSED(requestID);}
65
43
66 signals:
44 signals:
67 DEPRECATE(
68 /**
69 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
70 * identified by acqIdentifier
71 */
72 void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired,
73 const DateTimeRange &dataRangeAcquired);
74 )
75
76 void finished(QUuid requestID, std::shared_ptr<IDataSeries> dataSerie,
77 const DateTimeRange &range);
78
79 DEPRECATE(
80 /**
81 * @brief dataProvidedProgress notify the progression of the data identifier by acqIdentifier
82 */
83 void dataProvidedProgress(QUuid acqIdentifier, double progress);
84 )
85
45
86 void progress(QUuid requestID, double progress);
46 void progress(QUuid requestID, double progress);
87
47
88 DEPRECATE(
89 /**
90 * @brief dataProvidedFailed notify that data acquisition has failed
91 */
92 void dataProvidedFailed(QUuid acqIdentifier);
93 )
94
95 void failed(QUuid requestID);
96
97 /**
98 * @brief requestConstructed send a request for the data identified by acqIdentifier
99 * @callback is the methode call by the reply of the request when it is finished.
100 */
101 DEPRECATE(
102 void requestConstructed(std::shared_ptr<QNetworkRequest> request, QUuid acqIdentifier,
103 std::function<void(QNetworkReply *, QUuid)> callback);
104 )
105 };
48 };
106
49
107 // Required for using shared_ptr in signals/slots
50 // Required for using shared_ptr in signals/slots
108 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
51 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
109 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
52 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
110 std::function<void(QNetworkReply *, QUuid)>)
53 std::function<void(QNetworkReply *, QUuid)>)
111
54
112 #endif // SCIQLOP_IDATAPROVIDER_H
55 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,126 +1,128
1 #include <QThreadPool>
1 #include <QThreadPool>
2 #include <QRunnable>
2 #include <QRunnable>
3 #include <QObject>
3 #include <QObject>
4 #include <QReadWriteLock>
4 #include <QReadWriteLock>
5
5
6 #include "Variable/VariableSynchronizationGroup2.h"
6 #include "Variable/VariableSynchronizationGroup2.h"
7 #include <Variable/Variable.h>
7 #include <Variable/Variable.h>
8 #include <Common/containers.h>
8 #include <Common/containers.h>
9 #include <Common/debug.h>
9 #include <Common/debug.h>
10 #include <Data/DataProviderParameters.h>
10 #include <Data/DataProviderParameters.h>
11 #include <Data/DateTimeRangeHelper.h>
11 #include <Data/DateTimeRangeHelper.h>
12 #include <Data/DateTimeRange.h>
12 #include <Data/DateTimeRange.h>
13 #include <Data/IDataProvider.h>
13 #include <Data/IDataProvider.h>
14
14
15 struct VCTransaction
15 struct VCTransaction
16 {
16 {
17 VCTransaction(QUuid refVar, DateTimeRange range, int varCount)
17 VCTransaction(QUuid refVar, DateTimeRange range, int varCount)
18 :refVar{refVar},range{range},_remainingVars{varCount}
18 :refVar{refVar},range{range},_remainingVars{varCount}
19 {}
19 {}
20
20
21 QUuid refVar;
21 QUuid refVar;
22 DateTimeRange range;
22 DateTimeRange range;
23 bool ready()
23 bool ready()
24 {
24 {
25 QReadLocker lock{&_lock};
25 QReadLocker lock{&_lock};
26 return _remainingVars == 0;
26 return _remainingVars == 0;
27 }
27 }
28
28
29 bool done()
29 bool done()
30 {
30 {
31 QWriteLocker lock{&_lock};
31 QWriteLocker lock{&_lock};
32 _remainingVars-=1;
32 _remainingVars-=1;
33 return _remainingVars == 0;
33 return _remainingVars == 0;
34 }
34 }
35 private:
35 private:
36 QReadWriteLock _lock;
36 QReadWriteLock _lock;
37 int _remainingVars;
37 int _remainingVars;
38 };
38 };
39
39
40 class TransactionExe:public QObject,public QRunnable
40 class TransactionExe:public QObject,public QRunnable
41 {
41 {
42 Q_OBJECT
42 Q_OBJECT
43 std::shared_ptr<Variable> _variable;
43 std::shared_ptr<Variable> _variable;
44 std::shared_ptr<IDataProvider> _provider;
44 std::shared_ptr<IDataProvider> _provider;
45 std::vector<DateTimeRange> _ranges;
45 std::vector<DateTimeRange> _ranges;
46 DateTimeRange _range;
46 DateTimeRange _range;
47 DateTimeRange _cacheRange;
47 DateTimeRange _cacheRange;
48 public:
48 public:
49 TransactionExe(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider,
49 TransactionExe(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider,
50 const std::vector<DateTimeRange>& ranges, DateTimeRange range, DateTimeRange cacheRange)
50 const std::vector<DateTimeRange>& ranges, DateTimeRange range, DateTimeRange cacheRange)
51 :_variable{variable}, _provider{provider},_ranges{ranges},_range{range},_cacheRange{cacheRange}
51 :_variable{variable}, _provider{provider},_ranges{ranges},_range{range},_cacheRange{cacheRange}
52 {
52 {
53 setAutoDelete(true);
53 setAutoDelete(true);
54 }
54 }
55 void run()override
55 void run()override
56 {
56 {
57 std::vector<IDataSeries*> data;
57 std::vector<IDataSeries*> data;
58 for(auto range:_ranges)
58 for(auto range:_ranges)
59 {
59 {
60 data.push_back(_provider->getData(DataProviderParameters{{range}, _variable->metadata()}));
60 auto ds = _provider->getData(DataProviderParameters{{range}, _variable->metadata()});
61 if(ds)
62 data.push_back(ds);
61 }
63 }
62 _variable->updateData(data, _range, _cacheRange, true);
64 _variable->updateData(data, _range, _cacheRange, true);
63 emit transactionComplete();
65 emit transactionComplete();
64 }
66 }
65 signals:
67 signals:
66 void transactionComplete();
68 void transactionComplete();
67 };
69 };
68
70
69 class VCTransactionsQueues
71 class VCTransactionsQueues
70 {
72 {
71 QReadWriteLock _mutex{QReadWriteLock::Recursive};
73 QReadWriteLock _mutex{QReadWriteLock::Recursive};
72 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _nextTransactions;
74 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _nextTransactions;
73 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _pendingTransactions;
75 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _pendingTransactions;
74 public:
76 public:
75 void addEntry(QUuid id)
77 void addEntry(QUuid id)
76 {
78 {
77 QWriteLocker lock{&_mutex};
79 QWriteLocker lock{&_mutex};
78 _nextTransactions[id] = std::nullopt;
80 _nextTransactions[id] = std::nullopt;
79 _pendingTransactions[id] = std::nullopt;
81 _pendingTransactions[id] = std::nullopt;
80 }
82 }
81
83
82 void removeEntry(QUuid id)
84 void removeEntry(QUuid id)
83 {
85 {
84 QWriteLocker lock{&_mutex};
86 QWriteLocker lock{&_mutex};
85 _nextTransactions.erase(id);
87 _nextTransactions.erase(id);
86 _pendingTransactions.erase(id);
88 _pendingTransactions.erase(id);
87 }
89 }
88
90
89 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> pendingTransactions()
91 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> pendingTransactions()
90 {
92 {
91 QReadLocker lock{&_mutex};
93 QReadLocker lock{&_mutex};
92 return _pendingTransactions;
94 return _pendingTransactions;
93 }
95 }
94
96
95 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> nextTransactions()
97 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> nextTransactions()
96 {
98 {
97 QReadLocker lock{&_mutex};
99 QReadLocker lock{&_mutex};
98 return _nextTransactions;
100 return _nextTransactions;
99 }
101 }
100
102
101 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
103 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
102 {
104 {
103 QWriteLocker lock{&_mutex};
105 QWriteLocker lock{&_mutex};
104 _pendingTransactions[id] = _nextTransactions[id];
106 _pendingTransactions[id] = _nextTransactions[id];
105 _nextTransactions[id] = std::nullopt;
107 _nextTransactions[id] = std::nullopt;
106 return _pendingTransactions[id];
108 return _pendingTransactions[id];
107 }
109 }
108
110
109 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
111 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
110 {
112 {
111 QWriteLocker lock{&_mutex};
113 QWriteLocker lock{&_mutex};
112 _nextTransactions[id] = transaction;
114 _nextTransactions[id] = transaction;
113 }
115 }
114
116
115 void complete(QUuid id)
117 void complete(QUuid id)
116 {
118 {
117 QWriteLocker lock{&_mutex};
119 QWriteLocker lock{&_mutex};
118 _pendingTransactions[id] = std::nullopt;
120 _pendingTransactions[id] = std::nullopt;
119 }
121 }
120
122
121 bool active(QUuid id)
123 bool active(QUuid id)
122 {
124 {
123 QReadLocker lock{&_mutex};
125 QReadLocker lock{&_mutex};
124 return _nextTransactions[id].has_value() || _pendingTransactions[id].has_value();
126 return _nextTransactions[id].has_value() || _pendingTransactions[id].has_value();
125 }
127 }
126 };
128 };
@@ -1,123 +1,127
1 #include <Network/Downloader.h>
1 #include <Network/Downloader.h>
2 #include <memory>
2 #include <memory>
3
3
4 #include <QNetworkRequest>
4 #include <QNetworkRequest>
5 #include <QNetworkReply>
5 #include <QNetworkReply>
6 #include <QNetworkAccessManager>
6 #include <QNetworkAccessManager>
7 #include <QAuthenticator>
7 #include <QAuthenticator>
8 #include <QVariant>
8 #include <QVariant>
9 #include <QHash>
9 #include <QHash>
10 #include <QPair>
10 #include <QPair>
11 #include <QCoreApplication>
11 #include <QCoreApplication>
12 #include <QReadWriteLock>
12 #include <QReadWriteLock>
13 #include <QThread>
13
14
14 class Downloader::p_Downloader
15 class Downloader::p_Downloader
15 {
16 {
16 using login_pair=QPair<QString,QString>;
17 using login_pair=QPair<QString,QString>;
17 QNetworkAccessManager manager;
18 QNetworkAccessManager manager;
18 QHash<QString,login_pair> auth;
19 QHash<QString,login_pair> auth;
19 QReadWriteLock pending_requests_lock;
20 QReadWriteLock pending_requests_lock;
20 QHash<QUuid,QNetworkReply*> pending_requests;
21 QHash<QUuid,QNetworkReply*> pending_requests;
21
22
22 QNetworkRequest buildRequest(const QString& url, const QString &user="", const QString &passwd="")
23 QNetworkRequest buildRequest(const QString& url, const QString &user="", const QString &passwd="")
23 {
24 {
24 QNetworkRequest request;
25 QNetworkRequest request;
25 request.setUrl(QUrl(url));
26 request.setUrl(QUrl(url));
26 request.setRawHeader("User-Agent", "SciQLop 1.0");
27 request.setRawHeader("User-Agent", "SciQLop 1.0");
27 if(user!="" and passwd!="")
28 if(user!="" and passwd!="")
28 {
29 {
29 //might grow quickly since we can have tons of URLs for the same host
30 //might grow quickly since we can have tons of URLs for the same host
30 auth[url]=login_pair(user,passwd);
31 auth[url]=login_pair(user,passwd);
31 QString login = "Basic "+user+":"+passwd;
32 QString login = "Basic "+user+":"+passwd;
32 request.setRawHeader("Authorization",login.toLocal8Bit());
33 request.setRawHeader("Authorization",login.toLocal8Bit());
33 }
34 }
34 return request;
35 return request;
35 }
36 }
36
37
37 public:
38 public:
38 explicit p_Downloader()
39 explicit p_Downloader()
39 {
40 {
40
41
41 auto login_bambda = [this](QNetworkReply * reply, QAuthenticator * authenticator)
42 auto login_bambda = [this](QNetworkReply * reply, QAuthenticator * authenticator)
42 {
43 {
43 if(auth.contains(reply->url().toString()))
44 if(auth.contains(reply->url().toString()))
44 {
45 {
45 auto login = auth[reply->url().toString()];
46 auto login = auth[reply->url().toString()];
46 authenticator->setUser(login.first);
47 authenticator->setUser(login.first);
47 authenticator->setPassword(login.second);
48 authenticator->setPassword(login.second);
48 }
49 }
49 };
50 };
50
51
51 QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, login_bambda);
52 QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, login_bambda);
52 }
53 }
53
54
54 Response get(const QString& url, const QString &user="", const QString &passwd="")
55 Response get(const QString& url, const QString &user="", const QString &passwd="")
55 {
56 {
56 QNetworkRequest request = buildRequest(url, user, passwd);
57 QNetworkRequest request = buildRequest(url, user, passwd);
57 QNetworkReply *reply = manager.get(request);
58 QNetworkReply *reply = manager.get(request);
58 while (!reply->isFinished())
59 while (!reply->isFinished())
60 {
59 QCoreApplication::processEvents();
61 QCoreApplication::processEvents();
62 QThread::usleep(10000);
63 }
60 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
64 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
61 Response resp = Response(reply->readAll(), status_code.toInt());
65 Response resp = Response(reply->readAll(), status_code.toInt());
62 delete reply;
66 delete reply;
63 if(user!="" and passwd!="")
67 if(user!="" and passwd!="")
64 auth.remove(url);
68 auth.remove(url);
65 return resp;
69 return resp;
66 }
70 }
67
71
68 QUuid getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
72 QUuid getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
69 {
73 {
70 auto uuid = QUuid::createUuid();
74 auto uuid = QUuid::createUuid();
71 QNetworkRequest request = buildRequest(url, user, passwd);
75 QNetworkRequest request = buildRequest(url, user, passwd);
72 QNetworkReply *reply = manager.get(request);
76 QNetworkReply *reply = manager.get(request);
73 auto callback_wrapper = [url, uuid, callback, this](){
77 auto callback_wrapper = [url, uuid, callback, this](){
74 QNetworkReply* reply;
78 QNetworkReply* reply;
75 {
79 {
76 QWriteLocker locker(&pending_requests_lock);
80 QWriteLocker locker(&pending_requests_lock);
77 reply = pending_requests.take(uuid);
81 reply = pending_requests.take(uuid);
78 }
82 }
79 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
83 QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
80 Response resp = Response(reply->readAll(), status_code.toInt());
84 Response resp = Response(reply->readAll(), status_code.toInt());
81 auth.remove(url);
85 auth.remove(url);
82 delete reply;
86 delete reply;
83 callback(uuid, resp);
87 callback(uuid, resp);
84 };
88 };
85 QObject::connect(reply, &QNetworkReply::finished, callback_wrapper);
89 QObject::connect(reply, &QNetworkReply::finished, callback_wrapper);
86 {
90 {
87 QWriteLocker locker(&pending_requests_lock);
91 QWriteLocker locker(&pending_requests_lock);
88 pending_requests[uuid] = reply;
92 pending_requests[uuid] = reply;
89 }
93 }
90 return uuid;
94 return uuid;
91 }
95 }
92 bool downloadFinished(QUuid uuid)
96 bool downloadFinished(QUuid uuid)
93 {
97 {
94 QReadLocker locker(&pending_requests_lock);
98 QReadLocker locker(&pending_requests_lock);
95 if(pending_requests.contains(uuid))
99 if(pending_requests.contains(uuid))
96 {
100 {
97 auto req = pending_requests[uuid];
101 auto req = pending_requests[uuid];
98 return req->isFinished();
102 return req->isFinished();
99 }
103 }
100 return true;
104 return true;
101 }
105 }
102 };
106 };
103
107
104 Response Downloader::get(const QString &url, const QString &user, const QString &passwd)
108 Response Downloader::get(const QString &url, const QString &user, const QString &passwd)
105 {
109 {
106 return Downloader::instance().impl->get(url, user, passwd);
110 return Downloader::instance().impl->get(url, user, passwd);
107 }
111 }
108
112
109 QUuid Downloader::getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
113 QUuid Downloader::getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd)
110 {
114 {
111 return Downloader::instance().impl->getAsync(url, callback, user, passwd);
115 return Downloader::instance().impl->getAsync(url, callback, user, passwd);
112 }
116 }
113
117
114 bool Downloader::downloadFinished(QUuid uuid)
118 bool Downloader::downloadFinished(QUuid uuid)
115 {
119 {
116 return Downloader::instance().impl->downloadFinished(uuid);
120 return Downloader::instance().impl->downloadFinished(uuid);
117 }
121 }
118
122
119 Downloader::Downloader()
123 Downloader::Downloader()
120 :impl(spimpl::make_unique_impl<p_Downloader>())
124 :impl(spimpl::make_unique_impl<p_Downloader>())
121 {
125 {
122 }
126 }
123
127
@@ -1,392 +1,390
1 #include <QQueue>
1 #include <QQueue>
2 #include <QThreadPool>
2 #include <QThreadPool>
3 #include <QRunnable>
3 #include <QRunnable>
4 #include <QObject>
4 #include <QObject>
5 #include <QDataStream>
5 #include <QDataStream>
6
6
7 #include "Variable/VariableController2.h"
7 #include "Variable/VariableController2.h"
8 #include "Variable/VariableSynchronizationGroup2.h"
8 #include "Variable/VariableSynchronizationGroup2.h"
9 #include <Common/containers.h>
9 #include <Common/containers.h>
10 #include <Common/debug.h>
10 #include <Common/debug.h>
11 #include <Data/DataProviderParameters.h>
11 #include <Data/DataProviderParameters.h>
12 #include <Data/DateTimeRangeHelper.h>
12 #include <Data/DateTimeRangeHelper.h>
13 #include <Data/DateTimeRange.h>
13 #include <Data/DateTimeRange.h>
14 #include <Variable/VariableCacheStrategyFactory.h>
14 #include <Variable/VariableCacheStrategyFactory.h>
15 #include <Variable/private/VCTransaction.h>
15 #include <Variable/private/VCTransaction.h>
16 #include <QCoreApplication>
16 #include <QCoreApplication>
17
17
18
18
19
19
20 class VariableController2::VariableController2Private
20 class VariableController2::VariableController2Private
21 {
21 {
22 struct threadSafeVaraiblesMaps
22 struct threadSafeVaraiblesMaps
23 {
23 {
24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
25 {
25 {
26 QWriteLocker lock{&_lock};
26 QWriteLocker lock{&_lock};
27 _variables[*variable] = variable;
27 _variables[*variable] = variable;
28 _providers[*variable] = provider;
28 _providers[*variable] = provider;
29 _synchronizationGroups[*variable] = synchronizationGroup;
29 _synchronizationGroups[*variable] = synchronizationGroup;
30 }
30 }
31
31
32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
33 {
33 {
34 QWriteLocker lock{&_lock};
34 QWriteLocker lock{&_lock};
35 _variables.erase(*variable);
35 _variables.erase(*variable);
36 _providers.remove(*variable);
36 _providers.remove(*variable);
37 _synchronizationGroups.remove(*variable);
37 _synchronizationGroups.remove(*variable);
38 }
38 }
39
39
40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
41 {
41 {
42 QWriteLocker lock{&_lock};
42 QWriteLocker lock{&_lock};
43 if(with.has_value())
43 if(with.has_value())
44 {
44 {
45 auto newGroup = _synchronizationGroups[*with.value()];
45 auto newGroup = _synchronizationGroups[*with.value()];
46 newGroup->addVariable(*variable);
46 newGroup->addVariable(*variable);
47 _synchronizationGroups[*variable] = newGroup;
47 _synchronizationGroups[*variable] = newGroup;
48 }
48 }
49 else
49 else
50 {
50 {
51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
52 }
52 }
53 }
53 }
54
54
55 inline std::shared_ptr<Variable> variable(QUuid variable)
55 inline std::shared_ptr<Variable> variable(QUuid variable)
56 {
56 {
57 QReadLocker lock{&_lock};
57 QReadLocker lock{&_lock};
58 auto it = _variables.find(variable);
58 auto it = _variables.find(variable);
59 [[unlikely]]
59 [[unlikely]]
60 if(it==_variables.end())
60 if(it==_variables.end())
61 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
61 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
62 return (*it).second;
62 return (*it).second;
63 }
63 }
64
64
65 inline std::shared_ptr<Variable> variable(int index)
65 inline std::shared_ptr<Variable> variable(int index)
66 {
66 {
67 QReadLocker lock{&_lock};
67 QReadLocker lock{&_lock};
68 [[unlikely]]
68 [[unlikely]]
69 if(!_variables.size() > index)
69 if(!_variables.size() > index)
70 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
70 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
71 auto it = _variables.cbegin();
71 auto it = _variables.cbegin();
72 while (index!=0) {
72 while (index!=0) {
73 index-=1;
73 index-=1;
74 it++;
74 it++;
75 }
75 }
76 return (*it).second;
76 return (*it).second;
77 }
77 }
78
78
79 inline const std::vector<std::shared_ptr<Variable>> variables()
79 inline const std::vector<std::shared_ptr<Variable>> variables()
80 {
80 {
81 std::vector<std::shared_ptr<Variable>> vars;
81 std::vector<std::shared_ptr<Variable>> vars;
82 QReadLocker lock{&_lock};
82 QReadLocker lock{&_lock};
83 for(const auto&[id, var]:_variables)
83 for(const auto&[id, var]:_variables)
84 {
84 {
85 vars.push_back(var);
85 vars.push_back(var);
86 }
86 }
87 return vars;
87 return vars;
88 }
88 }
89
89
90 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
90 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
91 {
91 {
92 QReadLocker lock{&_lock};
92 QReadLocker lock{&_lock};
93 [[unlikely]]
93 [[unlikely]]
94 if(!_providers.contains(variable))
94 if(!_providers.contains(variable))
95 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
95 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
96 return _providers[variable];
96 return _providers[variable];
97 }
97 }
98
98
99 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
99 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
100 {
100 {
101 QReadLocker lock{&_lock};
101 QReadLocker lock{&_lock};
102 [[unlikely]]
102 [[unlikely]]
103 if(!_synchronizationGroups.contains(variable))
103 if(!_synchronizationGroups.contains(variable))
104 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
104 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
105 return _synchronizationGroups[variable];
105 return _synchronizationGroups[variable];
106 }
106 }
107
107
108 inline bool has(const std::shared_ptr<Variable>& variable)
108 inline bool has(const std::shared_ptr<Variable>& variable)
109 {
109 {
110 QReadLocker lock{&_lock};
110 QReadLocker lock{&_lock};
111 return _variables.find(*variable)==_variables.end();
111 return _variables.find(*variable)==_variables.end();
112 }
112 }
113
113
114 private:
114 private:
115 std::map<QUuid,std::shared_ptr<Variable>> _variables;
115 std::map<QUuid,std::shared_ptr<Variable>> _variables;
116 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
116 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
117 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
117 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
118 QReadWriteLock _lock{QReadWriteLock::Recursive};
118 QReadWriteLock _lock{QReadWriteLock::Recursive};
119 }_maps;
119 }_maps;
120 QThreadPool _ThreadPool;
120 QThreadPool* _ThreadPool;
121 VCTransactionsQueues _transactions;
121 VCTransactionsQueues _transactions;
122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
123
123
124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
125 {
125 {
126 if(transaction->done())
126 if(transaction->done())
127 {
127 {
128 _transactions.complete(group);
128 _transactions.complete(group);
129 }
129 }
130 this->_processTransactions();
130 this->_processTransactions();
131 }
131 }
132 void _processTransactions()
132 void _processTransactions()
133 {
133 {
134 auto nextTransactions = _transactions.nextTransactions();
134 auto nextTransactions = _transactions.nextTransactions();
135 auto pendingTransactions = _transactions.pendingTransactions();
135 auto pendingTransactions = _transactions.pendingTransactions();
136 for( auto [groupID, newTransaction] : nextTransactions)
136 for( auto [groupID, newTransaction] : nextTransactions)
137 {
137 {
138 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
138 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
139 {
139 {
140 _transactions.start(groupID);
140 _transactions.start(groupID);
141 auto refVar = _maps.variable(newTransaction.value()->refVar);
141 auto refVar = _maps.variable(newTransaction.value()->refVar);
142 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
142 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
143 for( auto const& [ID, range] : ranges)
143 for( auto const& [ID, range] : ranges)
144 {
144 {
145 auto provider = _maps.provider(ID);
145 auto provider = _maps.provider(ID);
146 auto variable = _maps.variable(ID);
146 auto variable = _maps.variable(ID);
147 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
147 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
148 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
148 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
149 QObject::connect(exe,
149 QObject::connect(exe,
150 &TransactionExe::transactionComplete,
150 &TransactionExe::transactionComplete,
151 [groupID=groupID,transaction=newTransaction.value(),this]()
151 [groupID=groupID,transaction=newTransaction.value(),this]()
152 {
152 {
153 this->_transactionComplete(groupID, transaction);
153 this->_transactionComplete(groupID, transaction);
154 }
154 }
155 );
155 );
156 _ThreadPool.start(exe);
156 _ThreadPool->start(exe);
157 }
157 }
158 }
158 }
159 }
159 }
160 }
160 }
161
161
162 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
162 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
163 {
163 {
164 std::map<QUuid,DateTimeRange> ranges;
164 std::map<QUuid,DateTimeRange> ranges;
165 if(!DateTimeRangeHelper::hasnan(r))
165 if(!DateTimeRangeHelper::hasnan(r))
166 {
166 {
167 auto group = _maps.group(*refVar);
167 auto group = _maps.group(*refVar);
168 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
168 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
169 transformation.has_value())
169 transformation.has_value())
170 {
170 {
171 for(auto varId:group->variables())
171 for(auto varId:group->variables())
172 {
172 {
173 auto var = _maps.variable(varId);
173 auto var = _maps.variable(varId);
174 auto newRange = var->range().transform(transformation.value());
174 auto newRange = var->range().transform(transformation.value());
175 ranges[varId] = newRange;
175 ranges[varId] = newRange;
176 }
176 }
177 }
177 }
178 else // force new range to all variables -> may be weird if more than one var in the group
178 else // force new range to all variables -> may be weird if more than one var in the group
179 // @TODO ensure that there is no side effects
179 // @TODO ensure that there is no side effects
180 {
180 {
181 for(auto varId:group->variables())
181 for(auto varId:group->variables())
182 {
182 {
183 auto var = _maps.variable(varId);
183 auto var = _maps.variable(varId);
184 ranges[varId] = r;
184 ranges[varId] = r;
185 }
185 }
186 }
186 }
187 }
187 }
188 else
188 else
189 {
189 {
190 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
190 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
191 }
191 }
192 return ranges;
192 return ranges;
193 }
193 }
194
194
195 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
195 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
196 {
196 {
197 DateTimeRange newCacheRange;
197 DateTimeRange newCacheRange;
198 std::vector<DateTimeRange> missingRanges;
198 std::vector<DateTimeRange> missingRanges;
199 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
199 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
200 {
200 {
201 newCacheRange = _cacheStrategy->computeRange(r,r);
201 newCacheRange = _cacheStrategy->computeRange(r,r);
202 missingRanges = {newCacheRange};
202 missingRanges = {newCacheRange};
203 }
203 }
204 else
204 else
205 {
205 {
206 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
206 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
207 missingRanges = newCacheRange - var->cacheRange();
207 missingRanges = newCacheRange - var->cacheRange();
208 }
208 }
209 return {missingRanges,newCacheRange};
209 return {missingRanges,newCacheRange};
210 }
210 }
211
211
212 void _changeRange(QUuid id, DateTimeRange r)
212 void _changeRange(QUuid id, DateTimeRange r)
213 {
213 {
214 _changeRange(_maps.variable(id) ,r);
214 _changeRange(_maps.variable(id) ,r);
215 }
215 }
216 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
216 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
217 {
217 {
218 auto provider = _maps.provider(*var);
218 auto provider = _maps.provider(*var);
219 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
219 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
220 std::vector<IDataSeries*> data;
220 std::vector<IDataSeries*> data;
221 for(auto range:missingRanges)
221 for(auto range:missingRanges)
222 {
222 {
223 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
223 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
224 }
224 }
225 var->updateData(data, r, newCacheRange, true);
225 var->updateData(data, r, newCacheRange, true);
226 }
226 }
227 public:
227 public:
228 VariableController2Private(QObject* parent=Q_NULLPTR)
228 VariableController2Private(QObject* parent=Q_NULLPTR)
229 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
229 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
230 {
230 {
231 Q_UNUSED(parent);
231 Q_UNUSED(parent);
232 this->_ThreadPool.setMaxThreadCount(32);
232 this->_ThreadPool = new QThreadPool();
233 this->_ThreadPool->setMaxThreadCount(32);
233 }
234 }
234
235
235 /*
236 /*
236 * This dtor has to like this even if this is ugly, because default dtor would rely on
237 * This dtor has to like this even if this is ugly, because default dtor would rely on
237 * declaration order to destruct members and that would always lead to regressions when
238 * declaration order to destruct members and that would always lead to regressions when
238 * modifying class members
239 * modifying class members
239 */
240 */
240 ~VariableController2Private()
241 ~VariableController2Private()
241 {
242 {
242 while (this->_ThreadPool.activeThreadCount())
243 delete this->_ThreadPool;
243 {
244 this->_ThreadPool.waitForDone(100);
245 }
246 }
244 }
247
245
248 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
246 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
249 {
247 {
250 auto newVar = std::make_shared<Variable>(name,metadata);
248 auto newVar = std::make_shared<Variable>(name,metadata);
251 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
249 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
252 _maps.addVariable(newVar,std::move(provider),group);
250 _maps.addVariable(newVar,std::move(provider),group);
253 this->_transactions.addEntry(*group);
251 this->_transactions.addEntry(*group);
254 return newVar;
252 return newVar;
255 }
253 }
256
254
257 std::shared_ptr<Variable> variable(QUuid ID)
255 std::shared_ptr<Variable> variable(QUuid ID)
258 {
256 {
259 return _maps.variable(ID);
257 return _maps.variable(ID);
260 }
258 }
261
259
262 std::shared_ptr<Variable> variable(int index)
260 std::shared_ptr<Variable> variable(int index)
263 {
261 {
264 return _maps.variable(index);
262 return _maps.variable(index);
265 }
263 }
266
264
267 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
265 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
268 {
266 {
269 auto newVar = variable->clone();
267 auto newVar = variable->clone();
270 _maps.synchronize(newVar,std::nullopt);
268 _maps.synchronize(newVar,std::nullopt);
271 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
269 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
272 this->_transactions.addEntry(*_maps.group(*newVar));
270 this->_transactions.addEntry(*_maps.group(*newVar));
273 return newVar;
271 return newVar;
274 }
272 }
275
273
276 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
274 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
277 {
275 {
278 return _transactions.active(*_maps.group(*variable));
276 return _transactions.active(*_maps.group(*variable));
279 }
277 }
280
278
281 void deleteVariable(const std::shared_ptr<Variable>& variable)
279 void deleteVariable(const std::shared_ptr<Variable>& variable)
282 {
280 {
283 _maps.removeVariable(variable);
281 _maps.removeVariable(variable);
284 }
282 }
285
283
286 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
284 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
287 {
285 {
288 if(!DateTimeRangeHelper::hasnan(r))
286 if(!DateTimeRangeHelper::hasnan(r))
289 {
287 {
290 auto group = _maps.group(*variable);
288 auto group = _maps.group(*variable);
291 // Just overwrite next transaction
289 // Just overwrite next transaction
292 {
290 {
293 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
291 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
294 }
292 }
295 _processTransactions();
293 _processTransactions();
296 }
294 }
297 else
295 else
298 {
296 {
299 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
297 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
300 }
298 }
301 }
299 }
302
300
303 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
301 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
304 {
302 {
305 asyncChangeRange(variable,r);
303 asyncChangeRange(variable,r);
306 while (hasPendingTransactions(variable))
304 while (hasPendingTransactions(variable))
307 {
305 {
308 QCoreApplication::processEvents();
306 QCoreApplication::processEvents();
309 }
307 }
310 }
308 }
311
309
312 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
310 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
313 {
311 {
314 _maps.synchronize(var, with);
312 _maps.synchronize(var, with);
315 }
313 }
316
314
317 inline const std::vector<std::shared_ptr<Variable>> variables()
315 inline const std::vector<std::shared_ptr<Variable>> variables()
318 {
316 {
319 return _maps.variables();
317 return _maps.variables();
320 }
318 }
321
319
322 };
320 };
323
321
324 VariableController2::VariableController2()
322 VariableController2::VariableController2()
325 :impl{spimpl::make_unique_impl<VariableController2Private>()}
323 :impl{spimpl::make_unique_impl<VariableController2Private>()}
326 {}
324 {}
327
325
328 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
326 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
329 {
327 {
330 auto var = impl->createVariable(name, metadata, provider);
328 auto var = impl->createVariable(name, metadata, provider);
331 emit variableAdded(var);
329 emit variableAdded(var);
332 if(!DateTimeRangeHelper::hasnan(range))
330 if(!DateTimeRangeHelper::hasnan(range))
333 impl->changeRange(var,range);
331 impl->asyncChangeRange(var,range);
334 else
332 else
335 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
333 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
336 return var;
334 return var;
337 }
335 }
338
336
339 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
337 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
340 {
338 {
341 return impl->cloneVariable(variable);
339 return impl->cloneVariable(variable);
342 }
340 }
343
341
344 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
342 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
345 {
343 {
346 impl->deleteVariable(variable);
344 impl->deleteVariable(variable);
347 emit variableDeleted(variable);
345 emit variableDeleted(variable);
348 }
346 }
349
347
350 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
348 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
351 {
349 {
352 impl->changeRange(variable, r);
350 impl->changeRange(variable, r);
353 }
351 }
354
352
355 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
353 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
356 {
354 {
357 impl->asyncChangeRange(variable, r);
355 impl->asyncChangeRange(variable, r);
358 }
356 }
359
357
360 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
358 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
361 {
359 {
362 return impl->variables();
360 return impl->variables();
363 }
361 }
364
362
365 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
363 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
366 {
364 {
367 return impl->hasPendingTransactions(variable);
365 return impl->hasPendingTransactions(variable);
368 }
366 }
369
367
370 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
368 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
371 {
369 {
372 impl->synchronize(var, with);
370 impl->synchronize(var, with);
373 }
371 }
374
372
375 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
373 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
376 {
374 {
377 std::vector<std::shared_ptr<Variable>> variables;
375 std::vector<std::shared_ptr<Variable>> variables;
378 for (const auto& id : ids) {
376 for (const auto& id : ids) {
379 variables.push_back(impl->variable(id));
377 variables.push_back(impl->variable(id));
380 }
378 }
381 return variables;
379 return variables;
382 }
380 }
383
381
384 const std::shared_ptr<Variable> &VariableController2::operator[](int index) const
382 const std::shared_ptr<Variable> &VariableController2::operator[](int index) const
385 {
383 {
386 return impl->variable (index);
384 return impl->variable (index);
387 }
385 }
388
386
389 std::shared_ptr<Variable> VariableController2::operator[](int index)
387 std::shared_ptr<Variable> VariableController2::operator[](int index)
390 {
388 {
391 return impl->variable (index);
389 return impl->variable (index);
392 }
390 }
@@ -1,96 +1,83
1 #ifndef TESTPROVIDER_H
1 #ifndef TESTPROVIDER_H
2 #define TESTPROVIDER_H
2 #define TESTPROVIDER_H
3
3
4 #include <memory>
4 #include <memory>
5 #include <cmath>
5 #include <cmath>
6 #include <algorithm>
6 #include <algorithm>
7 #include <numeric>
7 #include <numeric>
8
8
9 #include <QUuid>
9 #include <QUuid>
10 #include <QtGlobal>
10 #include <QtGlobal>
11 #include <QtTest>
11 #include <QtTest>
12
12
13 #include <Data/IDataProvider.h>
13 #include <Data/IDataProvider.h>
14 #include <Data/DataProviderParameters.h>
14 #include <Data/DataProviderParameters.h>
15 #include <Data/DataSeries.h>
15 #include <Data/DataSeries.h>
16 #include <Data/ScalarSeries.h>
16 #include <Data/ScalarSeries.h>
17 #include <Variable/Variable.h>
17 #include <Variable/Variable.h>
18
18
19
19
20 template<int slope>
20 template<int slope>
21 class SimpleRange: public IDataProvider
21 class SimpleRange: public IDataProvider
22 {
22 {
23 public:
23 public:
24 SimpleRange() = default;
24 SimpleRange() = default;
25
25
26 int callCounter = 0;
26 int callCounter = 0;
27 std::shared_ptr<IDataProvider> clone() const override{ return std::make_shared<SimpleRange>(); }
27 std::shared_ptr<IDataProvider> clone() const override{ return std::make_shared<SimpleRange>(); }
28
28
29 IDataSeries* getData(const DataProviderParameters &parameters) override
29 IDataSeries* getData(const DataProviderParameters &parameters) override
30 {
30 {
31 callCounter+=1;
31 callCounter+=1;
32 auto tstart = parameters.m_Times[0].m_TStart;
32 auto tstart = parameters.m_Times[0].m_TStart;
33 auto tend = parameters.m_Times[0].m_TEnd;
33 auto tend = parameters.m_Times[0].m_TEnd;
34 std::vector<double> x;
34 std::vector<double> x;
35 std::vector<double> y;
35 std::vector<double> y;
36 for(double i = ceil(tstart);i<=floor(tend);i+=1.) //1 seconde data resolution
36 for(double i = ceil(tstart);i<=floor(tend);i+=1.) //1 seconde data resolution
37 {
37 {
38 x.push_back(i);
38 x.push_back(i);
39 y.push_back(i*slope);
39 y.push_back(i*slope);
40 }
40 }
41 auto serie = new ScalarSeries(std::move(x),std::move(y),Unit("Secondes",true),Unit("Volts",false));
41 auto serie = new ScalarSeries(std::move(x),std::move(y),Unit("Secondes",true),Unit("Volts",false));
42 return serie;
42 return serie;
43 }
43 }
44
44
45
46
47 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
48 {
49 Q_UNUSED(acqIdentifier)
50 Q_UNUSED(parameters)
51 }
52
53 void requestDataAborting(QUuid acqIdentifier) override
54 {
55 Q_UNUSED(acqIdentifier)
56 }
57
58 };
45 };
59
46
60
47
61 template <class T>
48 template <class T>
62 auto sumdiff(T begin, T end)
49 auto sumdiff(T begin, T end)
63 {
50 {
64 std::vector<double> diff_vect(end-begin-1);
51 std::vector<double> diff_vect(end-begin-1);
65 auto diff = [](auto next,auto item)
52 auto diff = [](auto next,auto item)
66 {
53 {
67 return next.value() - item.value();
54 return next.value() - item.value();
68 };
55 };
69 std::transform (begin+1, end, begin, diff_vect.begin(),diff);
56 std::transform (begin+1, end, begin, diff_vect.begin(),diff);
70 return std::accumulate(diff_vect.cbegin(), diff_vect.cend(), 0);
57 return std::accumulate(diff_vect.cbegin(), diff_vect.cend(), 0);
71 }
58 }
72
59
73 template <int slope=1>
60 template <int slope=1>
74 struct RangeType
61 struct RangeType
75 {
62 {
76 static void check_properties(std::shared_ptr<Variable> v, DateTimeRange r)
63 static void check_properties(std::shared_ptr<Variable> v, DateTimeRange r)
77 {
64 {
78 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
65 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
79 auto s = sumdiff(bounds.first, bounds.second) / slope;
66 auto s = sumdiff(bounds.first, bounds.second) / slope;
80 auto nbpoints = bounds.second - bounds.first+1.;
67 auto nbpoints = bounds.second - bounds.first+1.;
81 QCOMPARE(nbpoints, int(s)+2);//<- @TODO weird has to be investigated why +2?
68 QCOMPARE(nbpoints, int(s)+2);//<- @TODO weird has to be investigated why +2?
82 QCOMPARE(bounds.first->x(), bounds.first->value()/slope);
69 QCOMPARE(bounds.first->x(), bounds.first->value()/slope);
83 }
70 }
84 };
71 };
85
72
86 template <class T>
73 template <class T>
87 void check_variable_state(std::shared_ptr<Variable> v, DateTimeRange r)
74 void check_variable_state(std::shared_ptr<Variable> v, DateTimeRange r)
88 {
75 {
89 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
76 auto bounds = v->dataSeries()->valuesBounds(r.m_TStart, r.m_TEnd);
90 //generated data has to be inside range
77 //generated data has to be inside range
91 QVERIFY(bounds.first->x() >= r.m_TStart);
78 QVERIFY(bounds.first->x() >= r.m_TStart);
92 QVERIFY(bounds.second->x() <= r.m_TEnd);
79 QVERIFY(bounds.second->x() <= r.m_TEnd);
93 T::check_properties(v,r);
80 T::check_properties(v,r);
94 }
81 }
95
82
96 #endif
83 #endif
General Comments 0
You need to be logged in to leave comments. Login now