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