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 "irq_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t { ID = 0, TS, DURS, CALL_IDS, CAT, NAME, DEPTH, COOKIE_ID, PARENT_ID, ARGSET, FLAG };
IrqTable(const TraceDataCache *dataCache)21 IrqTable::IrqTable(const TraceDataCache *dataCache) : TableBase(dataCache)
22 {
23 tableColumn_.emplace_back(TableBase::ColumnInfo("id", "INTEGER"));
24 tableColumn_.emplace_back(TableBase::ColumnInfo("ts", "INTEGER"));
25 tableColumn_.emplace_back(TableBase::ColumnInfo("dur", "INTEGER"));
26 tableColumn_.emplace_back(TableBase::ColumnInfo("callid", "INTEGER"));
27 tableColumn_.emplace_back(TableBase::ColumnInfo("cat", "TEXT"));
28 tableColumn_.emplace_back(TableBase::ColumnInfo("name", "TEXT"));
29 tableColumn_.emplace_back(TableBase::ColumnInfo("depth", "INTEGER"));
30 tableColumn_.emplace_back(TableBase::ColumnInfo("cookie", "INTEGER"));
31 tableColumn_.emplace_back(TableBase::ColumnInfo("parent_id", "INTEGER"));
32 tableColumn_.emplace_back(TableBase::ColumnInfo("argsetid", "INTEGER"));
33 tableColumn_.emplace_back(TableBase::ColumnInfo("flag", "TEXT"));
34 tablePriKey_.emplace_back("callid");
35 tablePriKey_.emplace_back("ts");
36 tablePriKey_.emplace_back("depth");
37 }
38
~IrqTable()39 IrqTable::~IrqTable() {}
40
FilterByConstraint(FilterConstraints &irqfc, double &irqfilterCost, size_t irqrowCount, uint32_t irqcurrenti)41 void IrqTable::FilterByConstraint(FilterConstraints &irqfc,
42 double &irqfilterCost,
43 size_t irqrowCount,
44 uint32_t irqcurrenti)
45 {
46 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
47 // for loop
48 const auto &irqc = irqfc.GetConstraints()[irqcurrenti];
49 switch (static_cast<Index>(irqc.col)) {
50 case Index::ID: {
51 if (CanFilterId(irqc.op, irqrowCount)) {
52 irqfc.UpdateConstraint(irqcurrenti, true);
53 irqfilterCost += 1; // id can position by 1 step
54 } else {
55 irqfilterCost += irqrowCount; // scan all rows
56 }
57 break;
58 }
59 default: // other column
60 irqfilterCost += irqrowCount; // scan all rows
61 break;
62 }
63 }
64
CreateCursor()65 std::unique_ptr<TableBase::Cursor> IrqTable::CreateCursor()
66 {
67 return std::make_unique<Cursor>(dataCache_, this);
68 }
69
Cursor(const TraceDataCache *dataCache, TableBase *table)70 IrqTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
71 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstIrqData().Size())),
72 slicesObj_(dataCache->GetConstIrqData())
73 {
74 }
75
~Cursor()76 IrqTable::Cursor::~Cursor() {}
77
Filter(const FilterConstraints &fc, sqlite3_value **argv)78 int32_t IrqTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
79 {
80 // reset indexMap_
81 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
82
83 if (rowCount_ <= 0) {
84 return SQLITE_OK;
85 }
86
87 auto &irqCs = fc.GetConstraints();
88 for (size_t i = 0; i < irqCs.size(); i++) {
89 const auto &c = irqCs[i];
90 switch (static_cast<Index>(c.col)) {
91 case Index::ID:
92 FilterId(c.op, argv[i]);
93 break;
94 default:
95 break;
96 }
97 }
98
99 auto irqTableOrderbys = fc.GetOrderBys();
100 for (auto i = irqTableOrderbys.size(); i > 0;) {
101 i--;
102 switch (static_cast<Index>(irqTableOrderbys[i].iColumn)) {
103 case Index::ID:
104 indexMap_->SortBy(irqTableOrderbys[i].desc);
105 break;
106 default:
107 break;
108 }
109 }
110
111 return SQLITE_OK;
112 }
113
Column(int32_t column) const114 int32_t IrqTable::Cursor::Column(int32_t column) const
115 {
116 switch (static_cast<Index>(column)) {
117 case Index::ID:
118 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.IdsData()[CurrentRow()]));
119 break;
120 case Index::TS:
121 SetTypeColumnInt64(slicesObj_.TimeStampData()[CurrentRow()], INVALID_UINT64);
122 break;
123 case Index::DURS:
124 SetTypeColumnInt64(slicesObj_.DursData()[CurrentRow()], INVALID_UINT64);
125 break;
126 case Index::CALL_IDS:
127 SetTypeColumnInt64(slicesObj_.CallIds()[CurrentRow()], INVALID_UINT64);
128 break;
129 case Index::CAT: {
130 SetTypeColumnText(slicesObj_.CatsData()[CurrentRow()], INVALID_UINT64);
131 break;
132 }
133 case Index::NAME: {
134 SetTypeColumnText(slicesObj_.NamesData()[CurrentRow()], INVALID_UINT64);
135 break;
136 }
137 case Index::DEPTH:
138 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.Depths()[CurrentRow()]));
139 break;
140 default:
141 HandleTypeColumns(column);
142 }
143 return SQLITE_OK;
144 }
HandleTypeColumns(int32_t column) const145 void IrqTable::Cursor::HandleTypeColumns(int32_t column) const
146 {
147 switch (static_cast<Index>(column)) {
148 case Index::COOKIE_ID:
149 SetTypeColumnInt64(slicesObj_.Cookies()[CurrentRow()], INVALID_INT64);
150 break;
151 case Index::PARENT_ID: {
152 if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) {
153 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.ParentIdData()[CurrentRow()].value()));
154 }
155 break;
156 }
157 case Index::ARGSET:
158 SetTypeColumnInt64(slicesObj_.ArgSetIdsData()[CurrentRow()], INVALID_UINT32);
159 break;
160 case Index::FLAG:
161 sqlite3_result_text(context_, slicesObj_.Flags()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr);
162 break;
163 default:
164 TS_LOGF("Unregistered column : %d", column);
165 break;
166 }
167 }
GetOrbyes(FilterConstraints &irqfc, EstimatedIndexInfo &irqei)168 void IrqTable::GetOrbyes(FilterConstraints &irqfc, EstimatedIndexInfo &irqei)
169 {
170 auto irqorderbys = irqfc.GetOrderBys();
171 for (auto i = 0; i < irqorderbys.size(); i++) {
172 switch (static_cast<Index>(irqorderbys[i].iColumn)) {
173 case Index::ID:
174 break;
175 default: // other columns can be sorted by SQLite
176 irqei.isOrdered = false;
177 break;
178 }
179 }
180 }
181 } // namespace TraceStreamer
182 } // namespace SysTuning
183