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