• 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 #include "ebpf_elf_table.h"
16 
17 namespace SysTuning {
18 namespace TraceStreamer {
19 namespace {
20 enum Index {
21     ID = 0,
22     ELF_ID,
23     TEXT_VADDR,
24     TEXT_OFFSET,
25     STR_TAB_LEN,
26     SYM_TAB_LEN,
27     FILE_NAME_LEN,
28     SYM_ENT_LEN,
29     FILE_PATH_ID,
30 };
31 }
EbpfElfTable(const TraceDataCache * dataCache)32 EbpfElfTable::EbpfElfTable(const TraceDataCache* dataCache) : TableBase(dataCache)
33 {
34     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
35     tableColumn_.push_back(TableBase::ColumnInfo("elf_id", "INTEGER"));
36     tableColumn_.push_back(TableBase::ColumnInfo("text_vaddr", "INTEGER"));
37     tableColumn_.push_back(TableBase::ColumnInfo("text_offset", "INTEGER"));
38     tableColumn_.push_back(TableBase::ColumnInfo("str_tab_len", "INTEGER"));
39     tableColumn_.push_back(TableBase::ColumnInfo("sym_tab_len", "INTEGER"));
40     tableColumn_.push_back(TableBase::ColumnInfo("file_name_len", "INTEGER"));
41     tableColumn_.push_back(TableBase::ColumnInfo("sym_ent_len", "INTEGER"));
42     tableColumn_.push_back(TableBase::ColumnInfo("file_path_id", "INTEGER"));
43     tablePriKey_.push_back("id");
44 }
45 
~EbpfElfTable()46 EbpfElfTable::~EbpfElfTable() {}
47 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)48 void EbpfElfTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
49 {
50     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
51     constexpr double indexCost = 2.0;
52     ei.estimatedCost = filterBaseCost;
53 
54     auto rowCount = dataCache_->GetConstHidumpData().Size();
55     if (rowCount == 0 || rowCount == 1) {
56         ei.estimatedRows = rowCount;
57         ei.estimatedCost += indexCost * rowCount;
58         return;
59     }
60 
61     double filterCost = 0.0;
62     auto constraints = fc.GetConstraints();
63     if (constraints.empty()) { // scan all rows
64         filterCost = rowCount;
65     } else {
66         FilterByConstraint(fc, filterCost, rowCount);
67     }
68     ei.estimatedCost += filterCost;
69     ei.estimatedRows = rowCount;
70     ei.estimatedCost += rowCount * indexCost;
71 
72     ei.isOrdered = true;
73     auto orderbys = fc.GetOrderBys();
74     for (auto i = 0; i < orderbys.size(); i++) {
75         switch (orderbys[i].iColumn) {
76             case ID:
77                 break;
78             default: // other columns can be sorted by SQLite
79                 ei.isOrdered = false;
80                 break;
81         }
82     }
83 }
84 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)85 void EbpfElfTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
86 {
87     auto fcConstraints = fc.GetConstraints();
88     for (int i = 0; i < static_cast<int>(fcConstraints.size()); i++) {
89         if (rowCount <= 1) {
90             // only one row or nothing, needn't filter by constraint
91             filterCost += rowCount;
92             break;
93         }
94         const auto& c = fcConstraints[i];
95         switch (c.col) {
96             case ID: {
97                 if (CanFilterId(c.op, rowCount)) {
98                     fc.UpdateConstraint(i, true);
99                     filterCost += 1; // id can position by 1 step
100                 } else {
101                     filterCost += rowCount; // scan all rows
102                 }
103                 break;
104             }
105             default:                    // other column
106                 filterCost += rowCount; // scan all rows
107                 break;
108         }
109     }
110 }
111 
CanFilterId(const char op,size_t & rowCount)112 bool EbpfElfTable::CanFilterId(const char op, size_t& rowCount)
113 {
114     switch (op) {
115         case SQLITE_INDEX_CONSTRAINT_EQ:
116             rowCount = 1;
117             break;
118         case SQLITE_INDEX_CONSTRAINT_GT:
119         case SQLITE_INDEX_CONSTRAINT_GE:
120         case SQLITE_INDEX_CONSTRAINT_LE:
121         case SQLITE_INDEX_CONSTRAINT_LT:
122             // assume filter out a half of rows
123             rowCount = (rowCount >> 1);
124             break;
125         default:
126             return false;
127     }
128     return true;
129 }
130 
CreateCursor()131 std::unique_ptr<TableBase::Cursor> EbpfElfTable::CreateCursor()
132 {
133     return std::make_unique<Cursor>(dataCache_, this);
134 }
135 
Cursor(const TraceDataCache * dataCache,TableBase * table)136 EbpfElfTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
137     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstEbpfElf().Size())),
138       ebpfElfObj_(dataCache->GetConstEbpfElf())
139 {
140 }
141 
~Cursor()142 EbpfElfTable::Cursor::~Cursor() {}
143 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)144 int EbpfElfTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
145 {
146     // reset indexMap_
147     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
148 
149     if (rowCount_ <= 0) {
150         return SQLITE_OK;
151     }
152 
153     auto& cs = fc.GetConstraints();
154     for (size_t i = 0; i < cs.size(); i++) {
155         const auto& c = cs[i];
156         switch (c.col) {
157             case ID:
158                 FilterId(c.op, argv[i]);
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(int column) const180 int EbpfElfTable::Cursor::Column(int column) const
181 {
182     switch (column) {
183         case ID:
184             sqlite3_result_int64(context_, static_cast<int32_t>(ebpfElfObj_.IdsData()[CurrentRow()]));
185             break;
186         case ELF_ID:
187             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.ElfIds()[CurrentRow()]));
188             break;
189         case TEXT_VADDR:
190             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.TextVaddrs()[CurrentRow()]));
191             break;
192         case TEXT_OFFSET:
193             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.TextOffsets()[CurrentRow()]));
194             break;
195         case STR_TAB_LEN:
196             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.StrTabLens()[CurrentRow()]));
197             break;
198         case SYM_TAB_LEN: {
199             if (ebpfElfObj_.SymTabLens()[CurrentRow()] != INVALID_UINT64) {
200                 sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.SymTabLens()[CurrentRow()]));
201             }
202             break;
203         }
204         case FILE_NAME_LEN: {
205             if (ebpfElfObj_.FileNameLens()[CurrentRow()] != INVALID_UINT64) {
206                 sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.FileNameLens()[CurrentRow()]));
207             }
208             break;
209         }
210         case SYM_ENT_LEN: {
211             if (ebpfElfObj_.SymEntLens()[CurrentRow()] != INVALID_UINT64) {
212                 sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.SymEntLens()[CurrentRow()]));
213             }
214             break;
215         }
216         case FILE_PATH_ID: {
217             if (ebpfElfObj_.FileNameIndexs()[CurrentRow()] != INVALID_UINT64) {
218                 sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfObj_.FileNameIndexs()[CurrentRow()]));
219             }
220             break;
221         }
222         default:
223             TS_LOGF("Unregistered column : %d", column);
224             break;
225     }
226     return SQLITE_OK;
227 }
228 
FilterId(unsigned char op,sqlite3_value * argv)229 void EbpfElfTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv)
230 {
231     auto type = sqlite3_value_type(argv);
232     if (type != SQLITE_INTEGER) {
233         // other type consider it NULL
234         indexMap_->Intersect(0, 0);
235         return;
236     }
237 
238     auto v = static_cast<TableRowId>(sqlite3_value_int64(argv));
239     switch (op) {
240         case SQLITE_INDEX_CONSTRAINT_EQ:
241             indexMap_->Intersect(v, v + 1);
242             break;
243         case SQLITE_INDEX_CONSTRAINT_GE:
244             indexMap_->Intersect(v, rowCount_);
245             break;
246         case SQLITE_INDEX_CONSTRAINT_GT:
247             v++;
248             indexMap_->Intersect(v, rowCount_);
249             break;
250         case SQLITE_INDEX_CONSTRAINT_LE:
251             v++;
252             indexMap_->Intersect(0, v);
253             break;
254         case SQLITE_INDEX_CONSTRAINT_LT:
255             indexMap_->Intersect(0, v);
256             break;
257         default:
258             // can't filter, all rows
259             break;
260     }
261 }
262 } // namespace TraceStreamer
263 } // namespace SysTuning
264