##// END OF EJS Templates
Calls purge() method when setting cache range or data series of a variable
Alexandre Leroux -
r630:0efbd3cc5e8d
parent child
Show More
@@ -1,75 +1,74
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataSeriesIterator.h>
6 #include <Data/DataSeriesIterator.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11
11
12 #include <Common/MetaTypes.h>
12 #include <Common/MetaTypes.h>
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16
16
17 class IDataSeries;
17 class IDataSeries;
18 class QString;
18 class QString;
19
19
20 /**
20 /**
21 * @brief The Variable class represents a variable in SciQlop.
21 * @brief The Variable class represents a variable in SciQlop.
22 */
22 */
23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24
24
25 Q_OBJECT
25 Q_OBJECT
26
26
27 public:
27 public:
28 explicit Variable(const QString &name, const SqpRange &dateTime,
28 explicit Variable(const QString &name, const SqpRange &dateTime,
29 const QVariantHash &metadata = {});
29 const QVariantHash &metadata = {});
30
30
31 QString name() const noexcept;
31 QString name() const noexcept;
32 SqpRange range() const noexcept;
32 SqpRange range() const noexcept;
33 void setRange(const SqpRange &range) noexcept;
33 void setRange(const SqpRange &range) noexcept;
34 SqpRange cacheRange() const noexcept;
34 SqpRange cacheRange() const noexcept;
35 void setCacheRange(const SqpRange &cacheRange) noexcept;
35 void setCacheRange(const SqpRange &cacheRange) noexcept;
36
36
37 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
37 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
38 /// series between the range of the variable. The real range is updated each time the variable
38 /// series between the range of the variable. The real range is updated each time the variable
39 /// range or the data series changed
39 /// range or the data series changed
40 /// @return the real range, invalid range if the data series is null or empty
40 /// @return the real range, invalid range if the data series is null or empty
41 /// @sa setDataSeries()
41 /// @sa setDataSeries()
42 /// @sa setRange()
42 /// @sa setRange()
43 SqpRange realRange() const noexcept;
43 SqpRange realRange() const noexcept;
44
44
45 /// @return the data of the variable, nullptr if there is no data
45 /// @return the data of the variable, nullptr if there is no data
46 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
46 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
47
47
48 QVariantHash metadata() const noexcept;
48 QVariantHash metadata() const noexcept;
49
49
50 bool contains(const SqpRange &range) const noexcept;
50 bool contains(const SqpRange &range) const noexcept;
51 bool intersect(const SqpRange &range) const noexcept;
51 bool intersect(const SqpRange &range) const noexcept;
52 bool isInside(const SqpRange &range) const noexcept;
52 bool isInside(const SqpRange &range) const noexcept;
53
53
54 bool cacheContains(const SqpRange &range) const noexcept;
54 bool cacheContains(const SqpRange &range) const noexcept;
55 bool cacheIntersect(const SqpRange &range) const noexcept;
55 bool cacheIntersect(const SqpRange &range) const noexcept;
56 bool cacheIsInside(const SqpRange &range) const noexcept;
56 bool cacheIsInside(const SqpRange &range) const noexcept;
57
57
58 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
58 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
59 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
59 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
60 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
61 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
60 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
62
61
63 signals:
62 signals:
64 void updated();
63 void updated();
65
64
66 private:
65 private:
67 class VariablePrivate;
66 class VariablePrivate;
68 spimpl::unique_impl_ptr<VariablePrivate> impl;
67 spimpl::unique_impl_ptr<VariablePrivate> impl;
69 };
68 };
70
69
71 // Required for using shared_ptr in signals/slots
70 // Required for using shared_ptr in signals/slots
72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
71 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
73 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
74
73
75 #endif // SCIQLOP_VARIABLE_H
74 #endif // SCIQLOP_VARIABLE_H
@@ -1,279 +1,270
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/SqpRange.h>
4 #include <Data/SqpRange.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11
11
12 struct Variable::VariablePrivate {
12 struct Variable::VariablePrivate {
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
14 const QVariantHash &metadata)
14 const QVariantHash &metadata)
15 : m_Name{name},
15 : m_Name{name},
16 m_Range{dateTime},
16 m_Range{dateTime},
17 m_Metadata{metadata},
17 m_Metadata{metadata},
18 m_DataSeries{nullptr},
18 m_DataSeries{nullptr},
19 m_RealRange{INVALID_RANGE}
19 m_RealRange{INVALID_RANGE}
20 {
20 {
21 }
21 }
22
22
23 void lockRead() { m_Lock.lockForRead(); }
23 void lockRead() { m_Lock.lockForRead(); }
24 void lockWrite() { m_Lock.lockForWrite(); }
24 void lockWrite() { m_Lock.lockForWrite(); }
25 void unlock() { m_Lock.unlock(); }
25 void unlock() { m_Lock.unlock(); }
26
26
27 void purgeDataSeries()
28 {
29 if (m_DataSeries) {
30 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
31 }
32 updateRealRange();
33 }
34
27 /// Updates real range according to current variable range and data series
35 /// Updates real range according to current variable range and data series
28 void updateRealRange()
36 void updateRealRange()
29 {
37 {
30 if (m_DataSeries) {
38 if (m_DataSeries) {
31 m_DataSeries->lockRead();
39 m_DataSeries->lockRead();
32 auto end = m_DataSeries->cend();
40 auto end = m_DataSeries->cend();
33 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
41 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
34 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
42 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
35
43
36 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
44 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
37 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
45 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
38 : INVALID_RANGE;
46 : INVALID_RANGE;
39 m_DataSeries->unlock();
47 m_DataSeries->unlock();
40 }
48 }
41 else {
49 else {
42 m_RealRange = INVALID_RANGE;
50 m_RealRange = INVALID_RANGE;
43 }
51 }
44 }
52 }
45
53
46 QString m_Name;
54 QString m_Name;
47
55
48 SqpRange m_Range;
56 SqpRange m_Range;
49 SqpRange m_CacheRange;
57 SqpRange m_CacheRange;
50 QVariantHash m_Metadata;
58 QVariantHash m_Metadata;
51 std::shared_ptr<IDataSeries> m_DataSeries;
59 std::shared_ptr<IDataSeries> m_DataSeries;
52 SqpRange m_RealRange;
60 SqpRange m_RealRange;
53
61
54 QReadWriteLock m_Lock;
62 QReadWriteLock m_Lock;
55 };
63 };
56
64
57 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
65 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
58 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
66 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
59 {
67 {
60 }
68 }
61
69
62 QString Variable::name() const noexcept
70 QString Variable::name() const noexcept
63 {
71 {
64 impl->lockRead();
72 impl->lockRead();
65 auto name = impl->m_Name;
73 auto name = impl->m_Name;
66 impl->unlock();
74 impl->unlock();
67 return name;
75 return name;
68 }
76 }
69
77
70 SqpRange Variable::range() const noexcept
78 SqpRange Variable::range() const noexcept
71 {
79 {
72 impl->lockRead();
80 impl->lockRead();
73 auto range = impl->m_Range;
81 auto range = impl->m_Range;
74 impl->unlock();
82 impl->unlock();
75 return range;
83 return range;
76 }
84 }
77
85
78 void Variable::setRange(const SqpRange &range) noexcept
86 void Variable::setRange(const SqpRange &range) noexcept
79 {
87 {
80 impl->lockWrite();
88 impl->lockWrite();
81 impl->m_Range = range;
89 impl->m_Range = range;
82 impl->updateRealRange();
90 impl->updateRealRange();
83 impl->unlock();
91 impl->unlock();
84 }
92 }
85
93
86 SqpRange Variable::cacheRange() const noexcept
94 SqpRange Variable::cacheRange() const noexcept
87 {
95 {
88 impl->lockRead();
96 impl->lockRead();
89 auto cacheRange = impl->m_CacheRange;
97 auto cacheRange = impl->m_CacheRange;
90 impl->unlock();
98 impl->unlock();
91 return cacheRange;
99 return cacheRange;
92 }
100 }
93
101
94 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
102 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
95 {
103 {
96 impl->lockWrite();
104 impl->lockWrite();
97 impl->m_CacheRange = cacheRange;
105 if (cacheRange != impl->m_CacheRange) {
106 impl->m_CacheRange = cacheRange;
107 impl->purgeDataSeries();
108 }
98 impl->unlock();
109 impl->unlock();
99 }
110 }
100
111
101 SqpRange Variable::realRange() const noexcept
112 SqpRange Variable::realRange() const noexcept
102 {
113 {
103 return impl->m_RealRange;
114 return impl->m_RealRange;
104 }
115 }
105
116
106 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
107 {
108 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
109 << QThread::currentThread()->objectName();
110 if (!dataSeries) {
111 /// @todo ALX : log
112 return;
113 }
114 impl->lockWrite();
115 impl->m_DataSeries = dataSeries->clone();
116 impl->updateRealRange();
117 impl->unlock();
118 }
119
120 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
117 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
121 {
118 {
122 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
119 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
123 << QThread::currentThread()->objectName();
120 << QThread::currentThread()->objectName();
124 if (!dataSeries) {
121 if (!dataSeries) {
125 /// @todo ALX : log
122 /// @todo ALX : log
126 return;
123 return;
127 }
124 }
128
125
129 // Add or merge the data
126 // Add or merge the data
130 // Inits the data series of the variable
131 impl->lockWrite();
127 impl->lockWrite();
132 if (!impl->m_DataSeries) {
128 if (!impl->m_DataSeries) {
133 impl->m_DataSeries = dataSeries->clone();
129 impl->m_DataSeries = dataSeries->clone();
134 }
130 }
135 else {
131 else {
136 impl->m_DataSeries->merge(dataSeries.get());
132 impl->m_DataSeries->merge(dataSeries.get());
137 }
133 }
134 impl->purgeDataSeries();
138 impl->unlock();
135 impl->unlock();
139
140 // sub the data
141 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
142 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
143 this->setDataSeries(subData);
144 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
145 }
136 }
146
137
147 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
138 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
148 {
139 {
149 impl->lockRead();
140 impl->lockRead();
150 auto dataSeries = impl->m_DataSeries;
141 auto dataSeries = impl->m_DataSeries;
151 impl->unlock();
142 impl->unlock();
152
143
153 return dataSeries;
144 return dataSeries;
154 }
145 }
155
146
156 QVariantHash Variable::metadata() const noexcept
147 QVariantHash Variable::metadata() const noexcept
157 {
148 {
158 impl->lockRead();
149 impl->lockRead();
159 auto metadata = impl->m_Metadata;
150 auto metadata = impl->m_Metadata;
160 impl->unlock();
151 impl->unlock();
161 return metadata;
152 return metadata;
162 }
153 }
163
154
164 bool Variable::contains(const SqpRange &range) const noexcept
155 bool Variable::contains(const SqpRange &range) const noexcept
165 {
156 {
166 impl->lockRead();
157 impl->lockRead();
167 auto res = impl->m_Range.contains(range);
158 auto res = impl->m_Range.contains(range);
168 impl->unlock();
159 impl->unlock();
169 return res;
160 return res;
170 }
161 }
171
162
172 bool Variable::intersect(const SqpRange &range) const noexcept
163 bool Variable::intersect(const SqpRange &range) const noexcept
173 {
164 {
174
165
175 impl->lockRead();
166 impl->lockRead();
176 auto res = impl->m_Range.intersect(range);
167 auto res = impl->m_Range.intersect(range);
177 impl->unlock();
168 impl->unlock();
178 return res;
169 return res;
179 }
170 }
180
171
181 bool Variable::isInside(const SqpRange &range) const noexcept
172 bool Variable::isInside(const SqpRange &range) const noexcept
182 {
173 {
183 impl->lockRead();
174 impl->lockRead();
184 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
175 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
185 impl->unlock();
176 impl->unlock();
186 return res;
177 return res;
187 }
178 }
188
179
189 bool Variable::cacheContains(const SqpRange &range) const noexcept
180 bool Variable::cacheContains(const SqpRange &range) const noexcept
190 {
181 {
191 impl->lockRead();
182 impl->lockRead();
192 auto res = impl->m_CacheRange.contains(range);
183 auto res = impl->m_CacheRange.contains(range);
193 impl->unlock();
184 impl->unlock();
194 return res;
185 return res;
195 }
186 }
196
187
197 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
188 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
198 {
189 {
199 impl->lockRead();
190 impl->lockRead();
200 auto res = impl->m_CacheRange.intersect(range);
191 auto res = impl->m_CacheRange.intersect(range);
201 impl->unlock();
192 impl->unlock();
202 return res;
193 return res;
203 }
194 }
204
195
205 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
196 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
206 {
197 {
207 impl->lockRead();
198 impl->lockRead();
208 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
199 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
209 impl->unlock();
200 impl->unlock();
210 return res;
201 return res;
211 }
202 }
212
203
213
204
214 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
205 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
215 {
206 {
216 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
207 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
217
208
218 auto notInCache = QVector<SqpRange>{};
209 auto notInCache = QVector<SqpRange>{};
219
210
220 if (!this->cacheContains(range)) {
211 if (!this->cacheContains(range)) {
221 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
212 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
222 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
213 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
223 notInCache << range;
214 notInCache << range;
224 }
215 }
225 else if (range.m_TStart < impl->m_CacheRange.m_TStart
216 else if (range.m_TStart < impl->m_CacheRange.m_TStart
226 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
217 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
227 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
218 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
228 }
219 }
229 else if (range.m_TStart < impl->m_CacheRange.m_TStart
220 else if (range.m_TStart < impl->m_CacheRange.m_TStart
230 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
221 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
231 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
222 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
232 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
223 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
233 }
224 }
234 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
225 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
235 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
226 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
236 }
227 }
237 else {
228 else {
238 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
229 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
239 << QThread::currentThread();
230 << QThread::currentThread();
240 }
231 }
241 }
232 }
242
233
243 return notInCache;
234 return notInCache;
244 }
235 }
245
236
246 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
237 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
247 {
238 {
248 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
239 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
249
240
250 auto inCache = QVector<SqpRange>{};
241 auto inCache = QVector<SqpRange>{};
251
242
252
243
253 if (this->intersect(range)) {
244 if (this->intersect(range)) {
254 if (range.m_TStart <= impl->m_CacheRange.m_TStart
245 if (range.m_TStart <= impl->m_CacheRange.m_TStart
255 && range.m_TEnd >= impl->m_CacheRange.m_TStart
246 && range.m_TEnd >= impl->m_CacheRange.m_TStart
256 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
247 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
257 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
248 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
258 }
249 }
259
250
260 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
251 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
261 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
252 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
262 inCache << range;
253 inCache << range;
263 }
254 }
264 else if (range.m_TStart > impl->m_CacheRange.m_TStart
255 else if (range.m_TStart > impl->m_CacheRange.m_TStart
265 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
256 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
266 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
257 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
267 }
258 }
268 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
259 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
269 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
260 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
270 inCache << impl->m_CacheRange;
261 inCache << impl->m_CacheRange;
271 }
262 }
272 else {
263 else {
273 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
264 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
274 << QThread::currentThread();
265 << QThread::currentThread();
275 }
266 }
276 }
267 }
277
268
278 return inCache;
269 return inCache;
279 }
270 }
General Comments 0
You need to be logged in to leave comments. Login now