• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef TABLE_INDEX_MAP_H
17 #define TABLE_INDEX_MAP_H
18 
19 #include <cstdint>
20 #include <deque>
21 #include <functional>
22 #include <vector>
23 #include "sqlite3.h"
24 #include "ts_common.h"
25 
26 namespace SysTuning {
27 namespace TraceStreamer {
28 class IndexMap {
29 public:
IndexMap()30     IndexMap() {}
~IndexMap()31     ~IndexMap() {}
32 
33     IndexMap(TableRowId start, TableRowId end);
34     void CovertToIndexMap();
35     static void Sort();
36     void Print();
37     void Init();
38     void Merge(IndexMap* other);
39     void FilterId(unsigned char op, sqlite3_value* argv);
40     void FilterTS(unsigned char op, sqlite3_value* argv, const std::deque<InternalTime>& times);
41     template <class T>
ProcessData(const std::deque<T> & dataQueue,bool remove,std::function<bool (TableRowId)> firstCheck,std::function<bool (TableRowId)> scondCheck)42     void ProcessData(const std::deque<T>& dataQueue,
43                      bool remove,
44                      std::function<bool(TableRowId)> firstCheck,
45                      std::function<bool(TableRowId)> scondCheck)
46     {
47         bool changed = false;
48         if (remove) {
49             for (const auto& val : rowIndex_) {
50                 if (!firstCheck(val)) {
51                     changed = true;
52                     rowIndexBak_.push_back(val);
53                 }
54             }
55             if (changed) {
56                 rowIndex_ = rowIndexBak_;
57             }
58         } else {
59             for (auto i = 0; i < dataQueue.size(); i++) {
60                 if (scondCheck(i)) {
61                     rowIndex_.push_back(i);
62                 }
63             }
64         }
65         indexType_ = INDEX_TYPE_OUTER_INDEX;
66         FixSize();
67     }
68     template <class T>
MixRange(unsigned char op,T value,const std::deque<T> & dataQueue)69     void MixRange(unsigned char op, T value, const std::deque<T>& dataQueue)
70     {
71         filters_++;
72         auto invalidValue = std::numeric_limits<T>::max();
73         bool remove = false;
74         if (HasData()) {
75             CovertToIndexMap();
76             remove = true;
77         }
78         rowIndexBak_.clear();
79         switch (op) {
80             case SQLITE_INDEX_CONSTRAINT_EQ:
81                 ProcessData(
82                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != value; },
83                     [&](TableRowId id) -> bool { return dataQueue[id] == value; });
84                 break;
85             case SQLITE_INDEX_CONSTRAINT_NE:
86                 ProcessData(
87                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == value; },
88                     [&](TableRowId id) -> bool { return dataQueue[id] != value; });
89                 break;
90             case SQLITE_INDEX_CONSTRAINT_ISNULL:
91                 ProcessData(
92                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; },
93                     [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; });
94                 break;
95             case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
96                 ProcessData(
97                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; },
98                     [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; });
99                 break;
100             case SQLITE_INDEX_CONSTRAINT_GT:
101                 ProcessData(
102                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] <= value; },
103                     [&](TableRowId id) -> bool { return dataQueue[id] > value; });
104                 break;
105             case SQLITE_INDEX_CONSTRAINT_GE:
106                 ProcessData(
107                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] < value; },
108                     [&](TableRowId id) -> bool { return dataQueue[id] >= invalidValue; });
109                 break;
110             case SQLITE_INDEX_CONSTRAINT_LE:
111                 ProcessData(
112                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] > value; },
113                     [&](TableRowId id) -> bool { return dataQueue[id] < invalidValue; });
114                 break;
115             case SQLITE_INDEX_CONSTRAINT_LT:
116                 ProcessData(
117                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] >= value; },
118                     [&](TableRowId id) -> bool { return dataQueue[id] < invalidValue; });
119                 break;
120             default:
121                 break;
122         } // end of switch (op)
123         empty_ = false;
124     }
FixSize()125     void FixSize()
126     {
127         if (indexType_ == INDEX_TYPE_OUTER_INDEX) {
128             end_ = rowIndex_.size();
129             current_ = 0;
130         }
131     }
Remove(TableRowId row)132     void Remove(TableRowId row)
133     {
134         (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row);
135     }
Set(TableRowId start,TableRowId end)136     void Set(TableRowId start, TableRowId end)
137     {
138         if (indexType_ == INDEX_TYPE_ID) {
139             end_ = std::min(end_, end);
140             current_ = start_ = std::max(start_, start);
141         }
142     }
143 
144     size_t Size() const;
145 
146     void Next();
147 
148     bool Eof() const;
149 
150     TableRowId CurrentRow() const;
151 
152     void SortBy(bool desc);
153     void Intersect(TableRowId start, TableRowId end);
154 
155     // the follow functions require that thecolData is sotred
156     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectabcEqual(const std::deque<Row> & rows,Val v,GetV getValue)157     void IntersectabcEqual(const std::deque<Row>& rows, Val v, GetV getValue)
158     {
159         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v);
160         auto end = std::upper_bound(start, rows.begin() + end_, v);
161         auto newStart = std::distance(rows.begin(), start);
162         auto newEnd = std::distance(rows.begin(), end);
163         Intersect(newStart, newEnd);
164         return;
165     }
166 
167     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectGreaterEqual(const std::deque<Row> & rows,Val v,GetV getValue)168     void IntersectGreaterEqual(const std::deque<Row>& rows, Val v, GetV getValue)
169     {
170         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v,
171                                       [&](const Row& row, const Val& v) { return v > getValue(row); });
172         auto newStart = std::distance(rows.begin(), start);
173         Intersect(newStart, INVALID_INT32);
174         return;
175     }
176 
177     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectLessEqual(const std::deque<Row> & rows,Val v,GetV getValue)178     void IntersectLessEqual(const std::deque<Row>& rows, Val v, GetV getValue)
179     {
180         auto end = std::upper_bound(rows.begin() + start_, rows.begin() + end_, v,
181                                     [&](const Row& row, const Val& v) { return v > getValue(row); });
182         auto newEnd = std::distance(rows.begin(), end);
183         Intersect(0, newEnd);
184         return;
185     }
186     template <typename T>
RemoveNullElements(const std::deque<T> & rows,T v)187     void RemoveNullElements(const std::deque<T>& rows, T v)
188     {
189         auto invalidValue = std::numeric_limits<T>::max();
190         bool remove = false;
191         if (HasData()) {
192             CovertToIndexMap();
193             remove = true;
194         }
195 
196         if (remove) {
197             for (auto i = rowIndex_.begin(); i != rowIndex_.end();) {
198                 if (rows[*i] == invalidValue) {
199                     i = rowIndex_.erase(i);
200                 } else {
201                     i++;
202                 }
203             }
204         } else {
205             auto size = rows.size();
206             for (size_t i = 0; i < size; i++) {
207                 if (rows[i] != invalidValue) {
208                     rowIndex_.push_back(i);
209                 }
210             }
211         }
212         indexType_ = INDEX_TYPE_OUTER_INDEX;
213         FixSize();
214         return;
215     }
216     bool HasData() const;
217     std::vector<TableRowId> rowIndex_ = {};
218     std::vector<TableRowId> rowIndexBak_ = {};
219 
220 private:
221     TableRowId end_ = INVALID_INT32;
222     TableRowId current_ = 0;
223     TableRowId start_ = 0;
224     enum FindIndexType {
225         INDEX_TYPE_ID,
226         INDEX_TYPE_OUTER_INDEX,
227     };
228     FindIndexType indexType_ = INDEX_TYPE_ID;
229 
230     enum IndexType { COMPACT, SPARSE };
231     bool empty_ = true;
232     bool desc_ = false;
233     bool converted_ = false;
234     uint8_t filters_ = 0;
235     bool intersectEable_ = false;
236 };
237 } // namespace TraceStreamer
238 } // namespace SysTuning
239 
240 #endif // TABLE_INDEX_MAP_H
241