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 "bio_latency_sample_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 namespace {
21 enum Index {
22 ID = 0,
23 CALLCHAIN_ID,
24 TYPE,
25 IPID,
26 ITID,
27 START_TS,
28 END_TS,
29 LATENCY_DUR,
30 TIER,
31 SIZE,
32 BLOCK_NUMBER,
33 PATH,
34 DUR_PER_4K,
35 };
36 }
BioLatencySampleTable(const TraceDataCache * dataCache)37 BioLatencySampleTable::BioLatencySampleTable(const TraceDataCache* dataCache) : TableBase(dataCache)
38 {
39 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
40 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
41 tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER"));
42 tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER"));
43 tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
44 tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER"));
45 tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER"));
46 tableColumn_.push_back(TableBase::ColumnInfo("latency_dur", "INTEGER"));
47 tableColumn_.push_back(TableBase::ColumnInfo("tier", "INTEGER"));
48 tableColumn_.push_back(TableBase::ColumnInfo("size", "INTEGER"));
49 tableColumn_.push_back(TableBase::ColumnInfo("block_number", "TEXT"));
50 tableColumn_.push_back(TableBase::ColumnInfo("path_id", "TEXT"));
51 tableColumn_.push_back(TableBase::ColumnInfo("dur_per_4k", "INTEGER"));
52 tablePriKey_.push_back("id");
53 }
54
~BioLatencySampleTable()55 BioLatencySampleTable::~BioLatencySampleTable() {}
56
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)57 void BioLatencySampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
58 {
59 constexpr double filterBaseCost = 1000.0; // set-up and tear-down
60 constexpr double indexCost = 2.0;
61 ei.estimatedCost = filterBaseCost;
62
63 auto rowCount = dataCache_->GetConstHidumpData().Size();
64 if (rowCount == 0 || rowCount == 1) {
65 ei.estimatedRows = rowCount;
66 ei.estimatedCost += indexCost * rowCount;
67 return;
68 }
69
70 double filterCost = 0.0;
71 auto constraints = fc.GetConstraints();
72 if (constraints.empty()) { // scan all rows
73 filterCost = rowCount;
74 } else {
75 FilterByConstraint(fc, filterCost, rowCount);
76 }
77 ei.estimatedCost += filterCost;
78 ei.estimatedRows = rowCount;
79 ei.estimatedCost += rowCount * indexCost;
80
81 ei.isOrdered = true;
82 auto orderbys = fc.GetOrderBys();
83 for (auto i = 0; i < orderbys.size(); i++) {
84 switch (orderbys[i].iColumn) {
85 case ID:
86 break;
87 default: // other columns can be sorted by SQLite
88 ei.isOrdered = false;
89 break;
90 }
91 }
92 }
93
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)94 void BioLatencySampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
95 {
96 auto fcConstraints = fc.GetConstraints();
97 for (int i = 0; i < static_cast<int>(fcConstraints.size()); i++) {
98 if (rowCount <= 1) {
99 // only one row or nothing, needn't filter by constraint
100 filterCost += rowCount;
101 break;
102 }
103 const auto& c = fcConstraints[i];
104 switch (c.col) {
105 case ID: {
106 if (CanFilterId(c.op, rowCount)) {
107 fc.UpdateConstraint(i, true);
108 filterCost += 1; // id can position by 1 step
109 } else {
110 filterCost += rowCount; // scan all rows
111 }
112 break;
113 }
114 default: // other column
115 filterCost += rowCount; // scan all rows
116 break;
117 }
118 }
119 }
120
CanFilterId(const char op,size_t & rowCount)121 bool BioLatencySampleTable::CanFilterId(const char op, size_t& rowCount)
122 {
123 switch (op) {
124 case SQLITE_INDEX_CONSTRAINT_EQ:
125 rowCount = 1;
126 break;
127 case SQLITE_INDEX_CONSTRAINT_GT:
128 case SQLITE_INDEX_CONSTRAINT_GE:
129 case SQLITE_INDEX_CONSTRAINT_LE:
130 case SQLITE_INDEX_CONSTRAINT_LT:
131 // assume filter out a half of rows
132 rowCount = (rowCount >> 1);
133 break;
134 default:
135 return false;
136 }
137 return true;
138 }
139
CreateCursor()140 std::unique_ptr<TableBase::Cursor> BioLatencySampleTable::CreateCursor()
141 {
142 return std::make_unique<Cursor>(dataCache_, this);
143 }
144
Cursor(const TraceDataCache * dataCache,TableBase * table)145 BioLatencySampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
146 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstBioLatencySampleData().Size())),
147 bioLatencySampleObj_(dataCache->GetConstBioLatencySampleData())
148 {
149 }
150
~Cursor()151 BioLatencySampleTable::Cursor::~Cursor() {}
152
Filter(const FilterConstraints & fc,sqlite3_value ** argv)153 int BioLatencySampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
154 {
155 // reset indexMap_
156 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
157
158 if (rowCount_ <= 0) {
159 return SQLITE_OK;
160 }
161
162 auto& cs = fc.GetConstraints();
163 for (size_t i = 0; i < cs.size(); i++) {
164 const auto& c = cs[i];
165 switch (c.col) {
166 case ID:
167 FilterId(c.op, argv[i]);
168 break;
169 default:
170 break;
171 }
172 }
173
174 auto orderbys = fc.GetOrderBys();
175 for (auto i = orderbys.size(); i > 0;) {
176 i--;
177 switch (orderbys[i].iColumn) {
178 case ID:
179 indexMap_->SortBy(orderbys[i].desc);
180 break;
181 default:
182 break;
183 }
184 }
185
186 return SQLITE_OK;
187 }
188
Column(int column) const189 int BioLatencySampleTable::Cursor::Column(int column) const
190 {
191 switch (column) {
192 case ID:
193 sqlite3_result_int64(context_, static_cast<int32_t>(bioLatencySampleObj_.IdsData()[CurrentRow()]));
194 break;
195 case CALLCHAIN_ID:
196 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.CallChainIds()[CurrentRow()]));
197 break;
198 case TYPE:
199 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.Types()[CurrentRow()]));
200 break;
201 case IPID: {
202 if (bioLatencySampleObj_.Ipids()[CurrentRow()] != INVALID_UINT64) {
203 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.Ipids()[CurrentRow()]));
204 }
205 break;
206 }
207 case ITID: {
208 if (bioLatencySampleObj_.Itids()[CurrentRow()] != INVALID_UINT64) {
209 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.Itids()[CurrentRow()]));
210 }
211 break;
212 }
213 case START_TS: {
214 if (bioLatencySampleObj_.StartTs()[CurrentRow()] != INVALID_UINT64) {
215 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.StartTs()[CurrentRow()]));
216 }
217 break;
218 }
219 case END_TS: {
220 if (bioLatencySampleObj_.EndTs()[CurrentRow()] != INVALID_UINT64) {
221 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.EndTs()[CurrentRow()]));
222 }
223 break;
224 }
225 case LATENCY_DUR: {
226 if (bioLatencySampleObj_.LatencyDurs()[CurrentRow()] != INVALID_UINT64) {
227 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.LatencyDurs()[CurrentRow()]));
228 }
229 break;
230 }
231 case TIER: {
232 if (bioLatencySampleObj_.Tiers()[CurrentRow()] != INVALID_UINT32) {
233 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.Tiers()[CurrentRow()]));
234 }
235 break;
236 }
237 case SIZE: {
238 if (bioLatencySampleObj_.Sizes()[CurrentRow()] != INVALID_UINT64) {
239 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.Sizes()[CurrentRow()]));
240 }
241 break;
242 }
243 case BLOCK_NUMBER: {
244 if (bioLatencySampleObj_.BlockNumbers()[CurrentRow()] != INVALID_UINT64) {
245 auto returnValueIndex0 = bioLatencySampleObj_.BlockNumbers()[CurrentRow()];
246 sqlite3_result_text(context_, dataCache_->GetDataFromDict(returnValueIndex0).c_str(), STR_DEFAULT_LEN,
247 nullptr);
248 }
249 break;
250 }
251 case PATH: {
252 if (bioLatencySampleObj_.FilePathIds()[CurrentRow()] != INVALID_UINT64) {
253 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.FilePathIds()[CurrentRow()]));
254 }
255 break;
256 }
257 case DUR_PER_4K: {
258 if (bioLatencySampleObj_.DurPer4k()[CurrentRow()] != INVALID_UINT64) {
259 sqlite3_result_int64(context_, static_cast<int64_t>(bioLatencySampleObj_.DurPer4k()[CurrentRow()]));
260 }
261 break;
262 }
263 default:
264 TS_LOGF("Unregistered column : %d", column);
265 break;
266 }
267 return SQLITE_OK;
268 }
269 } // namespace TraceStreamer
270 } // namespace SysTuning
271