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