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 "perf_call_chain_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t { ID = 0, CALLCHAIN_ID, DEPTH, IP, VADDR_IN_FILE, FILE_ID, SYMBOL_ID, NAME };
PerfCallChainTable(const TraceDataCache * dataCache)21 PerfCallChainTable::PerfCallChainTable(const TraceDataCache *dataCache) : TableBase(dataCache)
22 {
23 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
24 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
25 tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER"));
26 tableColumn_.push_back(TableBase::ColumnInfo("ip", "INTEGER"));
27 tableColumn_.push_back(TableBase::ColumnInfo("vaddr_in_file", "INTEGER"));
28 tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER"));
29 tableColumn_.push_back(TableBase::ColumnInfo("symbol_id", "INTEGER"));
30 tableColumn_.push_back(TableBase::ColumnInfo("name", "INTEGER"));
31 tablePriKey_.push_back("id");
32 }
33
~PerfCallChainTable()34 PerfCallChainTable::~PerfCallChainTable() {}
35
FilterByConstraint(FilterConstraints & chainfc,double & chainfilterCost,size_t chainrowCount,uint32_t chaincurrenti)36 void PerfCallChainTable::FilterByConstraint(FilterConstraints &chainfc,
37 double &chainfilterCost,
38 size_t chainrowCount,
39 uint32_t chaincurrenti)
40 {
41 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
42 // for loop
43 const auto &chainc = chainfc.GetConstraints()[chaincurrenti];
44 switch (static_cast<Index>(chainc.col)) {
45 case Index::ID: {
46 if (CanFilterId(chainc.op, chainrowCount)) {
47 chainfc.UpdateConstraint(chaincurrenti, true);
48 chainfilterCost += 1; // id can position by 1 step
49 } else {
50 chainfilterCost += chainrowCount; // scan all rows
51 }
52 break;
53 }
54 default: // other column
55 chainfilterCost += chainrowCount; // scan all rows
56 break;
57 }
58 }
59
CreateCursor()60 std::unique_ptr<TableBase::Cursor> PerfCallChainTable::CreateCursor()
61 {
62 return std::make_unique<Cursor>(dataCache_, this);
63 }
64
Cursor(const TraceDataCache * dataCache,TableBase * table)65 PerfCallChainTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
66 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstPerfCallChainData().Size())),
67 perfCallChainObj_(dataCache->GetConstPerfCallChainData())
68 {
69 }
70
~Cursor()71 PerfCallChainTable::Cursor::~Cursor() {}
72
Filter(const FilterConstraints & fc,sqlite3_value ** argv)73 int32_t PerfCallChainTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
74 {
75 // reset indexMap_
76 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
77
78 if (rowCount_ <= 0) {
79 return SQLITE_OK;
80 }
81
82 auto perfCallChainCs = fc.GetConstraints();
83 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)};
84 SwapIndexFront(perfCallChainCs, sId);
85 for (size_t i = 0; i < perfCallChainCs.size(); i++) {
86 const auto &c = perfCallChainCs[i];
87 switch (static_cast<Index>(c.col)) {
88 case Index::ID:
89 FilterId(c.op, argv[c.idxInaConstraint]);
90 break;
91 case Index::CALLCHAIN_ID:
92 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
93 perfCallChainObj_.CallChainIds());
94 break;
95 case Index::FILE_ID:
96 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
97 perfCallChainObj_.FileIds());
98 break;
99 case Index::SYMBOL_ID:
100 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
101 perfCallChainObj_.SymbolIds());
102 break;
103 default:
104 break;
105 }
106 }
107
108 auto perfCallChainOrderbys = fc.GetOrderBys();
109 for (auto i = perfCallChainOrderbys.size(); i > 0;) {
110 i--;
111 switch (static_cast<Index>(perfCallChainOrderbys[i].iColumn)) {
112 case Index::ID:
113 indexMap_->SortBy(perfCallChainOrderbys[i].desc);
114 break;
115 default:
116 break;
117 }
118 }
119
120 return SQLITE_OK;
121 }
122
Column(int32_t column) const123 int32_t PerfCallChainTable::Cursor::Column(int32_t column) const
124 {
125 switch (static_cast<Index>(column)) {
126 case Index::ID:
127 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.IdsData()[CurrentRow()]));
128 break;
129 case Index::CALLCHAIN_ID:
130 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.CallChainIds()[CurrentRow()]));
131 break;
132 case Index::DEPTH:
133 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Depths()[CurrentRow()]));
134 break;
135 case Index::IP:
136 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Ips()[CurrentRow()]));
137 break;
138 case Index::VADDR_IN_FILE:
139 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.VaddrInFiles()[CurrentRow()]));
140 break;
141 case Index::FILE_ID:
142 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.FileIds()[CurrentRow()]));
143 break;
144 case Index::SYMBOL_ID:
145 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.SymbolIds()[CurrentRow()]));
146 break;
147 case Index::NAME:
148 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Names()[CurrentRow()]));
149 break;
150 default:
151 TS_LOGF("Unregistered column : %d", column);
152 break;
153 }
154 return SQLITE_OK;
155 }
156
GetOrbyes(FilterConstraints & chainfc,EstimatedIndexInfo & chainei)157 void PerfCallChainTable::GetOrbyes(FilterConstraints &chainfc, EstimatedIndexInfo &chainei)
158 {
159 auto chainorderbys = chainfc.GetOrderBys();
160 for (auto i = 0; i < chainorderbys.size(); i++) {
161 switch (static_cast<Index>(chainorderbys[i].iColumn)) {
162 case Index::ID:
163 break;
164 default: // other columns can be sorted by SQLite
165 chainei.isOrdered = false;
166 break;
167 }
168 }
169 }
170 } // namespace TraceStreamer
171 } // namespace SysTuning
172