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 #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 fprintf(stdout, "%d,", *itor);
48 }
49 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>& times)
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 }
Merge(IndexMap * other)168 void IndexMap::Merge(IndexMap* other)
169 {
170 if (indexType_ == INDEX_TYPE_ID && other->indexType_ == INDEX_TYPE_ID) {
171 if ((other->start_ >= start_ && other->start_ <= end_) || (start_ >= other->start_ && start_ <= other->end_)) {
172 start_ = std::min(start_, other->start_);
173 end_ = std::max(end_, other->end_);
174 } else if (start_ > other->start_) {
175 this->CovertToIndexMap();
176 other->CovertToIndexMap();
177 const std::vector<TableRowId> b = other->rowIndex_;
178 uint32_t bIndex = 0;
179 uint32_t bSize = b.size();
180 while (bIndex != bSize) {
181 rowIndex_.push_back(b[bIndex]);
182 }
183 start_ = current_ = 0;
184 end_ = rowIndex_.size();
185 } else {
186 this->CovertToIndexMap();
187 other->CovertToIndexMap();
188 std::vector<TableRowId> c = other->rowIndex_;
189 uint32_t aIndex = 0;
190 uint32_t aSize = rowIndex_.size();
191 while (aIndex != aSize) {
192 c.push_back(rowIndex_[aIndex]);
193 }
194 start_ = current_ = 0;
195 end_ = rowIndex_.size();
196 }
197 return;
198 }
199 this->CovertToIndexMap();
200 other->CovertToIndexMap();
201 const std::vector<TableRowId> b = other->rowIndex_;
202 const std::vector<TableRowId>& a = rowIndex_;
203 std::vector<TableRowId> c;
204 uint32_t aIndex = 0;
205 uint32_t aSize = a.size();
206 uint32_t bIndex = 0;
207 uint32_t bSize = b.size();
208 while (aIndex != aSize || bIndex != bSize) {
209 if (aIndex == aSize) {
210 while (bIndex != bSize) {
211 c.push_back(b[bIndex]);
212 bIndex++;
213 }
214 break;
215 }
216 if (bIndex == bSize) {
217 while (aIndex != aSize) {
218 c.push_back(a[aIndex]);
219 bIndex++;
220 }
221 break;
222 }
223 if (a[aIndex] < b[bIndex]) {
224 c.push_back(a[aIndex]);
225 aIndex++;
226 } else if (a[aIndex] == b[bIndex]) {
227 c.push_back(a[aIndex]);
228 aIndex++;
229 bIndex++;
230 } else {
231 c.push_back(b[bIndex]);
232 bIndex++;
233 }
234 }
235 rowIndex_ = c;
236 start_ = current_ = 0;
237 end_ = rowIndex_.size();
238 }
239
Eof() const240 bool IndexMap::Eof() const
241 {
242 if (desc_) {
243 return current_ <= start_ - 1;
244 } else {
245 return current_ >= end_;
246 }
247 }
248
CurrentRow() const249 TableRowId IndexMap::CurrentRow() const
250 {
251 auto current = current_;
252 if (indexType_ == INDEX_TYPE_ID) {
253 return current;
254 } else {
255 return rowIndex_[current];
256 }
257 }
258
SortBy(bool desc)259 void IndexMap::SortBy(bool desc)
260 {
261 if (desc) {
262 current_ = end_ - 1;
263 } else {
264 current_ = start_;
265 }
266 desc_ = desc;
267 }
268 } // namespace TraceStreamer
269 } // namespace SysTuning
270