• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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