• 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 "native_hook_table.h"
17 
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum Index {
21     ID = 0,
22     CALLCHAIN_ID,
23     IPID,
24     ITID,
25     EVENT_TYPE,
26     SUB_TYPE_ID,
27     START_TS,
28     END_TS,
29     DURATION,
30     ADDR,
31     MEM_SIZE,
32     ALL_MEM_SIZE,
33     CURRENT_SIZE_DUR,
34     LAST_LIB_ID
35 };
NativeHookTable(const TraceDataCache * dataCache)36 NativeHookTable::NativeHookTable(const TraceDataCache* dataCache) : TableBase(dataCache)
37 {
38     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
39     tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
40     tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER"));
41     tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
42     tableColumn_.push_back(TableBase::ColumnInfo("event_type", "TEXT"));
43     tableColumn_.push_back(TableBase::ColumnInfo("sub_type_id", "INTEGER"));
44     tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER"));
45     tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER"));
46     tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
47     tableColumn_.push_back(TableBase::ColumnInfo("addr", "INTEGER"));
48     tableColumn_.push_back(TableBase::ColumnInfo("heap_size", "INTEGER"));
49     tableColumn_.push_back(TableBase::ColumnInfo("all_heap_size", "INTEGER"));
50     tableColumn_.push_back(TableBase::ColumnInfo("current_size_dur", "INTEGER"));
51     tableColumn_.push_back(TableBase::ColumnInfo("last_lib_id", "INTEGER"));
52     tablePriKey_.push_back("id");
53 }
54 
~NativeHookTable()55 NativeHookTable::~NativeHookTable() {}
56 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)57 void NativeHookTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
58 {
59     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
60     constexpr double indexCost = 2.0;
61     ei.estimatedCost = filterBaseCost;
62 
63     auto rowCount = dataCache_->GetConstNativeHookData().Size();
64     if (rowCount == 0 || rowCount == 1) {
65         ei.estimatedRows = rowCount;
66         ei.estimatedCost += indexCost * rowCount;
67         return;
68     }
69 
70     double filterCost = 0.0;
71     auto constraints = fc.GetConstraints();
72     if (constraints.empty()) { // scan all rows
73         filterCost = rowCount;
74     } else {
75         FilterByConstraint(fc, filterCost, rowCount);
76     }
77     ei.estimatedCost += filterCost;
78     ei.estimatedRows = rowCount;
79     ei.estimatedCost += rowCount * indexCost;
80 
81     ei.isOrdered = true;
82     auto orderbys = fc.GetOrderBys();
83     for (auto i = 0; i < orderbys.size(); i++) {
84         switch (orderbys[i].iColumn) {
85             case ID:
86                 break;
87             default: // other columns can be sorted by SQLite
88                 ei.isOrdered = false;
89                 break;
90         }
91     }
92 }
93 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)94 void NativeHookTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
95 {
96     auto fcConstraints = fc.GetConstraints();
97     for (int32_t i = 0; i < static_cast<int32_t>(fcConstraints.size()); i++) {
98         if (rowCount <= 1) {
99             // only one row or nothing, needn't filter by constraint
100             filterCost += rowCount;
101             break;
102         }
103         const auto& c = fcConstraints[i];
104         switch (c.col) {
105             case ID: {
106                 if (CanFilterId(c.op, rowCount)) {
107                     fc.UpdateConstraint(i, true);
108                     filterCost += 1; // id can position by 1 step
109                 } else {
110                     filterCost += rowCount; // scan all rows
111                 }
112                 break;
113             }
114             default:                    // other column
115                 filterCost += rowCount; // scan all rows
116                 break;
117         }
118     }
119 }
120 
CreateCursor()121 std::unique_ptr<TableBase::Cursor> NativeHookTable::CreateCursor()
122 {
123     return std::make_unique<Cursor>(dataCache_, this);
124 }
125 
Cursor(const TraceDataCache * dataCache,TableBase * table)126 NativeHookTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
127     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstNativeHookData().Size())),
128       nativeHookObj_(dataCache->GetConstNativeHookData())
129 {
130 }
131 
~Cursor()132 NativeHookTable::Cursor::~Cursor() {}
133 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)134 int32_t NativeHookTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
135 {
136     // reset indexMap_
137     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
138 
139     if (rowCount_ <= 0) {
140         return SQLITE_OK;
141     }
142 
143     auto& cs = fc.GetConstraints();
144     for (size_t i = 0; i < cs.size(); i++) {
145         const auto& c = cs[i];
146         switch (c.col) {
147             case ID:
148                 FilterId(c.op, argv[i]);
149                 break;
150             case IPID:
151                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])), nativeHookObj_.Ipids());
152                 break;
153             case ITID:
154                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])), nativeHookObj_.Itids());
155                 break;
156             case CALLCHAIN_ID:
157                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[i])),
158                                     nativeHookObj_.CallChainIds());
159                 break;
160             default:
161                 break;
162         }
163     }
164 
165     auto orderbys = fc.GetOrderBys();
166     for (auto i = orderbys.size(); i > 0;) {
167         i--;
168         switch (orderbys[i].iColumn) {
169             case ID:
170                 indexMap_->SortBy(orderbys[i].desc);
171                 break;
172             default:
173                 break;
174         }
175     }
176 
177     return SQLITE_OK;
178 }
179 
Column(int32_t column) const180 int32_t NativeHookTable::Cursor::Column(int32_t column) const
181 {
182     switch (column) {
183         case ID:
184             sqlite3_result_int64(context_, static_cast<int32_t>(CurrentRow()));
185             break;
186         case CALLCHAIN_ID:
187             if (nativeHookObj_.CallChainIds()[CurrentRow()] != INVALID_UINT32) {
188                 sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.CallChainIds()[CurrentRow()]));
189             } else {
190                 sqlite3_result_int64(context_, static_cast<int64_t>(INVALID_CALL_CHAIN_ID));
191             }
192             break;
193         case IPID:
194             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.Ipids()[CurrentRow()]));
195             break;
196         case ITID:
197             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.Itids()[CurrentRow()]));
198             break;
199         case EVENT_TYPE: {
200             if (!nativeHookObj_.EventTypes()[CurrentRow()].empty()) {
201                 sqlite3_result_text(context_, nativeHookObj_.EventTypes()[CurrentRow()].c_str(), STR_DEFAULT_LEN,
202                                     nullptr);
203             }
204             break;
205         }
206         case SUB_TYPE_ID: {
207             if (nativeHookObj_.SubTypes()[CurrentRow()] != INVALID_UINT64) {
208                 sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.SubTypes()[CurrentRow()]));
209             }
210             break;
211         }
212         case START_TS:
213             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.TimeStampData()[CurrentRow()]));
214             break;
215         case END_TS:
216             if (static_cast<int64_t>(nativeHookObj_.EndTimeStamps()[CurrentRow()]) != 0) {
217                 sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.EndTimeStamps()[CurrentRow()]));
218             }
219             break;
220         case DURATION:
221             if (static_cast<int64_t>(nativeHookObj_.Durations()[CurrentRow()]) != 0) {
222                 sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.Durations()[CurrentRow()]));
223             }
224             break;
225         case ADDR: {
226             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.Addrs()[CurrentRow()]));
227             break;
228         }
229         case MEM_SIZE: {
230             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.MemSizes()[CurrentRow()]));
231             break;
232         }
233         case ALL_MEM_SIZE: {
234             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.AllMemSizes()[CurrentRow()]));
235             break;
236         }
237         case CURRENT_SIZE_DUR: {
238             sqlite3_result_int64(context_, static_cast<int64_t>(nativeHookObj_.CurrentSizeDurs()[CurrentRow()]));
239             break;
240         }
241         case LAST_LIB_ID: {
242             if (nativeHookObj_.LastCallerPathIndexs()[CurrentRow()] != INVALID_UINT64) {
243                 sqlite3_result_int64(context_,
244                                      static_cast<int64_t>(nativeHookObj_.LastCallerPathIndexs()[CurrentRow()]));
245             }
246             break;
247         }
248         default:
249             TS_LOGF("Unregistered column : %d", column);
250             break;
251     }
252     return SQLITE_OK;
253 }
254 } // namespace TraceStreamer
255 } // namespace SysTuning
256