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