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