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 "native_hook_statistic_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t {
21 ID = 0,
22 CALLCHAIN_ID,
23 IPID,
24 TS,
25 MEMORY_TYPE,
26 MEMORY_SUB_TYPE,
27 APPLY_COUNT,
28 RELEASE_COUNT,
29 APPLY_SIZE,
30 RELEASE_SIZE,
31 LAST_LIB_ID,
32 LAST_SYMBOL_ID
33 };
NativeHookStatisticTable(const TraceDataCache * dataCache)34 NativeHookStatisticTable::NativeHookStatisticTable(const TraceDataCache *dataCache) : TableBase(dataCache)
35 {
36 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
37 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
38 tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER"));
39 tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
40 tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER"));
41 tableColumn_.push_back(TableBase::ColumnInfo("sub_type_id", "INTEGER"));
42 tableColumn_.push_back(TableBase::ColumnInfo("apply_count", "INTEGER"));
43 tableColumn_.push_back(TableBase::ColumnInfo("release_count", "INTEGER"));
44 tableColumn_.push_back(TableBase::ColumnInfo("apply_size", "INTEGER"));
45 tableColumn_.push_back(TableBase::ColumnInfo("release_size", "INTEGER"));
46 tableColumn_.push_back(TableBase::ColumnInfo("last_lib_id", "INTEGER"));
47 tableColumn_.push_back(TableBase::ColumnInfo("last_symbol_id", "INTEGER"));
48 tablePriKey_.push_back("id");
49 }
50
~NativeHookStatisticTable()51 NativeHookStatisticTable::~NativeHookStatisticTable() {}
52
FilterByConstraint(FilterConstraints & statisticfc,double & statisticfilterCost,size_t statisticrowCount,uint32_t statisticcurrenti)53 void NativeHookStatisticTable::FilterByConstraint(FilterConstraints &statisticfc,
54 double &statisticfilterCost,
55 size_t statisticrowCount,
56 uint32_t statisticcurrenti)
57 {
58 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
59 // for loop
60 const auto &statisticc = statisticfc.GetConstraints()[statisticcurrenti];
61 switch (static_cast<Index>(statisticc.col)) {
62 case Index::ID: {
63 if (CanFilterId(statisticc.op, statisticrowCount)) {
64 statisticfc.UpdateConstraint(statisticcurrenti, true);
65 statisticfilterCost += 1; // id can position by 1 step
66 } else {
67 statisticfilterCost += statisticrowCount; // scan all rows
68 }
69 break;
70 }
71 default: // other column
72 statisticfilterCost += statisticrowCount; // scan all rows
73 break;
74 }
75 }
76
CreateCursor()77 std::unique_ptr<TableBase::Cursor> NativeHookStatisticTable::CreateCursor()
78 {
79 return std::make_unique<Cursor>(dataCache_, this);
80 }
81
Cursor(const TraceDataCache * dataCache,TableBase * table)82 NativeHookStatisticTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
83 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstNativeHookStatisticData().Size())),
84 nativeHookStatisticInfoObj_(dataCache->GetConstNativeHookStatisticData())
85 {
86 }
87
~Cursor()88 NativeHookStatisticTable::Cursor::~Cursor() {}
89
Filter(const FilterConstraints & fc,sqlite3_value ** argv)90 int32_t NativeHookStatisticTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
91 {
92 // reset indexMap_
93 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
94
95 if (rowCount_ <= 0) {
96 return SQLITE_OK;
97 }
98
99 auto nativeHookStatisticCs = fc.GetConstraints();
100 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)};
101 SwapIndexFront(nativeHookStatisticCs, sId);
102 for (size_t i = 0; i < nativeHookStatisticCs.size(); i++) {
103 const auto &c = nativeHookStatisticCs[i];
104 switch (static_cast<Index>(c.col)) {
105 case Index::ID:
106 FilterId(c.op, argv[c.idxInaConstraint]);
107 break;
108 case Index::CALLCHAIN_ID:
109 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
110 nativeHookStatisticInfoObj_.CallChainIds());
111 break;
112 default:
113 break;
114 }
115 }
116
117 auto nativeHookStatisticOrderbys = fc.GetOrderBys();
118 for (auto i = nativeHookStatisticOrderbys.size(); i > 0;) {
119 i--;
120 switch (static_cast<Index>(nativeHookStatisticOrderbys[i].iColumn)) {
121 case Index::ID:
122 indexMap_->SortBy(nativeHookStatisticOrderbys[i].desc);
123 break;
124 default:
125 break;
126 }
127 }
128
129 return SQLITE_OK;
130 }
131
Column(int32_t column) const132 int32_t NativeHookStatisticTable::Cursor::Column(int32_t column) const
133 {
134 switch (static_cast<Index>(column)) {
135 case Index::ID:
136 sqlite3_result_int64(context_, static_cast<int32_t>(nativeHookStatisticInfoObj_.IdsData()[CurrentRow()]));
137 break;
138 case Index::CALLCHAIN_ID:
139 SetTypeColumn(nativeHookStatisticInfoObj_.CallChainIds()[CurrentRow()], INVALID_UINT32,
140 INVALID_CALL_CHAIN_ID);
141 break;
142 case Index::IPID:
143 SetTypeColumnInt64(nativeHookStatisticInfoObj_.Ipids()[CurrentRow()], INVALID_UINT32);
144 break;
145 case Index::TS:
146 SetTypeColumnInt64(nativeHookStatisticInfoObj_.TimeStampData()[CurrentRow()], INVALID_UINT64);
147 break;
148 case Index::MEMORY_TYPE:
149 SetTypeColumnInt64(nativeHookStatisticInfoObj_.MemoryTypes()[CurrentRow()], INVALID_UINT64);
150 break;
151 case Index::MEMORY_SUB_TYPE:
152 SetTypeColumnInt64(nativeHookStatisticInfoObj_.MemorySubTypes()[CurrentRow()], INVALID_UINT64);
153 break;
154 case Index::APPLY_COUNT:
155 SetTypeColumnInt64(nativeHookStatisticInfoObj_.ApplyCounts()[CurrentRow()], INVALID_UINT64);
156 break;
157 case Index::RELEASE_COUNT:
158 SetTypeColumnInt64(nativeHookStatisticInfoObj_.ReleaseCounts()[CurrentRow()], INVALID_UINT64);
159 break;
160 case Index::APPLY_SIZE:
161 SetTypeColumnInt64(nativeHookStatisticInfoObj_.ApplySizes()[CurrentRow()], INVALID_UINT64);
162 break;
163 case Index::RELEASE_SIZE:
164 SetTypeColumnInt64(nativeHookStatisticInfoObj_.ReleaseSizes()[CurrentRow()], INVALID_UINT64);
165 break;
166 case Index::LAST_LIB_ID:
167 SetTypeColumnInt64(nativeHookStatisticInfoObj_.LastCallerPathIndexs()[CurrentRow()], INVALID_DATAINDEX);
168 break;
169 case Index::LAST_SYMBOL_ID:
170 SetTypeColumnInt64(nativeHookStatisticInfoObj_.LastSymbolIndexs()[CurrentRow()], INVALID_DATAINDEX);
171 break;
172 default:
173 TS_LOGF("Unregistered column : %d", column);
174 break;
175 }
176 return SQLITE_OK;
177 }
178
GetOrbyes(FilterConstraints & statisticfc,EstimatedIndexInfo & statisticei)179 void NativeHookStatisticTable::GetOrbyes(FilterConstraints &statisticfc, EstimatedIndexInfo &statisticei)
180 {
181 auto statisticorderbys = statisticfc.GetOrderBys();
182 for (auto i = 0; i < statisticorderbys.size(); i++) {
183 switch (static_cast<Index>(statisticorderbys[i].iColumn)) {
184 case Index::ID:
185 break;
186 default: // other columns can be sorted by SQLite
187 statisticei.isOrdered = false;
188 break;
189 }
190 }
191 }
192 } // namespace TraceStreamer
193 } // namespace SysTuning
194