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