• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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     bool 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         if (remove) {
48             bool changed = false;
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     }
PrepMixRange(bool & remove)68     void PrepMixRange(bool &remove)
69     {
70         filters_++;
71         if (HasData()) {
72             CovertToIndexMap();
73             remove = true;
74         }
75         rowIndexBak_.clear();
76     }
77     template <class T>
MixRange(unsigned char op,T value,const std::deque<T> & dataQueue)78     void MixRange(unsigned char op, T value, const std::deque<T> &dataQueue)
79     {
80         auto invalidValue = std::numeric_limits<T>::max();
81         bool remove = false;
82         PrepMixRange(remove);
83         switch (op) {
84             case SQLITE_INDEX_CONSTRAINT_EQ:
85                 ProcessData(
86                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != value; },
87                     [&](TableRowId id) -> bool { return dataQueue[id] == value; });
88                 break;
89             case SQLITE_INDEX_CONSTRAINT_NE:
90                 ProcessData(
91                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == value; },
92                     [&](TableRowId id) -> bool { return dataQueue[id] != value; });
93                 break;
94             case SQLITE_INDEX_CONSTRAINT_ISNULL:
95                 ProcessData(
96                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; },
97                     [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; });
98                 break;
99             case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
100                 ProcessData(
101                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; },
102                     [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; });
103                 break;
104             case SQLITE_INDEX_CONSTRAINT_GT:
105                 ProcessData(
106                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] <= value; },
107                     [&](TableRowId id) -> bool { return dataQueue[id] > value; });
108                 break;
109             case SQLITE_INDEX_CONSTRAINT_GE:
110                 ProcessData(
111                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] < value; },
112                     [&](TableRowId id) -> bool { return dataQueue[id] >= value; });
113                 break;
114             case SQLITE_INDEX_CONSTRAINT_LE:
115                 ProcessData(
116                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] > value; },
117                     [&](TableRowId id) -> bool { return dataQueue[id] <= value; });
118                 break;
119             case SQLITE_INDEX_CONSTRAINT_LT:
120                 ProcessData(
121                     dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] >= value; },
122                     [&](TableRowId id) -> bool { return dataQueue[id] < value; });
123                 break;
124             default:
125                 break;
126         } // end of switch (op)
127         empty_ = false;
128     }
FixSize()129     void FixSize()
130     {
131         if (indexType_ == INDEX_TYPE_OUTER_INDEX) {
132             end_ = rowIndex_.size();
133             current_ = 0;
134         }
135     }
Remove(TableRowId row)136     void Remove(TableRowId row)
137     {
138         (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row);
139     }
Set(TableRowId start,TableRowId end)140     void Set(TableRowId start, TableRowId end)
141     {
142         if (indexType_ == INDEX_TYPE_ID) {
143             end_ = std::min(end_, end);
144             current_ = start_ = std::max(start_, start);
145         }
146     }
147 
148     size_t Size() const;
149 
150     void Next();
151 
152     bool Eof() const;
153 
154     TableRowId CurrentRow() const;
155 
156     void SortBy(bool desc);
157     void Intersect(TableRowId start, TableRowId end);
158 
159     // the follow functions require that thecolData is sotred
160     template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
IntersectabcEqual(const std::deque<Row> & rows,Val v,GetV getValue)161     void IntersectabcEqual(const std::deque<Row> &rows, Val v, GetV getValue)
162     {
163         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v);
164         auto end = std::upper_bound(start, rows.begin() + end_, v);
165         auto newStart = std::distance(rows.begin(), start);
166         auto newEnd = std::distance(rows.begin(), end);
167         Intersect(newStart, newEnd);
168         return;
169     }
170 
171     template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
IntersectGreaterEqual(const std::deque<Row> & rows,Val v,GetV getValue)172     void IntersectGreaterEqual(const std::deque<Row> &rows, Val v, GetV getValue)
173     {
174         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v,
175                                       [&](const Row &row, const Val &v) { return v > getValue(row); });
176         auto newStart = std::distance(rows.begin(), start);
177         Intersect(newStart, INVALID_INT32);
178         return;
179     }
180 
181     template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
IntersectLessEqual(const std::deque<Row> & rows,Val v,GetV getValue)182     void IntersectLessEqual(const std::deque<Row> &rows, Val v, GetV getValue)
183     {
184         auto end = std::upper_bound(rows.begin() + start_, rows.begin() + end_, v,
185                                     [&](const Row &row, const Val &v) { return v > getValue(row); });
186         auto newEnd = std::distance(rows.begin(), end);
187         Intersect(0, newEnd);
188         return;
189     }
190     template <typename T>
RemoveNullElements(const std::deque<T> & rows,T v)191     void RemoveNullElements(const std::deque<T> &rows, T v)
192     {
193         auto invalidValue = std::numeric_limits<T>::max();
194         bool remove = false;
195         if (HasData()) {
196             CovertToIndexMap();
197             remove = true;
198         }
199 
200         if (remove) {
201             for (auto i = rowIndex_.begin(); i != rowIndex_.end();) {
202                 if (rows[*i] == invalidValue) {
203                     i = rowIndex_.erase(i);
204                 } else {
205                     i++;
206                 }
207             }
208         } else {
209             auto size = rows.size();
210             for (size_t i = 0; i < size; i++) {
211                 if (rows[i] != invalidValue) {
212                     rowIndex_.push_back(i);
213                 }
214             }
215             empty_ = false;
216         }
217         indexType_ = INDEX_TYPE_OUTER_INDEX;
218         FixSize();
219         return;
220     }
221     bool HasData() const;
222     std::vector<TableRowId> rowIndex_ = {};
223     std::vector<TableRowId> rowIndexBak_ = {};
224 
225 private:
226     bool MergeIndexTypeId(IndexMap *other);
227 
228 private:
229     TableRowId end_ = INVALID_INT32;
230     TableRowId current_ = 0;
231     TableRowId start_ = 0;
232     enum FindIndexType {
233         INDEX_TYPE_ID,
234         INDEX_TYPE_OUTER_INDEX,
235     };
236     FindIndexType indexType_ = INDEX_TYPE_ID;
237 
238     enum IndexType { COMPACT, SPARSE };
239     bool empty_ = true;
240     bool desc_ = false;
241     bool converted_ = false;
242     uint8_t filters_ = 0;
243     bool intersectEable_ = false;
244 };
245 } // namespace TraceStreamer
246 } // namespace SysTuning
247 
248 #endif // TABLE_INDEX_MAP_H
249