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 "callstack_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t {
21 ID = 0,
22 TS,
23 DURS,
24 CALL_IDS,
25 CATS,
26 NAME,
27 DEPTHS,
28 COOKIES_ID,
29 #if IS_WASM
30 COLORINDEX,
31 #endif
32 PARENT_ID,
33 ARGSET,
34 CHAIN_IDS,
35 SPAN_IDS,
36 PARENT_SPAN_IDS,
37 FLAGS
38 };
CallStackTable(const TraceDataCache *dataCache)39 CallStackTable::CallStackTable(const TraceDataCache *dataCache) : TableBase(dataCache)
40 {
41 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
42 tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
43 tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
44 tableColumn_.push_back(TableBase::ColumnInfo("callid", "INTEGER"));
45 tableColumn_.push_back(TableBase::ColumnInfo("cat", "TEXT"));
46 tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
47 tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER"));
48 tableColumn_.push_back(TableBase::ColumnInfo("cookie", "INTEGER"));
49 #if IS_WASM
50 tableColumn_.push_back(TableBase::ColumnInfo("colorIndex", "INTEGER"));
51 #endif
52 tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "INTEGER"));
53 tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "INTEGER"));
54 tableColumn_.push_back(TableBase::ColumnInfo("chainId", "TEXT"));
55 tableColumn_.push_back(TableBase::ColumnInfo("spanId", "TEXT"));
56 tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "TEXT"));
57 tableColumn_.push_back(TableBase::ColumnInfo("flag", "TEXT"));
58 tablePriKey_.push_back("callid");
59 tablePriKey_.push_back("ts");
60 tablePriKey_.push_back("depth");
61 }
62
~CallStackTable()63 CallStackTable::~CallStackTable() {}
64
FilterByConstraint(FilterConstraints &callfc, double &callfilterCost, size_t callrowCount, uint32_t callCurrenti)65 void CallStackTable::FilterByConstraint(FilterConstraints &callfc,
66 double &callfilterCost,
67 size_t callrowCount,
68 uint32_t callCurrenti)
69 {
70 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
71 // for loop
72 const auto &callc = callfc.GetConstraints()[callCurrenti];
73 switch (static_cast<Index>(callc.col)) {
74 case Index::ID: {
75 if (CanFilterId(callc.op, callrowCount)) {
76 callfc.UpdateConstraint(callCurrenti, true);
77 callfilterCost += 1; // id can position by 1 step
78 } else {
79 callfilterCost += callrowCount; // scan all rows
80 }
81 break;
82 }
83 default: // other column
84 callfilterCost += callrowCount; // scan all rows
85 break;
86 }
87 }
88
CreateCursor()89 std::unique_ptr<TableBase::Cursor> CallStackTable::CreateCursor()
90 {
91 return std::make_unique<Cursor>(dataCache_, this);
92 }
93
Cursor(const TraceDataCache *dataCache, TableBase *table)94 CallStackTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
95 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstInternalSlicesData().Size())),
96 slicesObj_(dataCache->GetConstInternalSlicesData())
97 {
98 }
99
~Cursor()100 CallStackTable::Cursor::~Cursor() {}
101
Filter(const FilterConstraints &fc, sqlite3_value **argv)102 int32_t CallStackTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
103 {
104 // reset indexMap_
105 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
106
107 if (rowCount_ <= 0) {
108 return SQLITE_OK;
109 }
110
111 auto callStackTabCs = fc.GetConstraints();
112 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
113 SwapIndexFront(callStackTabCs, sId);
114 for (size_t i = 0; i < callStackTabCs.size(); i++) {
115 const auto &c = callStackTabCs[i];
116 switch (static_cast<Index>(c.col)) {
117 case Index::ID:
118 FilterId(c.op, argv[c.idxInaConstraint]);
119 break;
120 case Index::TS:
121 FilterTS(c.op, argv[c.idxInaConstraint], slicesObj_.TimeStampData());
122 break;
123 case Index::CALL_IDS:
124 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
125 slicesObj_.CallIds());
126 break;
127 case Index::COOKIES_ID:
128 indexMap_->MixRange(c.op, static_cast<int64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
129 slicesObj_.Cookies());
130 break;
131 default:
132 break;
133 }
134 }
135
136 auto callStackTableOrderbys = fc.GetOrderBys();
137 for (auto i = callStackTableOrderbys.size(); i > 0;) {
138 i--;
139 switch (static_cast<Index>(callStackTableOrderbys[i].iColumn)) {
140 case Index::ID:
141 indexMap_->SortBy(callStackTableOrderbys[i].desc);
142 break;
143 default:
144 break;
145 }
146 }
147
148 return SQLITE_OK;
149 }
150
Column(int32_t col) const151 int32_t CallStackTable::Cursor::Column(int32_t col) const
152 {
153 switch (static_cast<Index>(col)) {
154 case Index::ID:
155 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.IdsData()[CurrentRow()]));
156 break;
157 case Index::TS:
158 SetTypeColumnInt64(slicesObj_.TimeStampData()[CurrentRow()], INVALID_UINT64);
159 break;
160 case Index::DURS:
161 SetTypeColumnInt64(slicesObj_.DursData()[CurrentRow()], INVALID_UINT64);
162 break;
163 case Index::CALL_IDS:
164 SetTypeColumnInt64(slicesObj_.CallIds()[CurrentRow()], INVALID_UINT64);
165 break;
166 #if IS_WASM
167 case Index::COLORINDEX:
168 SetTypeColumnInt64(slicesObj_.ColorIndexs()[CurrentRow()], INVALID_UINT64);
169 break;
170 #endif
171 case Index::CATS: {
172 SetTypeColumnText(slicesObj_.CatsData()[CurrentRow()], INVALID_UINT64);
173 break;
174 }
175 case Index::NAME: {
176 SetTypeColumnText(slicesObj_.NamesData()[CurrentRow()], INVALID_UINT64);
177 break;
178 default:
179 HandleTypeColumns(col);
180 }
181 }
182 return SQLITE_OK;
183 }
HandleTypeColumns(int32_t col) const184 void CallStackTable::Cursor::HandleTypeColumns(int32_t col) const
185 {
186 switch (static_cast<Index>(col)) {
187 case Index::DEPTHS:
188 SetTypeColumnInt64(slicesObj_.Depths()[CurrentRow()], INVALID_UINT64);
189 break;
190 case Index::COOKIES_ID:
191 SetTypeColumnInt64(slicesObj_.Cookies()[CurrentRow()], INVALID_INT64);
192 break;
193 case Index::PARENT_ID: {
194 if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) {
195 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.ParentIdData()[CurrentRow()].value()));
196 }
197 break;
198 }
199 case Index::ARGSET:
200 SetTypeColumnInt64(slicesObj_.ArgSetIdsData()[CurrentRow()], INVALID_UINT32);
201 break;
202 case Index::CHAIN_IDS:
203 SetTypeColumnTextNotEmpty(slicesObj_.ChainIds()[CurrentRow()].empty(),
204 slicesObj_.ChainIds()[CurrentRow()].c_str());
205 break;
206 case Index::SPAN_IDS:
207 SetTypeColumnTextNotEmpty(slicesObj_.SpanIds()[CurrentRow()].empty(),
208 slicesObj_.SpanIds()[CurrentRow()].c_str());
209 break;
210 case Index::PARENT_SPAN_IDS:
211 SetTypeColumnTextNotEmpty(slicesObj_.ParentSpanIds()[CurrentRow()].empty(),
212 slicesObj_.ParentSpanIds()[CurrentRow()].c_str());
213 break;
214 case Index::FLAGS:
215 SetTypeColumnTextNotEmpty(slicesObj_.Flags()[CurrentRow()].empty(),
216 slicesObj_.Flags()[CurrentRow()].c_str());
217 break;
218 default:
219 TS_LOGF("Unregistered column : %d", col);
220 break;
221 }
222 }
GetOrbyes(FilterConstraints &callfc, EstimatedIndexInfo &callei)223 void CallStackTable::GetOrbyes(FilterConstraints &callfc, EstimatedIndexInfo &callei)
224 {
225 auto orderbys = callfc.GetOrderBys();
226 for (auto i = 0; i < orderbys.size(); i++) {
227 switch (static_cast<Index>(orderbys[i].iColumn)) {
228 case Index::ID:
229 break;
230 default: // other columns can be sorted by SQLite
231 callei.isOrdered = false;
232 break;
233 }
234 }
235 }
236 } // namespace TraceStreamer
237 } // namespace SysTuning
238