• 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 "irq_table.h"
17 
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum Index {
21     ID = 0,
22     TS,
23     DUR,
24     CALL_ID,
25     CAT,
26     NAME,
27     DEPTH,
28     COOKIE_ID,
29     PARENT_ID,
30     ARGSET,
31     CHAIN_ID,
32     SPAN_ID,
33     PARENT_SPAN_ID,
34     FLAG,
35     ARGS
36 };
IrqTable(const TraceDataCache * dataCache)37 IrqTable::IrqTable(const TraceDataCache* dataCache) : TableBase(dataCache)
38 {
39     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
40     tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
41     tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
42     tableColumn_.push_back(TableBase::ColumnInfo("callid", "INTEGER"));
43     tableColumn_.push_back(TableBase::ColumnInfo("cat", "TEXT"));
44     tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
45     tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER"));
46     tableColumn_.push_back(TableBase::ColumnInfo("cookie", "INTEGER"));
47     tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "INTEGER"));
48     tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "INTEGER"));
49     tableColumn_.push_back(TableBase::ColumnInfo("chainId", "TEXT"));
50     tableColumn_.push_back(TableBase::ColumnInfo("spanId", "TEXT"));
51     tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "TEXT"));
52     tableColumn_.push_back(TableBase::ColumnInfo("flag", "TEXT"));
53     tableColumn_.push_back(TableBase::ColumnInfo("args", "TEXT"));
54     tablePriKey_.push_back("callid");
55     tablePriKey_.push_back("ts");
56     tablePriKey_.push_back("depth");
57 }
58 
~IrqTable()59 IrqTable::~IrqTable() {}
60 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)61 void IrqTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
62 {
63     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
64     constexpr double indexCost = 2.0;
65     ei.estimatedCost = filterBaseCost;
66 
67     auto rowCount = dataCache_->GetConstIrqData().Size();
68     if (rowCount == 0 || rowCount == 1) {
69         ei.estimatedRows = rowCount;
70         ei.estimatedCost += indexCost * rowCount;
71         return;
72     }
73 
74     double filterCost = 0.0;
75     auto constraints = fc.GetConstraints();
76     if (constraints.empty()) { // scan all rows
77         filterCost = rowCount;
78     } else {
79         FilterByConstraint(fc, filterCost, rowCount);
80     }
81     ei.estimatedCost += filterCost;
82     ei.estimatedRows = rowCount;
83     ei.estimatedCost += rowCount * indexCost;
84 
85     ei.isOrdered = true;
86     auto orderbys = fc.GetOrderBys();
87     for (auto i = 0; i < orderbys.size(); i++) {
88         switch (orderbys[i].iColumn) {
89             case ID:
90                 break;
91             default: // other columns can be sorted by SQLite
92                 ei.isOrdered = false;
93                 break;
94         }
95     }
96 }
97 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)98 void IrqTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
99 {
100     auto fcConstraints = fc.GetConstraints();
101     for (int32_t i = 0; i < static_cast<int32_t>(fcConstraints.size()); i++) {
102         if (rowCount <= 1) {
103             // only one row or nothing, needn't filter by constraint
104             filterCost += rowCount;
105             break;
106         }
107         const auto& c = fcConstraints[i];
108         switch (c.col) {
109             case ID: {
110                 if (CanFilterId(c.op, rowCount)) {
111                     fc.UpdateConstraint(i, true);
112                     filterCost += 1; // id can position by 1 step
113                 } else {
114                     filterCost += rowCount; // scan all rows
115                 }
116                 break;
117             }
118             default:                    // other column
119                 filterCost += rowCount; // scan all rows
120                 break;
121         }
122     }
123 }
124 
CreateCursor()125 std::unique_ptr<TableBase::Cursor> IrqTable::CreateCursor()
126 {
127     return std::make_unique<Cursor>(dataCache_, this);
128 }
129 
Cursor(const TraceDataCache * dataCache,TableBase * table)130 IrqTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
131     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstIrqData().Size())),
132       slicesObj_(dataCache->GetConstIrqData())
133 {
134 }
135 
~Cursor()136 IrqTable::Cursor::~Cursor() {}
137 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)138 int32_t IrqTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
139 {
140     // reset indexMap_
141     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
142 
143     if (rowCount_ <= 0) {
144         return SQLITE_OK;
145     }
146 
147     auto& cs = fc.GetConstraints();
148     for (size_t i = 0; i < cs.size(); i++) {
149         const auto& c = cs[i];
150         switch (c.col) {
151             case ID:
152                 FilterId(c.op, argv[i]);
153                 break;
154             default:
155                 break;
156         }
157     }
158 
159     auto orderbys = fc.GetOrderBys();
160     for (auto i = orderbys.size(); i > 0;) {
161         i--;
162         switch (orderbys[i].iColumn) {
163             case ID:
164                 indexMap_->SortBy(orderbys[i].desc);
165                 break;
166             default:
167                 break;
168         }
169     }
170 
171     return SQLITE_OK;
172 }
173 
Column(int32_t column) const174 int32_t IrqTable::Cursor::Column(int32_t column) const
175 {
176     switch (column) {
177         case ID:
178             sqlite3_result_int64(context_, CurrentRow());
179             break;
180         case TS:
181             sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.TimeStampData()[CurrentRow()]));
182             break;
183         case DUR:
184             sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.DursData()[CurrentRow()]));
185             break;
186         case CALL_ID:
187             sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.CallIds()[CurrentRow()]));
188             break;
189         case CAT: {
190             if (slicesObj_.CatsData()[CurrentRow()] != INVALID_UINT64) {
191                 auto catsDataIndex = static_cast<size_t>(slicesObj_.CatsData()[CurrentRow()]);
192                 sqlite3_result_text(context_, dataCache_->GetDataFromDict(catsDataIndex).c_str(), STR_DEFAULT_LEN,
193                                     nullptr);
194             }
195             break;
196         }
197         case NAME: {
198             if (slicesObj_.NamesData()[CurrentRow()] != INVALID_UINT64) {
199                 auto nameDataIndex = static_cast<size_t>(slicesObj_.NamesData()[CurrentRow()]);
200                 sqlite3_result_text(context_, dataCache_->GetDataFromDict(nameDataIndex).c_str(), STR_DEFAULT_LEN,
201                                     nullptr);
202             }
203             break;
204         }
205         case DEPTH:
206             sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.Depths()[CurrentRow()]));
207             break;
208         case COOKIE_ID:
209             if (slicesObj_.Cookies()[CurrentRow()] != INVALID_UINT64) {
210                 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.Cookies()[CurrentRow()]));
211             }
212             break;
213         case PARENT_ID: {
214             if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) {
215                 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.ParentIdData()[CurrentRow()].value()));
216             }
217             break;
218         }
219         case ARGSET:
220             if (slicesObj_.ArgSetIdsData()[CurrentRow()] != INVALID_UINT32) {
221                 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.ArgSetIdsData()[CurrentRow()]));
222             }
223             break;
224         case CHAIN_ID:
225             sqlite3_result_text(context_, slicesObj_.ChainIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
226             break;
227         case SPAN_ID:
228             sqlite3_result_text(context_, slicesObj_.SpanIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
229             break;
230         case PARENT_SPAN_ID:
231             sqlite3_result_text(context_, slicesObj_.ParentSpanIds()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
232             break;
233         case FLAG:
234             sqlite3_result_text(context_, slicesObj_.Flags()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
235             break;
236         case ARGS:
237             sqlite3_result_text(context_, slicesObj_.ArgsData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
238             break;
239         default:
240             TS_LOGF("Unregistered column : %d", column);
241             break;
242     }
243     return SQLITE_OK;
244 }
245 } // namespace TraceStreamer
246 } // namespace SysTuning
247