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