• 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_symbol_table.h"
16 
17 namespace SysTuning {
18 namespace TraceStreamer {
19 namespace {
20 enum Index {
21     ID = 0,
22     ELF_ID,
23     ST_NAME,
24     ST_VALUE,
25     ST_SIZE,
26 };
27 }
EbpfElfSymbolTable(const TraceDataCache * dataCache)28 EbpfElfSymbolTable::EbpfElfSymbolTable(const TraceDataCache* dataCache) : TableBase(dataCache)
29 {
30     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
31     tableColumn_.push_back(TableBase::ColumnInfo("elf_id", "INTEGER"));
32     tableColumn_.push_back(TableBase::ColumnInfo("st_name", "INTEGER"));
33     tableColumn_.push_back(TableBase::ColumnInfo("st_value", "INTEGER"));
34     tableColumn_.push_back(TableBase::ColumnInfo("st_size", "INTEGER"));
35     tablePriKey_.push_back("id");
36 }
37 
~EbpfElfSymbolTable()38 EbpfElfSymbolTable::~EbpfElfSymbolTable() {}
39 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)40 void EbpfElfSymbolTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
41 {
42     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
43     constexpr double indexCost = 2.0;
44     ei.estimatedCost = filterBaseCost;
45 
46     auto rowCount = dataCache_->GetConstHidumpData().Size();
47     if (rowCount == 0 || rowCount == 1) {
48         ei.estimatedRows = rowCount;
49         ei.estimatedCost += indexCost * rowCount;
50         return;
51     }
52 
53     double filterCost = 0.0;
54     auto constraints = fc.GetConstraints();
55     if (constraints.empty()) { // scan all rows
56         filterCost = rowCount;
57     } else {
58         FilterByConstraint(fc, filterCost, rowCount);
59     }
60     ei.estimatedCost += filterCost;
61     ei.estimatedRows = rowCount;
62     ei.estimatedCost += rowCount * indexCost;
63 
64     ei.isOrdered = true;
65     auto orderbys = fc.GetOrderBys();
66     for (auto i = 0; i < orderbys.size(); i++) {
67         switch (orderbys[i].iColumn) {
68             case ID:
69                 break;
70             default: // other columns can be sorted by SQLite
71                 ei.isOrdered = false;
72                 break;
73         }
74     }
75 }
76 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)77 void EbpfElfSymbolTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
78 {
79     auto fcConstraints = fc.GetConstraints();
80     for (int i = 0; i < static_cast<int>(fcConstraints.size()); i++) {
81         if (rowCount <= 1) {
82             // only one row or nothing, needn't filter by constraint
83             filterCost += rowCount;
84             break;
85         }
86         const auto& c = fcConstraints[i];
87         switch (c.col) {
88             case ID: {
89                 if (CanFilterId(c.op, rowCount)) {
90                     fc.UpdateConstraint(i, true);
91                     filterCost += 1; // id can position by 1 step
92                 } else {
93                     filterCost += rowCount; // scan all rows
94                 }
95                 break;
96             }
97             default:                    // other column
98                 filterCost += rowCount; // scan all rows
99                 break;
100         }
101     }
102 }
103 
CanFilterId(const char op,size_t & rowCount)104 bool EbpfElfSymbolTable::CanFilterId(const char op, size_t& rowCount)
105 {
106     switch (op) {
107         case SQLITE_INDEX_CONSTRAINT_EQ:
108             rowCount = 1;
109             break;
110         case SQLITE_INDEX_CONSTRAINT_GT:
111         case SQLITE_INDEX_CONSTRAINT_GE:
112         case SQLITE_INDEX_CONSTRAINT_LE:
113         case SQLITE_INDEX_CONSTRAINT_LT:
114             // assume filter out a half of rows
115             rowCount = (rowCount >> 1);
116             break;
117         default:
118             return false;
119     }
120     return true;
121 }
122 
CreateCursor()123 std::unique_ptr<TableBase::Cursor> EbpfElfSymbolTable::CreateCursor()
124 {
125     return std::make_unique<Cursor>(dataCache_, this);
126 }
127 
Cursor(const TraceDataCache * dataCache,TableBase * table)128 EbpfElfSymbolTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
129     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstEbpfElfSymbol().Size())),
130       ebpfElfSymbolObj_(dataCache->GetConstEbpfElfSymbol())
131 {
132 }
133 
~Cursor()134 EbpfElfSymbolTable::Cursor::~Cursor() {}
135 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)136 int EbpfElfSymbolTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
137 {
138     // reset indexMap_
139     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
140 
141     if (rowCount_ <= 0) {
142         return SQLITE_OK;
143     }
144 
145     auto& cs = fc.GetConstraints();
146     for (size_t i = 0; i < cs.size(); i++) {
147         const auto& c = cs[i];
148         switch (c.col) {
149             case ID:
150                 FilterId(c.op, argv[i]);
151                 break;
152             default:
153                 break;
154         }
155     }
156 
157     auto orderbys = fc.GetOrderBys();
158     for (auto i = orderbys.size(); i > 0;) {
159         i--;
160         switch (orderbys[i].iColumn) {
161             case ID:
162                 indexMap_->SortBy(orderbys[i].desc);
163                 break;
164             default:
165                 break;
166         }
167     }
168 
169     return SQLITE_OK;
170 }
171 
Column(int column) const172 int EbpfElfSymbolTable::Cursor::Column(int column) const
173 {
174     switch (column) {
175         case ID:
176             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfSymbolObj_.IdsData()[CurrentRow()]));
177             break;
178         case ELF_ID:
179             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfSymbolObj_.ElfIds()[CurrentRow()]));
180             break;
181         case ST_NAME:
182             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfSymbolObj_.StNames()[CurrentRow()]));
183             break;
184         case ST_VALUE:
185             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfSymbolObj_.StValues()[CurrentRow()]));
186             break;
187         case ST_SIZE:
188             sqlite3_result_int64(context_, static_cast<int64_t>(ebpfElfSymbolObj_.StSizes()[CurrentRow()]));
189             break;
190         default:
191             TS_LOGF("Unregistered column : %d", column);
192             break;
193     }
194     return SQLITE_OK;
195 }
196 
FilterId(unsigned char op,sqlite3_value * argv)197 void EbpfElfSymbolTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv)
198 {
199     auto type = sqlite3_value_type(argv);
200     if (type != SQLITE_INTEGER) {
201         // other type consider it NULL
202         indexMap_->Intersect(0, 0);
203         return;
204     }
205 
206     auto v = static_cast<TableRowId>(sqlite3_value_int64(argv));
207     switch (op) {
208         case SQLITE_INDEX_CONSTRAINT_EQ:
209             indexMap_->Intersect(v, v + 1);
210             break;
211         case SQLITE_INDEX_CONSTRAINT_GE:
212             indexMap_->Intersect(v, rowCount_);
213             break;
214         case SQLITE_INDEX_CONSTRAINT_GT:
215             v++;
216             indexMap_->Intersect(v, rowCount_);
217             break;
218         case SQLITE_INDEX_CONSTRAINT_LE:
219             v++;
220             indexMap_->Intersect(0, v);
221             break;
222         case SQLITE_INDEX_CONSTRAINT_LT:
223             indexMap_->Intersect(0, v);
224             break;
225         default:
226             // can't filter, all rows
227             break;
228     }
229 }
230 } // namespace TraceStreamer
231 } // namespace SysTuning
232