• 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     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(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != value; },
86                             [&](TableRowId id) -> bool { return dataQueue[id] == value; });
87                 break;
88             case SQLITE_INDEX_CONSTRAINT_NE:
89                 ProcessData(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == value; },
90                             [&](TableRowId id) -> bool { return dataQueue[id] != value; });
91                 break;
92             case SQLITE_INDEX_CONSTRAINT_ISNULL:
93                 ProcessData(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; },
94                             [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; });
95                 break;
96             case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
97                 ProcessData(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(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] <= value; },
102                             [&](TableRowId id) -> bool { return dataQueue[id] > value; });
103                 break;
104             case SQLITE_INDEX_CONSTRAINT_GE:
105                 ProcessData(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] < value; },
106                             [&](TableRowId id) -> bool { return dataQueue[id] >= value; });
107                 break;
108             case SQLITE_INDEX_CONSTRAINT_LE:
109                 ProcessData(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] > value; },
110                             [&](TableRowId id) -> bool { return dataQueue[id] <= value; });
111                 break;
112             case SQLITE_INDEX_CONSTRAINT_LT:
113                 ProcessData(dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] >= value; },
114                             [&](TableRowId id) -> bool { return dataQueue[id] < value; });
115                 break;
116             default:
117                 break;
118         } // end of switch (op)
119         empty_ = false;
120     }
FixSize()121     void FixSize()
122     {
123         if (indexType_ == INDEX_TYPE_OUTER_INDEX) {
124             end_ = rowIndex_.size();
125             current_ = 0;
126         }
127     }
Remove(TableRowId row)128     void Remove(TableRowId row)
129     {
130         (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row);
131     }
Set(TableRowId start,TableRowId end)132     void Set(TableRowId start, TableRowId end)
133     {
134         if (indexType_ == INDEX_TYPE_ID) {
135             end_ = std::min(end_, end);
136             current_ = start_ = std::max(start_, start);
137         }
138     }
139 
140     size_t Size() const;
141 
142     void Next();
143 
144     bool Eof() const;
145 
146     TableRowId CurrentRow() const;
147 
148     void SortBy(bool desc);
149     void Intersect(TableRowId start, TableRowId end);
150 
151     // the follow functions require that thecolData is sotred
152     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectabcEqual(const std::deque<Row> & rows,Val v,GetV getValue)153     void IntersectabcEqual(const std::deque<Row>& rows, Val v, GetV getValue)
154     {
155         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v);
156         auto end = std::upper_bound(start, rows.begin() + end_, v);
157         auto newStart = std::distance(rows.begin(), start);
158         auto newEnd = std::distance(rows.begin(), end);
159         Intersect(newStart, newEnd);
160         return;
161     }
162 
163     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectGreaterEqual(const std::deque<Row> & rows,Val v,GetV getValue)164     void IntersectGreaterEqual(const std::deque<Row>& rows, Val v, GetV getValue)
165     {
166         auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v,
167                                       [&](const Row& row, const Val& v) { return v > getValue(row); });
168         auto newStart = std::distance(rows.begin(), start);
169         Intersect(newStart, INVALID_INT32);
170         return;
171     }
172 
173     template <typename Row, typename Val, typename GetV = const Val&(const Row&)>
IntersectLessEqual(const std::deque<Row> & rows,Val v,GetV getValue)174     void IntersectLessEqual(const std::deque<Row>& rows, Val v, GetV getValue)
175     {
176         auto end = std::upper_bound(rows.begin() + start_, rows.begin() + end_, v,
177                                     [&](const Row& row, const Val& v) { return v > getValue(row); });
178         auto newEnd = std::distance(rows.begin(), end);
179         Intersect(0, newEnd);
180         return;
181     }
182     template <typename T>
RemoveNullElements(const std::deque<T> & rows,T v)183     void RemoveNullElements(const std::deque<T>& rows, T v)
184     {
185         auto invalidValue = std::numeric_limits<T>::max();
186         bool remove = false;
187         if (HasData()) {
188             CovertToIndexMap();
189             remove = true;
190         }
191 
192         if (remove) {
193             for (auto i = rowIndex_.begin(); i != rowIndex_.end();) {
194                 if (rows[*i] == invalidValue) {
195                     i = rowIndex_.erase(i);
196                 } else {
197                     i++;
198                 }
199             }
200         } else {
201             auto size = rows.size();
202             for (size_t i = 0; i < size; i++) {
203                 if (rows[i] != invalidValue) {
204                     rowIndex_.push_back(i);
205                 }
206             }
207             empty_ = false;
208         }
209         indexType_ = INDEX_TYPE_OUTER_INDEX;
210         FixSize();
211         return;
212     }
213     bool HasData() const;
214     std::vector<TableRowId> rowIndex_ = {};
215     std::vector<TableRowId> rowIndexBak_ = {};
216 
217 private:
218     bool MergeIndexTypeId(IndexMap* other);
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