##// END OF EJS Templates
Bypassed cache and merge mechanism, this seems to be broken...
jeandet -
r44:79fb0ced05d7
parent child
Show More
@@ -1,113 +1,117
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include <optional>
4 #include <optional>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8 #include <QUuid>
8 #include <QUuid>
9 #include <QReadWriteLock>
9 #include <QReadWriteLock>
10 #include <QDataStream>
10 #include <QDataStream>
11
11
12 #include "CoreGlobal.h"
12 #include "CoreGlobal.h"
13 #include <Data/DataSeriesIterator.h>
13 #include <Data/DataSeriesIterator.h>
14 #include <Data/DataSeriesType.h>
14 #include <Data/DataSeriesType.h>
15 #include <Data/DateTimeRange.h>
15 #include <Data/DateTimeRange.h>
16
16
17
17
18 #include <Common/deprecate.h>
18 #include <Common/deprecate.h>
19 #include <Common/MetaTypes.h>
19 #include <Common/MetaTypes.h>
20 #include <Common/spimpl.h>
20 #include <Common/spimpl.h>
21
21
22 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
22 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
23
23
24 class IDataSeries;
24 class IDataSeries;
25 class QString;
25 class QString;
26
26
27 /**
27 /**
28 * @brief The Variable class represents a variable in SciQlop.
28 * @brief The Variable class represents a variable in SciQlop.
29 */
29 */
30 class SCIQLOP_CORE_EXPORT Variable : public QObject {
30 class SCIQLOP_CORE_EXPORT Variable : public QObject {
31
31
32 Q_OBJECT
32 Q_OBJECT
33
33
34 public:
34 public:
35 explicit Variable(const QString &name, const QVariantHash &metadata = {});
35 explicit Variable(const QString &name, const QVariantHash &metadata = {});
36
36
37 /// Copy ctor
37 /// Copy ctor
38 explicit Variable(const Variable &other);
38 explicit Variable(const Variable &other);
39
39
40 std::shared_ptr<Variable> clone() const;
40 std::shared_ptr<Variable> clone() const;
41
41
42 QString name() const noexcept;
42 QString name() const noexcept;
43 void setName(const QString &name) noexcept;
43 void setName(const QString &name) noexcept;
44 DateTimeRange range() const noexcept;
44 DateTimeRange range() const noexcept;
45 void setRange(const DateTimeRange &range, bool notify=false) noexcept;
45 void setRange(const DateTimeRange &range, bool notify=false) noexcept;
46 DateTimeRange cacheRange() const noexcept;
46 DateTimeRange cacheRange() const noexcept;
47 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
47 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
48
48
49 /// @return the number of points hold by the variable. The number of points is updated each time
49 /// @return the number of points hold by the variable. The number of points is updated each time
50 /// the data series changes
50 /// the data series changes
51 unsigned int nbPoints() const noexcept;
51 unsigned int nbPoints() const noexcept;
52
52
53 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
53 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
54 /// series between the range of the variable. The real range is updated each time the variable
54 /// series between the range of the variable. The real range is updated each time the variable
55 /// range or the data series changed
55 /// range or the data series changed
56 /// @return the real range, invalid range if the data series is null or empty
56 /// @return the real range, invalid range if the data series is null or empty
57 /// @sa setDataSeries()
57 /// @sa setDataSeries()
58 /// @sa setRange()
58 /// @sa setRange()
59 std::optional<DateTimeRange> realRange() const noexcept;
59 std::optional<DateTimeRange> realRange() const noexcept;
60
60
61 /// @return the data of the variable, nullptr if there is no data
61 /// @return the data of the variable, nullptr if there is no data
62 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
62 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
63
63
64 /// @return the type of data that the variable holds
64 /// @return the type of data that the variable holds
65 DataSeriesType type() const noexcept;
65 DataSeriesType type() const noexcept;
66
66
67 QVariantHash metadata() const noexcept;
67 QVariantHash metadata() const noexcept;
68
68
69 void updateData(const std::vector<IDataSeries*>& dataSeries,
69 void updateData(const std::vector<IDataSeries*>& dataSeries,
70 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
70 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
71 bool notify=true);
71 bool notify=true);
72
72
73 void setData(const std::vector<IDataSeries*>& dataSeries,
74 const DateTimeRange& newRange, const DateTimeRange& newCacheRange,
75 bool notify=true);
76
73 static QByteArray mimeData(const std::vector<std::shared_ptr<Variable> > &variables)
77 static QByteArray mimeData(const std::vector<std::shared_ptr<Variable> > &variables)
74 {
78 {
75 auto encodedData = QByteArray{};
79 auto encodedData = QByteArray{};
76 QDataStream stream{&encodedData, QIODevice::WriteOnly};
80 QDataStream stream{&encodedData, QIODevice::WriteOnly};
77 for (auto &var : variables) {
81 for (auto &var : variables) {
78 stream << var->ID().toByteArray();
82 stream << var->ID().toByteArray();
79 }
83 }
80 return encodedData;
84 return encodedData;
81 }
85 }
82
86
83 static std::vector<QUuid> variablesIDs(QByteArray mimeData)
87 static std::vector<QUuid> variablesIDs(QByteArray mimeData)
84 {
88 {
85 std::vector<QUuid> variables;
89 std::vector<QUuid> variables;
86 QDataStream stream{mimeData};
90 QDataStream stream{mimeData};
87
91
88 QVariantList ids;
92 QVariantList ids;
89 stream >> ids;
93 stream >> ids;
90
94
91 for (const auto& id : ids) {
95 for (const auto& id : ids) {
92 variables.emplace_back (id.toByteArray());
96 variables.emplace_back (id.toByteArray());
93 }
97 }
94 return variables;
98 return variables;
95 }
99 }
96
100
97 operator QUuid() {return _uuid;}
101 operator QUuid() {return _uuid;}
98 QUuid ID(){return _uuid;}
102 QUuid ID(){return _uuid;}
99 signals:
103 signals:
100 void updated(QUuid ID);
104 void updated(QUuid ID);
101
105
102 private:
106 private:
103 class VariablePrivate;
107 class VariablePrivate;
104 spimpl::unique_impl_ptr<VariablePrivate> impl;
108 spimpl::unique_impl_ptr<VariablePrivate> impl;
105 QUuid _uuid;
109 QUuid _uuid;
106 QReadWriteLock m_lock;
110 QReadWriteLock m_lock;
107 };
111 };
108
112
109 // Required for using shared_ptr in signals/slots
113 // Required for using shared_ptr in signals/slots
110 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
114 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
111 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
115 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
112
116
113 #endif // SCIQLOP_VARIABLE_H
117 #endif // SCIQLOP_VARIABLE_H
@@ -1,128 +1,133
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 bool _overwrite;
48 public:
49 public:
49 TransactionExe(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider,
50 TransactionExe(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider,
50 const std::vector<DateTimeRange>& ranges, DateTimeRange range, DateTimeRange cacheRange)
51 const std::vector<DateTimeRange>& ranges, DateTimeRange range, DateTimeRange cacheRange,
51 :_variable{variable}, _provider{provider},_ranges{ranges},_range{range},_cacheRange{cacheRange}
52 bool overwrite=true)
53 :_variable{variable}, _provider{provider},_ranges{ranges},_range{range},_cacheRange{cacheRange}, _overwrite{overwrite}
52 {
54 {
53 setAutoDelete(true);
55 setAutoDelete(true);
54 }
56 }
55 void run()override
57 void run()override
56 {
58 {
57 std::vector<IDataSeries*> data;
59 std::vector<IDataSeries*> data;
58 for(auto range:_ranges)
60 for(auto range:_ranges)
59 {
61 {
60 auto ds = _provider->getData(DataProviderParameters{{range}, _variable->metadata()});
62 auto ds = _provider->getData(DataProviderParameters{{range}, _variable->metadata()});
61 if(ds)
63 if(ds)
62 data.push_back(ds);
64 data.push_back(ds);
63 }
65 }
64 _variable->updateData(data, _range, _cacheRange, true);
66 if(_overwrite)
67 _variable->setData(data,_range, _cacheRange, true);
68 else
69 _variable->updateData(data, _range, _cacheRange, true);
65 emit transactionComplete();
70 emit transactionComplete();
66 }
71 }
67 signals:
72 signals:
68 void transactionComplete();
73 void transactionComplete();
69 };
74 };
70
75
71 class VCTransactionsQueues
76 class VCTransactionsQueues
72 {
77 {
73 QReadWriteLock _mutex{QReadWriteLock::Recursive};
78 QReadWriteLock _mutex{QReadWriteLock::Recursive};
74 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _nextTransactions;
79 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _nextTransactions;
75 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _pendingTransactions;
80 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> _pendingTransactions;
76 public:
81 public:
77 void addEntry(QUuid id)
82 void addEntry(QUuid id)
78 {
83 {
79 QWriteLocker lock{&_mutex};
84 QWriteLocker lock{&_mutex};
80 _nextTransactions[id] = std::nullopt;
85 _nextTransactions[id] = std::nullopt;
81 _pendingTransactions[id] = std::nullopt;
86 _pendingTransactions[id] = std::nullopt;
82 }
87 }
83
88
84 void removeEntry(QUuid id)
89 void removeEntry(QUuid id)
85 {
90 {
86 QWriteLocker lock{&_mutex};
91 QWriteLocker lock{&_mutex};
87 _nextTransactions.erase(id);
92 _nextTransactions.erase(id);
88 _pendingTransactions.erase(id);
93 _pendingTransactions.erase(id);
89 }
94 }
90
95
91 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> pendingTransactions()
96 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> pendingTransactions()
92 {
97 {
93 QReadLocker lock{&_mutex};
98 QReadLocker lock{&_mutex};
94 return _pendingTransactions;
99 return _pendingTransactions;
95 }
100 }
96
101
97 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> nextTransactions()
102 std::map<QUuid,std::optional<std::shared_ptr<VCTransaction>>> nextTransactions()
98 {
103 {
99 QReadLocker lock{&_mutex};
104 QReadLocker lock{&_mutex};
100 return _nextTransactions;
105 return _nextTransactions;
101 }
106 }
102
107
103 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
108 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
104 {
109 {
105 QWriteLocker lock{&_mutex};
110 QWriteLocker lock{&_mutex};
106 _pendingTransactions[id] = _nextTransactions[id];
111 _pendingTransactions[id] = _nextTransactions[id];
107 _nextTransactions[id] = std::nullopt;
112 _nextTransactions[id] = std::nullopt;
108 return _pendingTransactions[id];
113 return _pendingTransactions[id];
109 }
114 }
110
115
111 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
116 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
112 {
117 {
113 QWriteLocker lock{&_mutex};
118 QWriteLocker lock{&_mutex};
114 _nextTransactions[id] = transaction;
119 _nextTransactions[id] = transaction;
115 }
120 }
116
121
117 void complete(QUuid id)
122 void complete(QUuid id)
118 {
123 {
119 QWriteLocker lock{&_mutex};
124 QWriteLocker lock{&_mutex};
120 _pendingTransactions[id] = std::nullopt;
125 _pendingTransactions[id] = std::nullopt;
121 }
126 }
122
127
123 bool active(QUuid id)
128 bool active(QUuid id)
124 {
129 {
125 QReadLocker lock{&_mutex};
130 QReadLocker lock{&_mutex};
126 return _nextTransactions[id].has_value() || _pendingTransactions[id].has_value();
131 return _nextTransactions[id].has_value() || _pendingTransactions[id].has_value();
127 }
132 }
128 };
133 };
@@ -1,212 +1,225
1 #include <optional>
1 #include <optional>
2 #include <QMutex>
2 #include <QMutex>
3 #include <QReadWriteLock>
3 #include <QReadWriteLock>
4 #include <QThread>
4 #include <QThread>
5
5
6 #include "Variable/Variable.h"
6 #include "Variable/Variable.h"
7
7
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Data/DateTimeRange.h>
9 #include <Data/DateTimeRange.h>
10
10
11 #include <Common/debug.h>
11 #include <Common/debug.h>
12
12
13 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
13 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
14
14
15
15
16 /**
16 /**
17 * Searches in metadata for a value that can be converted to DataSeriesType
17 * Searches in metadata for a value that can be converted to DataSeriesType
18 * @param metadata the metadata where to search
18 * @param metadata the metadata where to search
19 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
19 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
20 * @sa DataSeriesType
20 * @sa DataSeriesType
21 */
21 */
22 static DataSeriesType findDataSeriesType(const QVariantHash &metadata)
22 static DataSeriesType findDataSeriesType(const QVariantHash &metadata)
23 {
23 {
24 auto dataSeriesType = DataSeriesType::UNKNOWN;
24 auto dataSeriesType = DataSeriesType::UNKNOWN;
25
25
26 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
26 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
27 for (auto it = metadata.cbegin(), end = metadata.cend();
27 for (auto it = metadata.cbegin(), end = metadata.cend();
28 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
28 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
29 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
29 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
30 }
30 }
31
31
32 return dataSeriesType;
32 return dataSeriesType;
33 }
33 }
34
34
35
35
36 #define VP_PROPERTY(property,getter,setter,type) \
36 #define VP_PROPERTY(property,getter,setter,type) \
37 type getter() noexcept\
37 type getter() noexcept\
38 {\
38 {\
39 QReadLocker lock{&m_Lock};\
39 QReadLocker lock{&m_Lock};\
40 return property;\
40 return property;\
41 }\
41 }\
42 void setter(const type& getter) noexcept\
42 void setter(const type& getter) noexcept\
43 {\
43 {\
44 QWriteLocker lock{&m_Lock};\
44 QWriteLocker lock{&m_Lock};\
45 property = getter;\
45 property = getter;\
46 }\
46 }\
47 type property;\
47 type property;\
48
48
49 #define V_FW_GETTER_SETTER(getter,setter, type)\
49 #define V_FW_GETTER_SETTER(getter,setter, type)\
50 type Variable::getter() const noexcept \
50 type Variable::getter() const noexcept \
51 {\
51 {\
52 return impl->getter();\
52 return impl->getter();\
53 }\
53 }\
54 void Variable::setter(const type& getter) noexcept \
54 void Variable::setter(const type& getter) noexcept \
55 {\
55 {\
56 impl->setter(getter);\
56 impl->setter(getter);\
57 emit updated(this->ID());\
57 emit updated(this->ID());\
58 }\
58 }\
59
59
60 struct Variable::VariablePrivate {
60 struct Variable::VariablePrivate {
61 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
61 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
62 : m_Name{name},
62 : m_Name{name},
63 m_Range{INVALID_RANGE},
63 m_Range{INVALID_RANGE},
64 m_CacheRange{INVALID_RANGE},
64 m_CacheRange{INVALID_RANGE},
65 m_Metadata{metadata},
65 m_Metadata{metadata},
66 m_DataSeries{nullptr},
66 m_DataSeries{nullptr},
67 m_RealRange{INVALID_RANGE},
67 m_RealRange{INVALID_RANGE},
68 m_NbPoints{0},
68 m_NbPoints{0},
69 m_Type{findDataSeriesType(m_Metadata)}
69 m_Type{findDataSeriesType(m_Metadata)}
70 {
70 {
71 }
71 }
72
72
73 VariablePrivate(const VariablePrivate &other)
73 VariablePrivate(const VariablePrivate &other)
74 : m_Name{other.m_Name},
74 : m_Name{other.m_Name},
75 m_Range{other.m_Range},
75 m_Range{other.m_Range},
76 m_CacheRange{other.m_CacheRange},
76 m_CacheRange{other.m_CacheRange},
77 m_Metadata{other.m_Metadata},
77 m_Metadata{other.m_Metadata},
78 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
78 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
79 m_RealRange{other.m_RealRange},
79 m_RealRange{other.m_RealRange},
80 m_NbPoints{other.m_NbPoints},
80 m_NbPoints{other.m_NbPoints},
81 m_Type{findDataSeriesType(m_Metadata)}
81 m_Type{findDataSeriesType(m_Metadata)}
82 {
82 {
83 }
83 }
84
84
85 void lockRead() { m_Lock.lockForRead(); }
85 void lockRead() { m_Lock.lockForRead(); }
86 void lockWrite() { m_Lock.lockForWrite(); }
86 void lockWrite() { m_Lock.lockForWrite(); }
87 void unlock() { m_Lock.unlock(); }
87 void unlock() { m_Lock.unlock(); }
88
88
89 void purgeDataSeries()
89 void purgeDataSeries()
90 {
90 {
91 if (m_DataSeries) {
91 if (m_DataSeries) {
92 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
92 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
93 }
93 }
94 updateRealRange();
94 updateRealRange();
95 updateNbPoints();
95 updateNbPoints();
96 }
96 }
97 void mergeDataSeries(const std::vector<IDataSeries*>& dataseries)
97 void mergeDataSeries(const std::vector<IDataSeries*>& dataseries, bool overwrite=false)
98 {
98 {
99 QWriteLocker lock{&m_Lock};
99 QWriteLocker lock{&m_Lock};
100 for(auto ds:dataseries)
100 for(auto ds:dataseries)
101 {
101 {
102 if(m_DataSeries)
102 if(!overwrite & bool(m_DataSeries))
103 m_DataSeries->merge(ds);
103 m_DataSeries->merge(ds);
104 else
104 else
105 m_DataSeries = ds->clone();
105 m_DataSeries = ds->clone();
106 }
106 }
107 }
107 }
108 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
108 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
109
109
110 /// Updates real range according to current variable range and data series
110 /// Updates real range according to current variable range and data series
111 void updateRealRange()
111 void updateRealRange()
112 {
112 {
113 if (m_DataSeries) {
113 if (m_DataSeries) {
114 auto lock = m_DataSeries->getReadLock();
114 auto lock = m_DataSeries->getReadLock();
115 auto end = m_DataSeries->cend();
115 auto end = m_DataSeries->cend();
116 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
116 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
117 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
117 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
118 if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
118 if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
119 m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()};
119 m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()};
120 else
120 else
121 m_RealRange = std::nullopt;
121 m_RealRange = std::nullopt;
122 }
122 }
123 else {
123 else {
124 m_RealRange = std::nullopt;
124 m_RealRange = std::nullopt;
125 }
125 }
126 }
126 }
127
127
128 VP_PROPERTY(m_Name, name, setName, QString)
128 VP_PROPERTY(m_Name, name, setName, QString)
129 VP_PROPERTY(m_Range, range, setRange, DateTimeRange)
129 VP_PROPERTY(m_Range, range, setRange, DateTimeRange)
130 VP_PROPERTY(m_CacheRange, cacheRange, setCacheRange, DateTimeRange)
130 VP_PROPERTY(m_CacheRange, cacheRange, setCacheRange, DateTimeRange)
131 VP_PROPERTY(m_Metadata, metadata, setMetadata, QVariantHash)
131 VP_PROPERTY(m_Metadata, metadata, setMetadata, QVariantHash)
132 VP_PROPERTY(m_DataSeries, dataSeries, setDataSeries, std::shared_ptr<IDataSeries>)
132 VP_PROPERTY(m_DataSeries, dataSeries, setDataSeries, std::shared_ptr<IDataSeries>)
133 VP_PROPERTY(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
133 VP_PROPERTY(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
134 unsigned int m_NbPoints;
134 unsigned int m_NbPoints;
135 VP_PROPERTY(m_Type, type, setType, DataSeriesType)
135 VP_PROPERTY(m_Type, type, setType, DataSeriesType)
136 QReadWriteLock m_Lock;
136 QReadWriteLock m_Lock;
137 };
137 };
138
138
139 Variable::Variable(const QString &name, const QVariantHash &metadata)
139 Variable::Variable(const QString &name, const QVariantHash &metadata)
140 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
140 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
141 _uuid{QUuid::createUuid()}
141 _uuid{QUuid::createUuid()}
142 {
142 {
143 }
143 }
144
144
145 Variable::Variable(const Variable &other)
145 Variable::Variable(const Variable &other)
146 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
146 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
147 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
147 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
148 {
148 {
149 }
149 }
150
150
151 std::shared_ptr<Variable> Variable::clone() const
151 std::shared_ptr<Variable> Variable::clone() const
152 {
152 {
153 return std::make_shared<Variable>(*this);
153 return std::make_shared<Variable>(*this);
154 }
154 }
155
155
156 V_FW_GETTER_SETTER(name,setName,QString)
156 V_FW_GETTER_SETTER(name,setName,QString)
157
157
158 DateTimeRange Variable::range() const noexcept
158 DateTimeRange Variable::range() const noexcept
159 {
159 {
160 return impl->range();
160 return impl->range();
161 }
161 }
162
162
163 void Variable::setRange(const DateTimeRange &range, bool notify) noexcept
163 void Variable::setRange(const DateTimeRange &range, bool notify) noexcept
164 {
164 {
165 impl->setRange(range);
165 impl->setRange(range);
166 impl->updateRealRange();
166 impl->updateRealRange();
167 if(notify)
167 if(notify)
168 emit this->updated(this->ID());
168 emit this->updated(this->ID());
169 }
169 }
170
170
171 V_FW_GETTER_SETTER(cacheRange, setCacheRange, DateTimeRange)
171 V_FW_GETTER_SETTER(cacheRange, setCacheRange, DateTimeRange)
172
172
173 unsigned int Variable::nbPoints() const noexcept
173 unsigned int Variable::nbPoints() const noexcept
174 {
174 {
175 return impl->m_NbPoints;
175 return impl->m_NbPoints;
176 }
176 }
177
177
178 std::optional<DateTimeRange> Variable::realRange() const noexcept
178 std::optional<DateTimeRange> Variable::realRange() const noexcept
179 {
179 {
180 return impl->realRange();
180 return impl->realRange();
181 }
181 }
182
182
183 void Variable::updateData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
183 void Variable::updateData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
184 {
184 {
185 {
185 {
186 QWriteLocker lock{&m_lock};
186 QWriteLocker lock{&m_lock};
187 impl->mergeDataSeries(dataSeries);
187 impl->mergeDataSeries(dataSeries);
188 impl->setRange(newRange);
188 impl->setRange(newRange);
189 impl->setCacheRange(newCacheRange);
189 impl->setCacheRange(newCacheRange);
190 impl->purgeDataSeries();
190 impl->purgeDataSeries();
191 }
191 }
192 if(notify)
192 if(notify)
193 emit updated(this->ID());
193 emit updated(this->ID());
194 }
194 }
195
195
196 void Variable::setData(const std::vector<IDataSeries *> &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify)
197 {
198 {
199 QWriteLocker lock{&m_lock};
200 impl->mergeDataSeries(dataSeries, true);
201 impl->setRange(newRange);
202 impl->setCacheRange(newCacheRange);
203 impl->purgeDataSeries();
204 }
205 if(notify)
206 emit updated(this->ID());
207 }
208
196 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
209 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
197 {
210 {
198 return impl->dataSeries();
211 return impl->dataSeries();
199 }
212 }
200
213
201 DataSeriesType Variable::type() const noexcept
214 DataSeriesType Variable::type() const noexcept
202 {
215 {
203 return impl->type();
216 return impl->type();
204 }
217 }
205
218
206 QVariantHash Variable::metadata() const noexcept
219 QVariantHash Variable::metadata() const noexcept
207 {
220 {
208 impl->lockRead();
221 impl->lockRead();
209 auto metadata = impl->m_Metadata;
222 auto metadata = impl->m_Metadata;
210 impl->unlock();
223 impl->unlock();
211 return metadata;
224 return metadata;
212 }
225 }
@@ -1,399 +1,412
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
20 class VariableController2::VariableController2Private
19 class VariableController2::VariableController2Private
21 {
20 {
22 struct threadSafeVaraiblesMaps
21 struct threadSafeVaraiblesMaps
23 {
22 {
24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
23 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
25 {
24 {
26 QWriteLocker lock{&_lock};
25 QWriteLocker lock{&_lock};
27 _variables[*variable] = variable;
26 _variables[*variable] = variable;
28 _providers[*variable] = provider;
27 _providers[*variable] = provider;
29 _synchronizationGroups[*variable] = synchronizationGroup;
28 _synchronizationGroups[*variable] = synchronizationGroup;
30 }
29 }
31
30
32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
31 inline void removeVariable(const std::shared_ptr<Variable>& variable)
33 {
32 {
34 QWriteLocker lock{&_lock};
33 QWriteLocker lock{&_lock};
35 _variables.erase(*variable);
34 _variables.erase(*variable);
36 _providers.remove(*variable);
35 _providers.remove(*variable);
37 _synchronizationGroups.remove(*variable);
36 _synchronizationGroups.remove(*variable);
38 }
37 }
39
38
40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
39 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
41 {
40 {
42 QWriteLocker lock{&_lock};
41 QWriteLocker lock{&_lock};
43 if(with.has_value())
42 if(with.has_value())
44 {
43 {
45 auto newGroup = _synchronizationGroups[*with.value()];
44 auto newGroup = _synchronizationGroups[*with.value()];
46 newGroup->addVariable(*variable);
45 newGroup->addVariable(*variable);
47 _synchronizationGroups[*variable] = newGroup;
46 _synchronizationGroups[*variable] = newGroup;
48 }
47 }
49 else
48 else
50 {
49 {
51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
50 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
52 }
51 }
53 }
52 }
54
53
55 inline std::shared_ptr<Variable> variable(QUuid variable)
54 inline std::shared_ptr<Variable> variable(QUuid variable)
56 {
55 {
57 QReadLocker lock{&_lock};
56 QReadLocker lock{&_lock};
58 auto it = _variables.find(variable);
57 auto it = _variables.find(variable);
59 [[unlikely]]
58 [[unlikely]]
60 if(it==_variables.end())
59 if(it==_variables.end())
61 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
60 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
62 return (*it).second;
61 return (*it).second;
63 }
62 }
64
63
65 inline std::shared_ptr<Variable> variable(int index)
64 inline std::shared_ptr<Variable> variable(int index)
66 {
65 {
67 QReadLocker lock{&_lock};
66 QReadLocker lock{&_lock};
68 [[unlikely]]
67 [[unlikely]]
69 if(!_variables.size() > index)
68 if(!_variables.size() > index)
70 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
69 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
71 auto it = _variables.cbegin();
70 auto it = _variables.cbegin();
72 while (index!=0) {
71 while (index!=0) {
73 index-=1;
72 index-=1;
74 it++;
73 it++;
75 }
74 }
76 return (*it).second;
75 return (*it).second;
77 }
76 }
78
77
79 inline const std::vector<std::shared_ptr<Variable>> variables()
78 inline const std::vector<std::shared_ptr<Variable>> variables()
80 {
79 {
81 std::vector<std::shared_ptr<Variable>> vars;
80 std::vector<std::shared_ptr<Variable>> vars;
82 QReadLocker lock{&_lock};
81 QReadLocker lock{&_lock};
83 for(const auto&[id, var]:_variables)
82 for(const auto&[id, var]:_variables)
84 {
83 {
85 vars.push_back(var);
84 vars.push_back(var);
86 }
85 }
87 return vars;
86 return vars;
88 }
87 }
89
88
90 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
89 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
91 {
90 {
92 QReadLocker lock{&_lock};
91 QReadLocker lock{&_lock};
93 [[unlikely]]
92 [[unlikely]]
94 if(!_providers.contains(variable))
93 if(!_providers.contains(variable))
95 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
94 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
96 return _providers[variable];
95 return _providers[variable];
97 }
96 }
98
97
99 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
98 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
100 {
99 {
101 QReadLocker lock{&_lock};
100 QReadLocker lock{&_lock};
102 [[unlikely]]
101 [[unlikely]]
103 if(!_synchronizationGroups.contains(variable))
102 if(!_synchronizationGroups.contains(variable))
104 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
103 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
105 return _synchronizationGroups[variable];
104 return _synchronizationGroups[variable];
106 }
105 }
107
106
108 inline bool has(const std::shared_ptr<Variable>& variable)
107 inline bool has(const std::shared_ptr<Variable>& variable)
109 {
108 {
110 QReadLocker lock{&_lock};
109 QReadLocker lock{&_lock};
111 return _variables.find(*variable)==_variables.end();
110 return _variables.find(*variable)==_variables.end();
112 }
111 }
113
112
114 private:
113 private:
115 std::map<QUuid,std::shared_ptr<Variable>> _variables;
114 std::map<QUuid,std::shared_ptr<Variable>> _variables;
116 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
115 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
117 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
116 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
118 QReadWriteLock _lock{QReadWriteLock::Recursive};
117 QReadWriteLock _lock{QReadWriteLock::Recursive};
119 }_maps;
118 }_maps;
120 QThreadPool* _ThreadPool;
119 QThreadPool* _ThreadPool;
121 VCTransactionsQueues _transactions;
120 VCTransactionsQueues _transactions;
122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
121 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
123
122
124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
123 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
125 {
124 {
126 if(transaction->done())
125 if(transaction->done())
127 {
126 {
128 _transactions.complete(group);
127 _transactions.complete(group);
129 }
128 }
130 this->_processTransactions();
129 this->_processTransactions();
131 }
130 }
132
131
133 void _processTransactions()
132 void _processTransactions(bool fragmented=false)
134 {
133 {
135 auto nextTransactions = _transactions.nextTransactions();
134 auto nextTransactions = _transactions.nextTransactions();
136 auto pendingTransactions = _transactions.pendingTransactions();
135 auto pendingTransactions = _transactions.pendingTransactions();
137 for( auto [groupID, newTransaction] : nextTransactions)
136 for( auto [groupID, newTransaction] : nextTransactions)
138 {
137 {
139 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
138 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
140 {
139 {
141 _transactions.start(groupID);
140 _transactions.start(groupID);
142 auto refVar = _maps.variable(newTransaction.value()->refVar);
141 auto refVar = _maps.variable(newTransaction.value()->refVar);
143 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
142 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
144 for( auto const& [ID, range] : ranges)
143 for( auto const& [ID, range] : ranges)
145 {
144 {
146 auto provider = _maps.provider(ID);
145 auto provider = _maps.provider(ID);
147 auto variable = _maps.variable(ID);
146 auto variable = _maps.variable(ID);
148 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
147 if(fragmented)
149
148 {
150 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
149 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
151 QObject::connect(exe,
150
152 &TransactionExe::transactionComplete,
151 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
153 [groupID=groupID,transaction=newTransaction.value(),this]()
152 QObject::connect(exe,
154 {
153 &TransactionExe::transactionComplete,
155 this->_transactionComplete(groupID, transaction);
154 [groupID=groupID,transaction=newTransaction.value(),this]()
156 }
155 {
157 );
156 this->_transactionComplete(groupID, transaction);
158 _ThreadPool->start(exe);
157 }
159
158 );
159 _ThreadPool->start(exe);
160 }
161 else
162 {
163 auto exe = new TransactionExe(variable, provider, {range}, range, range);
164 QObject::connect(exe,
165 &TransactionExe::transactionComplete,
166 [groupID=groupID,transaction=newTransaction.value(),this]()
167 {
168 this->_transactionComplete(groupID, transaction);
169 }
170 );
171 _ThreadPool->start(exe);
172 }
160 }
173 }
161 }
174 }
162 }
175 }
163 }
176 }
164
177
165 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
178 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
166 {
179 {
167 std::map<QUuid,DateTimeRange> ranges;
180 std::map<QUuid,DateTimeRange> ranges;
168 if(!DateTimeRangeHelper::hasnan(r))
181 if(!DateTimeRangeHelper::hasnan(r))
169 {
182 {
170 auto group = _maps.group(*refVar);
183 auto group = _maps.group(*refVar);
171 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
184 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
172 transformation.has_value())
185 transformation.has_value())
173 {
186 {
174 for(auto varId:group->variables())
187 for(auto varId:group->variables())
175 {
188 {
176 auto var = _maps.variable(varId);
189 auto var = _maps.variable(varId);
177 auto newRange = var->range().transform(transformation.value());
190 auto newRange = var->range().transform(transformation.value());
178 ranges[varId] = newRange;
191 ranges[varId] = newRange;
179 }
192 }
180 }
193 }
181 else // force new range to all variables -> may be weird if more than one var in the group
194 else // force new range to all variables -> may be weird if more than one var in the group
182 // @TODO ensure that there is no side effects
195 // @TODO ensure that there is no side effects
183 {
196 {
184 for(auto varId:group->variables())
197 for(auto varId:group->variables())
185 {
198 {
186 auto var = _maps.variable(varId);
199 auto var = _maps.variable(varId);
187 ranges[varId] = r;
200 ranges[varId] = r;
188 }
201 }
189 }
202 }
190 }
203 }
191 else
204 else
192 {
205 {
193 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
206 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
194 }
207 }
195 return ranges;
208 return ranges;
196 }
209 }
197
210
198 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
211 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
199 {
212 {
200 DateTimeRange newCacheRange;
213 DateTimeRange newCacheRange;
201 std::vector<DateTimeRange> missingRanges;
214 std::vector<DateTimeRange> missingRanges;
202 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
215 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
203 {
216 {
204 newCacheRange = _cacheStrategy->computeRange(r,r);
217 newCacheRange = _cacheStrategy->computeRange(r,r);
205 missingRanges = {newCacheRange};
218 missingRanges = {newCacheRange};
206 }
219 }
207 else
220 else
208 {
221 {
209 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
222 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
210 missingRanges = newCacheRange - var->cacheRange();
223 missingRanges = newCacheRange - var->cacheRange();
211 }
224 }
212 return {missingRanges,newCacheRange};
225 return {missingRanges,newCacheRange};
213 }
226 }
214
227
215 void _changeRange(QUuid id, DateTimeRange r)
228 void _changeRange(QUuid id, DateTimeRange r)
216 {
229 {
217 _changeRange(_maps.variable(id) ,r);
230 _changeRange(_maps.variable(id) ,r);
218 }
231 }
219 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
232 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
220 {
233 {
221 auto provider = _maps.provider(*var);
234 auto provider = _maps.provider(*var);
222 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
235 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
223 std::vector<IDataSeries*> data;
236 std::vector<IDataSeries*> data;
224 for(auto range:missingRanges)
237 for(auto range:missingRanges)
225 {
238 {
226 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
239 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
227 }
240 }
228 var->updateData(data, r, newCacheRange, true);
241 var->updateData(data, r, newCacheRange, true);
229 }
242 }
230 public:
243 public:
231 VariableController2Private(QObject* parent=Q_NULLPTR)
244 VariableController2Private(QObject* parent=Q_NULLPTR)
232 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
245 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
233 {
246 {
234 Q_UNUSED(parent);
247 Q_UNUSED(parent);
235 this->_ThreadPool = new QThreadPool();
248 this->_ThreadPool = new QThreadPool();
236 this->_ThreadPool->setMaxThreadCount(32);
249 this->_ThreadPool->setMaxThreadCount(32);
237 }
250 }
238
251
239 /*
252 /*
240 * This dtor has to like this even if this is ugly, because default dtor would rely on
253 * This dtor has to like this even if this is ugly, because default dtor would rely on
241 * declaration order to destruct members and that would always lead to regressions when
254 * declaration order to destruct members and that would always lead to regressions when
242 * modifying class members
255 * modifying class members
243 */
256 */
244 ~VariableController2Private()
257 ~VariableController2Private()
245 {
258 {
246 delete this->_ThreadPool;
259 delete this->_ThreadPool;
247 }
260 }
248
261
249 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
262 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
250 {
263 {
251 auto newVar = std::make_shared<Variable>(name,metadata);
264 auto newVar = std::make_shared<Variable>(name,metadata);
252 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
265 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
253 _maps.addVariable(newVar,std::move(provider),group);
266 _maps.addVariable(newVar,std::move(provider),group);
254 this->_transactions.addEntry(*group);
267 this->_transactions.addEntry(*group);
255 return newVar;
268 return newVar;
256 }
269 }
257
270
258 std::shared_ptr<Variable> variable(QUuid ID)
271 std::shared_ptr<Variable> variable(QUuid ID)
259 {
272 {
260 return _maps.variable(ID);
273 return _maps.variable(ID);
261 }
274 }
262
275
263 std::shared_ptr<Variable> variable(int index)
276 std::shared_ptr<Variable> variable(int index)
264 {
277 {
265 return _maps.variable(index);
278 return _maps.variable(index);
266 }
279 }
267
280
268 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
281 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
269 {
282 {
270 auto newVar = variable->clone();
283 auto newVar = variable->clone();
271 _maps.synchronize(newVar,std::nullopt);
284 _maps.synchronize(newVar,std::nullopt);
272 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
285 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
273 this->_transactions.addEntry(*_maps.group(*newVar));
286 this->_transactions.addEntry(*_maps.group(*newVar));
274 return newVar;
287 return newVar;
275 }
288 }
276
289
277 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
290 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
278 {
291 {
279 return _transactions.active(*_maps.group(*variable));
292 return _transactions.active(*_maps.group(*variable));
280 }
293 }
281
294
282 bool hasPendingTransactions()
295 bool hasPendingTransactions()
283 {
296 {
284 bool has = false;
297 bool has = false;
285 for(const auto& var:_maps.variables())
298 for(const auto& var:_maps.variables())
286 {
299 {
287 has |= _transactions.active(*_maps.group(*var));
300 has |= _transactions.active(*_maps.group(*var));
288 }
301 }
289 return has;
302 return has;
290 }
303 }
291
304
292 void deleteVariable(const std::shared_ptr<Variable>& variable)
305 void deleteVariable(const std::shared_ptr<Variable>& variable)
293 {
306 {
294 _maps.removeVariable(variable);
307 _maps.removeVariable(variable);
295 }
308 }
296
309
297 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
310 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
298 {
311 {
299 if(!DateTimeRangeHelper::hasnan(r))
312 if(!DateTimeRangeHelper::hasnan(r))
300 {
313 {
301 auto group = _maps.group(*variable);
314 auto group = _maps.group(*variable);
302 // Just overwrite next transaction
315 // Just overwrite next transaction
303 {
316 {
304 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
317 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
305 }
318 }
306 _processTransactions();
319 _processTransactions();
307 }
320 }
308 else
321 else
309 {
322 {
310 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
323 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
311 }
324 }
312 }
325 }
313
326
314 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
327 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
315 {
328 {
316 asyncChangeRange(variable,r);
329 asyncChangeRange(variable,r);
317 while (hasPendingTransactions(variable))
330 while (hasPendingTransactions(variable))
318 {
331 {
319 QCoreApplication::processEvents();
332 QCoreApplication::processEvents();
320 }
333 }
321 }
334 }
322
335
323 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
336 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
324 {
337 {
325 _maps.synchronize(var, with);
338 _maps.synchronize(var, with);
326 }
339 }
327
340
328 inline const std::vector<std::shared_ptr<Variable>> variables()
341 inline const std::vector<std::shared_ptr<Variable>> variables()
329 {
342 {
330 return _maps.variables();
343 return _maps.variables();
331 }
344 }
332
345
333 };
346 };
334
347
335 VariableController2::VariableController2()
348 VariableController2::VariableController2()
336 :impl{spimpl::make_unique_impl<VariableController2Private>()}
349 :impl{spimpl::make_unique_impl<VariableController2Private>()}
337 {}
350 {}
338
351
339 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
352 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
340 {
353 {
341 auto var = impl->createVariable(name, metadata, provider);
354 auto var = impl->createVariable(name, metadata, provider);
342 var->setRange(range); // even with no data this is it's range
355 var->setRange(range); // even with no data this is it's range
343 emit variableAdded(var);
356 emit variableAdded(var);
344 if(!DateTimeRangeHelper::hasnan(range))
357 if(!DateTimeRangeHelper::hasnan(range))
345 impl->asyncChangeRange(var,range);
358 impl->asyncChangeRange(var,range);
346 else
359 else
347 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
360 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
348 return var;
361 return var;
349 }
362 }
350
363
351 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
364 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
352 {
365 {
353 return impl->cloneVariable(variable);
366 return impl->cloneVariable(variable);
354 }
367 }
355
368
356 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
369 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
357 {
370 {
358 impl->deleteVariable(variable);
371 impl->deleteVariable(variable);
359 emit variableDeleted(variable);
372 emit variableDeleted(variable);
360 }
373 }
361
374
362 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
375 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
363 {
376 {
364 impl->changeRange(variable, r);
377 impl->changeRange(variable, r);
365 }
378 }
366
379
367 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
380 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
368 {
381 {
369 impl->asyncChangeRange(variable, r);
382 impl->asyncChangeRange(variable, r);
370 }
383 }
371
384
372 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
385 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
373 {
386 {
374 return impl->variables();
387 return impl->variables();
375 }
388 }
376
389
377 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
390 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
378 {
391 {
379 return !impl->hasPendingTransactions(variable);
392 return !impl->hasPendingTransactions(variable);
380 }
393 }
381
394
382 bool VariableController2::isReady()
395 bool VariableController2::isReady()
383 {
396 {
384 return !impl->hasPendingTransactions();
397 return !impl->hasPendingTransactions();
385 }
398 }
386
399
387 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
400 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
388 {
401 {
389 impl->synchronize(var, with);
402 impl->synchronize(var, with);
390 }
403 }
391
404
392 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
405 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
393 {
406 {
394 std::vector<std::shared_ptr<Variable>> variables;
407 std::vector<std::shared_ptr<Variable>> variables;
395 for (const auto& id : ids) {
408 for (const auto& id : ids) {
396 variables.push_back(impl->variable(id));
409 variables.push_back(impl->variable(id));
397 }
410 }
398 return variables;
411 return variables;
399 }
412 }
General Comments 0
You need to be logged in to leave comments. Login now