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 "process_measure_filter_table.h"
17
18 #include <cmath>
19
20 namespace SysTuning {
21 namespace TraceStreamer {
22 enum class Index : int32_t { ID = 0, NAME, INTERNAL_PID };
ProcessMeasureFilterTable(const TraceDataCache * dataCache)23 ProcessMeasureFilterTable::ProcessMeasureFilterTable(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("ipid", "INTEGER"));
28 tablePriKey_.push_back("id");
29 }
30
~ProcessMeasureFilterTable()31 ProcessMeasureFilterTable::~ProcessMeasureFilterTable() {}
32
FilterByConstraint(FilterConstraints & filterfc,double & filterfilterCost,size_t filterrowCount,uint32_t filtercurrenti)33 void ProcessMeasureFilterTable::FilterByConstraint(FilterConstraints &filterfc,
34 double &filterfilterCost,
35 size_t filterrowCount,
36 uint32_t filtercurrenti)
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 &filterc = filterfc.GetConstraints()[filtercurrenti];
41 switch (static_cast<Index>(filterc.col)) {
42 case Index::ID: {
43 auto filteroldRowCount = filterrowCount;
44 if (CanFilterSorted(filterc.op, filterrowCount)) {
45 filterfc.UpdateConstraint(filtercurrenti, true);
46 filterfilterCost += log2(filteroldRowCount); // binary search
47 } else {
48 filterfilterCost += filteroldRowCount;
49 }
50 break;
51 }
52 default: // other column
53 filterfilterCost += filterrowCount; // scan all rows
54 break;
55 }
56 }
57
CreateCursor()58 std::unique_ptr<TableBase::Cursor> ProcessMeasureFilterTable::CreateCursor()
59 {
60 return std::make_unique<Cursor>(dataCache_, this);
61 }
62
Cursor(const TraceDataCache * dataCache,TableBase * table)63 ProcessMeasureFilterTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
64 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstProcessMeasureFilterData().Size()))
65 {
66 }
67
~Cursor()68 ProcessMeasureFilterTable::Cursor::~Cursor() {}
69
Filter(const FilterConstraints & fc,sqlite3_value ** argv)70 int32_t ProcessMeasureFilterTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
71 {
72 // reset indexMap_
73 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
74
75 if (rowCount_ <= 0) {
76 return SQLITE_OK;
77 }
78
79 auto &procMeasureFilterCs = fc.GetConstraints();
80 for (size_t i = 0; i < procMeasureFilterCs.size(); i++) {
81 const auto &c = procMeasureFilterCs[i];
82 switch (static_cast<Index>(c.col)) {
83 case Index::ID:
84 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[i])),
85 dataCache_->GetConstProcessMeasureFilterData().IdsData());
86 break;
87 case Index::INTERNAL_PID:
88 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
89 dataCache_->GetConstProcessMeasureFilterData().UpidsData());
90 break;
91 case Index::NAME:
92 indexMap_->MixRange(c.op,
93 dataCache_->GetConstDataIndex(
94 std::string(reinterpret_cast<const char *>(sqlite3_value_text(argv[i])))),
95 dataCache_->GetConstProcessMeasureFilterData().NamesData());
96 break;
97 default:
98 break;
99 }
100 }
101
102 auto procMeasureFilterOrderbys = fc.GetOrderBys();
103 for (auto i = procMeasureFilterOrderbys.size(); i > 0;) {
104 i--;
105 switch (static_cast<Index>(procMeasureFilterOrderbys[i].iColumn)) {
106 case Index::ID:
107 indexMap_->SortBy(procMeasureFilterOrderbys[i].desc);
108 break;
109 default:
110 break;
111 }
112 }
113
114 return SQLITE_OK;
115 }
116
Column(int32_t col) const117 int32_t ProcessMeasureFilterTable::Cursor::Column(int32_t col) const
118 {
119 switch (static_cast<Index>(col)) {
120 case Index::ID:
121 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(
122 dataCache_->GetConstProcessMeasureFilterData().IdsData()[CurrentRow()]));
123 break;
124 case Index::NAME: {
125 size_t strId =
126 static_cast<size_t>(dataCache_->GetConstProcessMeasureFilterData().NamesData()[CurrentRow()]);
127 sqlite3_result_text(context_, dataCache_->GetDataFromDict(strId).c_str(), STR_DEFAULT_LEN, nullptr);
128 break;
129 }
130 case Index::INTERNAL_PID:
131 sqlite3_result_int64(
132 context_,
133 static_cast<sqlite3_int64>(dataCache_->GetConstProcessMeasureFilterData().UpidsData()[CurrentRow()]));
134 break;
135 default:
136 TS_LOGF("Unregistered column : %d", col);
137 break;
138 }
139 return SQLITE_OK;
140 }
GetOrbyes(FilterConstraints & filterfc,EstimatedIndexInfo & filterei)141 void ProcessMeasureFilterTable::GetOrbyes(FilterConstraints &filterfc, EstimatedIndexInfo &filterei)
142 {
143 auto procMeasurefilterOrdbys = filterfc.GetOrderBys();
144 for (auto i = 0; i < procMeasurefilterOrdbys.size(); i++) {
145 switch (static_cast<Index>(procMeasurefilterOrdbys[i].iColumn)) {
146 case Index::ID:
147 break;
148 default: // other columns can be sorted by SQLite
149 filterei.isOrdered = false;
150 break;
151 }
152 }
153 }
154 } // namespace TraceStreamer
155 } // namespace SysTuning
156