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> ×); 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