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 #include "index_map.h"
17
18 #include <algorithm>
19
20 #include "log.h"
21
22 namespace SysTuning {
23 namespace TraceStreamer {
IndexMap(TableRowId start,TableRowId end)24 IndexMap::IndexMap(TableRowId start, TableRowId end) : end_(end), current_(start), start_(start) {}
25
CovertToIndexMap()26 void IndexMap::CovertToIndexMap()
27 {
28 if (converted_) {
29 indexType_ = INDEX_TYPE_OUTER_INDEX;
30 return;
31 }
32 converted_ = true;
33 if (indexType_ == INDEX_TYPE_ID && HasData()) {
34 for (auto i = start_; i < end_; i++) {
35 rowIndex_.push_back(i);
36 }
37 current_ = start_ = 0;
38 end_ = rowIndex_.size();
39 }
40 indexType_ = INDEX_TYPE_OUTER_INDEX;
41 empty_ = false;
42 }
43
Print()44 void IndexMap::Print()
45 {
46 for (auto itor = rowIndex_.begin(); itor != rowIndex_.end(); itor++) {
47 (void)fprintf(stdout, "%d,", *itor);
48 }
49 (void)fflush(stdout);
50 }
Sort()51 void IndexMap::Sort() {}
52
Init()53 void IndexMap::Init()
54 {
55 intersectEable_ = HasData();
56 }
HasData() const57 bool IndexMap::HasData() const
58 {
59 return !empty_;
60 }
Intersect(TableRowId start,TableRowId end)61 void IndexMap::Intersect(TableRowId start, TableRowId end)
62 {
63 if (indexType_ == INDEX_TYPE_OUTER_INDEX) {
64 bool changed = false;
65 rowIndexBak_.clear();
66 for (auto i = rowIndex_.begin(); i != rowIndex_.end(); i++) {
67 if (*i >= start && *i < end) {
68 changed = true;
69 rowIndexBak_.push_back(*i);
70 }
71 }
72 if (changed) {
73 rowIndex_ = rowIndexBak_;
74 }
75 start_ = current_ = 0;
76 end_ = rowIndex_.size();
77 } else {
78 start_ = std::max(start_, start);
79 end_ = std::min(end_, end);
80 current_ = start_;
81 }
82 empty_ = false;
83 }
84
Size() const85 size_t IndexMap::Size() const
86 {
87 return end_ - start_;
88 }
89
Next()90 void IndexMap::Next()
91 {
92 if (desc_) {
93 if (current_ > start_ - 1) {
94 current_--;
95 }
96 } else {
97 if (current_ < end_) {
98 current_++;
99 }
100 }
101 }
FilterId(unsigned char op,sqlite3_value * argv)102 void IndexMap::FilterId(unsigned char op, sqlite3_value *argv)
103 {
104 auto type = sqlite3_value_type(argv);
105 if (type != SQLITE_INTEGER) {
106 // other type consider it NULL
107 Intersect(0, 0);
108 return;
109 }
110 if (HasData()) {
111 CovertToIndexMap();
112 }
113
114 auto v = static_cast<TableRowId>(sqlite3_value_int64(argv));
115 switch (op) {
116 case SQLITE_INDEX_CONSTRAINT_EQ:
117 Intersect(v, v + 1);
118 break;
119 case SQLITE_INDEX_CONSTRAINT_GE:
120 Intersect(v, end_);
121 break;
122 case SQLITE_INDEX_CONSTRAINT_GT:
123 v++;
124 Intersect(v, end_);
125 break;
126 case SQLITE_INDEX_CONSTRAINT_LE:
127 v++;
128 Intersect(0, v);
129 break;
130 case SQLITE_INDEX_CONSTRAINT_LT:
131 Intersect(0, v);
132 break;
133 default:
134 // can't filter, all rows
135 break;
136 }
137 }
138
FilterTS(unsigned char op,sqlite3_value * argv,const std::deque<InternalTime> & times)139 void IndexMap::FilterTS(unsigned char op, sqlite3_value *argv, const std::deque<InternalTime> ×)
140 {
141 auto v = static_cast<uint64_t>(sqlite3_value_int64(argv));
142 auto getValue = [](const uint64_t &row) { return row; };
143 switch (op) {
144 case SQLITE_INDEX_CONSTRAINT_EQ:
145 IntersectabcEqual(times, v, getValue);
146 break;
147 case SQLITE_INDEX_CONSTRAINT_GT:
148 v++;
149 [[fallthrough]];
150 case SQLITE_INDEX_CONSTRAINT_GE: {
151 IntersectGreaterEqual(times, v, getValue);
152 break;
153 }
154 case SQLITE_INDEX_CONSTRAINT_LE:
155 v++;
156 [[fallthrough]];
157 case SQLITE_INDEX_CONSTRAINT_LT:
158 IntersectLessEqual(times, v, getValue);
159 break;
160 case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: {
161 RemoveNullElements(times, v);
162 break;
163 }
164 default:
165 break;
166 } // end of switch (op)
167 }
MergeIndexTypeId(IndexMap * other)168 bool IndexMap::MergeIndexTypeId(IndexMap *other)
169 {
170 if (indexType_ != INDEX_TYPE_ID && other->indexType_ != INDEX_TYPE_ID) {
171 return false;
172 }
173 if ((other->start_ >= start_ && other->start_ <= end_) || (start_ >= other->start_ && start_ <= other->end_)) {
174 start_ = std::min(start_, other->start_);
175 end_ = std::max(end_, other->end_);
176 } else if (start_ > other->start_) {
177 this->CovertToIndexMap();
178 other->CovertToIndexMap();
179 const std::vector<TableRowId> b = other->rowIndex_;
180 uint32_t bIndex = 0;
181 uint32_t bSize = b.size();
182 while (bIndex != bSize) {
183 rowIndex_.push_back(b[bIndex]);
184 }
185 start_ = current_ = 0;
186 end_ = rowIndex_.size();
187 } else {
188 this->CovertToIndexMap();
189 other->CovertToIndexMap();
190 std::vector<TableRowId> c = other->rowIndex_;
191 uint32_t aIndex = 0;
192 uint32_t aSize = rowIndex_.size();
193 while (aIndex != aSize) {
194 c.push_back(rowIndex_[aIndex]);
195 }
196 start_ = current_ = 0;
197 end_ = rowIndex_.size();
198 }
199 return true;
200 }
Merge(IndexMap * other)201 bool IndexMap::Merge(IndexMap *other)
202 {
203 TS_CHECK_TRUE_RET(MergeIndexTypeId(other) == false, true);
204 this->CovertToIndexMap();
205 other->CovertToIndexMap();
206 const std::vector<TableRowId> b = other->rowIndex_;
207 const std::vector<TableRowId> &a = rowIndex_;
208 std::vector<TableRowId> c;
209 uint32_t aIndex = 0;
210 uint32_t aSize = a.size();
211 uint32_t bIndex = 0;
212 uint32_t bSize = b.size();
213 while (aIndex != aSize || bIndex != bSize) {
214 if (aIndex == aSize) {
215 while (bIndex != bSize) {
216 c.push_back(b[bIndex]);
217 bIndex++;
218 }
219 break;
220 }
221 if (bIndex == bSize) {
222 while (aIndex != aSize) {
223 c.push_back(a[aIndex]);
224 bIndex++;
225 }
226 break;
227 }
228 if (a[aIndex] < b[bIndex]) {
229 c.push_back(a[aIndex]);
230 aIndex++;
231 } else if (a[aIndex] == b[bIndex]) {
232 c.push_back(a[aIndex]);
233 aIndex++;
234 bIndex++;
235 } else {
236 c.push_back(b[bIndex]);
237 bIndex++;
238 }
239 }
240 rowIndex_ = c;
241 start_ = current_ = 0;
242 end_ = rowIndex_.size();
243 return true;
244 }
245
Eof() const246 bool IndexMap::Eof() const
247 {
248 if (desc_) {
249 return current_ <= start_ - 1;
250 } else {
251 return current_ >= end_;
252 }
253 }
254
CurrentRow() const255 TableRowId IndexMap::CurrentRow() const
256 {
257 auto current = current_;
258 if (indexType_ == INDEX_TYPE_ID) {
259 return current;
260 } else {
261 return rowIndex_[current];
262 }
263 }
264
SortBy(bool desc)265 void IndexMap::SortBy(bool desc)
266 {
267 if (desc) {
268 current_ = end_ - 1;
269 } else {
270 current_ = start_;
271 }
272 desc_ = desc;
273 }
274 } // namespace TraceStreamer
275 } // namespace SysTuning
276