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 "cpu_measure_filter_table.h"
17
18 #include <cmath>
19
20 namespace SysTuning {
21 namespace TraceStreamer {
22 enum class Index : int32_t { ID = 0, NAME, CPU };
CpuMeasureFilterTable(const TraceDataCache * dataCache)23 CpuMeasureFilterTable::CpuMeasureFilterTable(const TraceDataCache *dataCache) : TableBase(dataCache)
24 {
25 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
26 tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
27 tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
28 tablePriKey_.push_back("id");
29 }
30
~CpuMeasureFilterTable()31 CpuMeasureFilterTable::~CpuMeasureFilterTable() {}
32
FilterByConstraint(FilterConstraints & cpufc,double & cpufilterCost,size_t cpurowCount,uint32_t cpucurrenti)33 void CpuMeasureFilterTable::FilterByConstraint(FilterConstraints &cpufc,
34 double &cpufilterCost,
35 size_t cpurowCount,
36 uint32_t cpucurrenti)
37 {
38 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
39 // for loop
40 const auto &cpuc = cpufc.GetConstraints()[cpucurrenti];
41 switch (static_cast<Index>(cpuc.col)) {
42 case Index::ID: {
43 auto cpuoldRowCount = cpurowCount;
44 if (CanFilterSorted(cpuc.op, cpurowCount)) {
45 cpufc.UpdateConstraint(cpucurrenti, true);
46 cpufilterCost += log2(cpuoldRowCount); // binary search
47 } else {
48 cpufilterCost += cpuoldRowCount;
49 }
50 break;
51 }
52 default: // other column
53 cpufilterCost += cpurowCount; // scan all rows
54 break;
55 }
56 }
57
CreateCursor()58 std::unique_ptr<TableBase::Cursor> CpuMeasureFilterTable::CreateCursor()
59 {
60 return std::make_unique<Cursor>(dataCache_, this);
61 }
62
Cursor(const TraceDataCache * dataCache,TableBase * table)63 CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
64 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstCpuMeasuresData().Size())),
65 cpuMeasureObj_(dataCache->GetConstCpuMeasuresData())
66 {
67 }
68
~Cursor()69 CpuMeasureFilterTable::Cursor::~Cursor() {}
70
Filter(const FilterConstraints & fc,sqlite3_value ** argv)71 int32_t CpuMeasureFilterTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
72 {
73 // reset indexMap_
74 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
75
76 if (rowCount_ <= 0) {
77 return SQLITE_OK;
78 }
79
80 auto &cpuMeasureFilterCs = fc.GetConstraints();
81 for (size_t i = 0; i < cpuMeasureFilterCs.size(); i++) {
82 const auto &c = cpuMeasureFilterCs[i];
83 switch (static_cast<Index>(c.col)) {
84 case Index::ID:
85 FilterSorted(c.col, c.op, argv[i]);
86 break;
87 case Index::CPU:
88 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])), cpuMeasureObj_.CpuData());
89 break;
90 default:
91 break;
92 }
93 }
94
95 auto cpuMeasureFilterTabOrderbys = fc.GetOrderBys();
96 for (auto i = cpuMeasureFilterTabOrderbys.size(); i > 0;) {
97 i--;
98 switch (static_cast<Index>(cpuMeasureFilterTabOrderbys[i].iColumn)) {
99 case Index::ID:
100 indexMap_->SortBy(cpuMeasureFilterTabOrderbys[i].desc);
101 break;
102 default:
103 break;
104 }
105 }
106
107 return SQLITE_OK;
108 }
109
Column(int32_t column) const110 int32_t CpuMeasureFilterTable::Cursor::Column(int32_t column) const
111 {
112 switch (static_cast<Index>(column)) {
113 case Index::ID:
114 sqlite3_result_int64(context_, static_cast<int64_t>(cpuMeasureObj_.IdsData()[CurrentRow()]));
115 break;
116 case Index::NAME: {
117 const std::string &str =
118 dataCache_->GetDataFromDict(static_cast<size_t>(cpuMeasureObj_.NameData()[CurrentRow()]));
119 sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
120 break;
121 }
122 case Index::CPU:
123 sqlite3_result_int64(context_, static_cast<int32_t>(cpuMeasureObj_.CpuData()[CurrentRow()]));
124 break;
125 default:
126 TS_LOGF("Unregistered column : %d", column);
127 break;
128 }
129 return SQLITE_OK;
130 }
131
FilterSorted(int32_t columns,unsigned char option,sqlite3_value * argv)132 void CpuMeasureFilterTable::Cursor::FilterSorted(int32_t columns, unsigned char option, sqlite3_value *argv)
133 {
134 auto valType = sqlite3_value_type(argv);
135 if (valType != SQLITE_INTEGER) {
136 // other valType consider it NULL, filter out nothing
137 indexMap_->Intersect(0, 0);
138 return;
139 }
140
141 switch (static_cast<Index>(columns)) {
142 case Index::ID: {
143 auto v = static_cast<uint64_t>(sqlite3_value_int64(argv));
144 auto getValue = [](const uint32_t &row) { return row; };
145 switch (option) {
146 case SQLITE_INDEX_CONSTRAINT_EQ:
147 indexMap_->IntersectabcEqual(cpuMeasureObj_.IdsData(), v, getValue);
148 break;
149 case SQLITE_INDEX_CONSTRAINT_GT:
150 v++;
151 case SQLITE_INDEX_CONSTRAINT_GE: {
152 indexMap_->IntersectGreaterEqual(cpuMeasureObj_.IdsData(), v, getValue);
153 break;
154 }
155 case SQLITE_INDEX_CONSTRAINT_LE:
156 v++;
157 case SQLITE_INDEX_CONSTRAINT_LT: {
158 indexMap_->IntersectLessEqual(cpuMeasureObj_.IdsData(), v, getValue);
159 break;
160 }
161 default:
162 break;
163 } // end of switch (option)
164 } // end of case TS
165 default:
166 // can't filter, all rows
167 break;
168 }
169 }
GetOrbyes(FilterConstraints & cpufc,EstimatedIndexInfo & cpuei)170 void CpuMeasureFilterTable::GetOrbyes(FilterConstraints &cpufc, EstimatedIndexInfo &cpuei)
171 {
172 auto cpuorderbys = cpufc.GetOrderBys();
173 for (auto i = 0; i < cpuorderbys.size(); i++) {
174 switch (static_cast<Index>(cpuorderbys[i].iColumn)) {
175 case Index::ID:
176 break;
177 default: // other columns can be sorted by SQLite
178 cpuei.isOrdered = false;
179 break;
180 }
181 }
182 }
183 } // namespace TraceStreamer
184 } // namespace SysTuning
185