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_napi_async_table.h"
17 #include "ts_common.h"
18
19 namespace SysTuning {
20 namespace TraceStreamer {
21 enum class Index : int32_t {
22 ID = 0,
23 TS,
24 TRACEID,
25 CPU_ID,
26 THREAD_ID,
27 PROCESS_ID,
28 CALLER_CALLCHAINID,
29 CALLEE_CALLCHAINID,
30 PERF_SAMPLE_ID,
31 EVENT_COUNT,
32 EVENT_TYPE_ID,
33 };
PerfNapiAsyncTable(const TraceDataCache *dataCache)34 PerfNapiAsyncTable::PerfNapiAsyncTable(const TraceDataCache *dataCache) : TableBase(dataCache)
35 {
36 tableColumn_.emplace_back("id", "INTEGER");
37 tableColumn_.emplace_back("ts", "INTEGER");
38 tableColumn_.emplace_back("traceid", "TEXT");
39 tableColumn_.emplace_back("cpu_id", "INTEGER");
40 tableColumn_.emplace_back("thread_id", "INTEGER");
41 tableColumn_.emplace_back("process_id", "INTEGER");
42 tableColumn_.emplace_back("caller_callchainid", "INTEGER");
43 tableColumn_.emplace_back("callee_callchainid", "INTEGER");
44 tableColumn_.emplace_back("perf_sample_id", "INTEGER");
45 tableColumn_.emplace_back("event_count", "INTEGER");
46 tableColumn_.emplace_back("event_type_id", "INTEGER");
47 tablePriKey_.emplace_back("id");
48 }
49
~PerfNapiAsyncTable()50 PerfNapiAsyncTable::~PerfNapiAsyncTable() {}
51
FilterByConstraint(FilterConstraints &napiAsyncFc, double &napiAsyncFilterCost, size_t napiAsyncRowCount, uint32_t napiAsyncCurrenti)52 void PerfNapiAsyncTable::FilterByConstraint(FilterConstraints &napiAsyncFc,
53 double &napiAsyncFilterCost,
54 size_t napiAsyncRowCount,
55 uint32_t napiAsyncCurrenti)
56 {
57 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
58 // for loop
59 const auto &napiAsyncC = napiAsyncFc.GetConstraints()[napiAsyncCurrenti];
60 switch (static_cast<Index>(napiAsyncC.col)) {
61 case Index::ID: {
62 if (CanFilterId(napiAsyncC.op, napiAsyncRowCount)) {
63 napiAsyncFc.UpdateConstraint(napiAsyncCurrenti, true);
64 napiAsyncFilterCost += 1; // id can position by 1 step
65 } else {
66 napiAsyncFilterCost += napiAsyncRowCount; // scan all rows
67 }
68 break;
69 }
70 default: // other column
71 napiAsyncFilterCost += napiAsyncRowCount; // scan all rows
72 break;
73 }
74 }
75
CreateCursor()76 std::unique_ptr<TableBase::Cursor> PerfNapiAsyncTable::CreateCursor()
77 {
78 return std::make_unique<Cursor>(dataCache_, this);
79 }
80
Cursor(const TraceDataCache *dataCache, TableBase *table)81 PerfNapiAsyncTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
82 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstPerfNapiAsyncData().Size())),
83 perfNapiAsyncObj_(dataCache->GetConstPerfNapiAsyncData())
84 {
85 }
86
~Cursor()87 PerfNapiAsyncTable::Cursor::~Cursor() {}
88
Filter(const FilterConstraints &fc, sqlite3_value **argv)89 int32_t PerfNapiAsyncTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
90 {
91 // reset indexMap_
92 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
93
94 if (rowCount_ <= 0) {
95 return SQLITE_OK;
96 }
97
98 auto perfNapiAsyncCs = fc.GetConstraints();
99 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)};
100 SwapIndexFront(perfNapiAsyncCs, sId);
101 for (size_t i = 0; i < perfNapiAsyncCs.size(); i++) {
102 const auto &c = perfNapiAsyncCs[i];
103 switch (static_cast<Index>(c.col)) {
104 case Index::ID:
105 FilterId(c.op, argv[c.idxInaConstraint]);
106 break;
107 case Index::TRACEID:
108 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
109 perfNapiAsyncObj_.Traceids());
110 break;
111 case Index::THREAD_ID:
112 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
113 perfNapiAsyncObj_.InternalTidsData());
114 break;
115 case Index::CALLER_CALLCHAINID:
116 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
117 perfNapiAsyncObj_.CallerCallchainids());
118 break;
119 case Index::CALLEE_CALLCHAINID:
120 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
121 perfNapiAsyncObj_.CalleeCallchainids());
122 break;
123 default:
124 break;
125 }
126 }
127
128 auto perfNapiAsyncOrderbys = fc.GetOrderBys();
129 for (auto i = perfNapiAsyncOrderbys.size(); i > 0;) {
130 i--;
131 switch (static_cast<Index>(perfNapiAsyncOrderbys[i].iColumn)) {
132 case Index::ID:
133 indexMap_->SortBy(perfNapiAsyncOrderbys[i].desc);
134 break;
135 default:
136 break;
137 }
138 }
139
140 return SQLITE_OK;
141 }
142
Column(int32_t column) const143 int32_t PerfNapiAsyncTable::Cursor::Column(int32_t column) const
144 {
145 switch (static_cast<Index>(column)) {
146 case Index::ID:
147 sqlite3_result_int64(context_, perfNapiAsyncObj_.IdsData()[CurrentRow()]);
148 break;
149 case Index::TS:
150 SetTypeColumnInt64(perfNapiAsyncObj_.TimeStampData()[CurrentRow()], INVALID_UINT64);
151 break;
152 case Index::TRACEID:
153 SetTypeColumnText(perfNapiAsyncObj_.Traceids()[CurrentRow()], INVALID_UINT64);
154 break;
155 case Index::CPU_ID:
156 SetTypeColumnInt64(perfNapiAsyncObj_.CpuIds()[CurrentRow()], INVALID_UINT64);
157 break;
158 case Index::THREAD_ID:
159 SetTypeColumnInt64(perfNapiAsyncObj_.InternalTidsData()[CurrentRow()], INVALID_UINT64);
160 break;
161 case Index::PROCESS_ID:
162 SetTypeColumnInt64(perfNapiAsyncObj_.ProcessIds()[CurrentRow()], INVALID_UINT64);
163 break;
164 case Index::CALLER_CALLCHAINID:
165 SetTypeColumnInt64(perfNapiAsyncObj_.CallerCallchainids()[CurrentRow()], INVALID_UINT64);
166 break;
167 case Index::CALLEE_CALLCHAINID:
168 SetTypeColumnInt64(perfNapiAsyncObj_.CalleeCallchainids()[CurrentRow()], INVALID_UINT64);
169 break;
170 case Index::PERF_SAMPLE_ID:
171 SetTypeColumnInt64(perfNapiAsyncObj_.PerfSampleIds()[CurrentRow()], INVALID_UINT64);
172 break;
173 case Index::EVENT_COUNT:
174 SetTypeColumnInt64(perfNapiAsyncObj_.EventCounts()[CurrentRow()], INVALID_UINT64);
175 break;
176 case Index::EVENT_TYPE_ID:
177 SetTypeColumnInt64(perfNapiAsyncObj_.EventTypeIds()[CurrentRow()], INVALID_UINT64);
178 break;
179 default:
180 TS_LOGF("Unregistered column : %d", column);
181 break;
182 }
183 return SQLITE_OK;
184 }
185
GetOrbyes(FilterConstraints &napiAsyncFc, EstimatedIndexInfo &napiAsyncEi)186 void PerfNapiAsyncTable::GetOrbyes(FilterConstraints &napiAsyncFc, EstimatedIndexInfo &napiAsyncEi)
187 {
188 auto napiAsyncOrderbys = napiAsyncFc.GetOrderBys();
189 for (auto i = 0; i < napiAsyncOrderbys.size(); i++) {
190 switch (static_cast<Index>(napiAsyncOrderbys[i].iColumn)) {
191 case Index::ID:
192 break;
193 default: // other columns can be sorted by SQLite
194 napiAsyncEi.isOrdered = false;
195 break;
196 }
197 }
198 }
199 } // namespace TraceStreamer
200 } // namespace SysTuning
201