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 "instants_table.h"
17 #include <cmath>
18
19 namespace SysTuning {
20 namespace TraceStreamer {
21 enum class Index : int32_t { TS = 0, NAME, REF, WAKEUP_FROM, REF_TYPE, VALUE };
InstantsTable(const TraceDataCache *dataCache)22 InstantsTable::InstantsTable(const TraceDataCache *dataCache) : TableBase(dataCache)
23 {
24 tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
25 tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
26 tableColumn_.push_back(TableBase::ColumnInfo("ref", "INTEGER"));
27 tableColumn_.push_back(TableBase::ColumnInfo("wakeup_from", "INTEGER"));
28 tableColumn_.push_back(TableBase::ColumnInfo("ref_type", "TEXT"));
29 tableColumn_.push_back(TableBase::ColumnInfo("value", "REAL"));
30 tablePriKey_.push_back("ts");
31 tablePriKey_.push_back("ref");
32 }
33
~InstantsTable()34 InstantsTable::~InstantsTable() {}
35
CreateCursor()36 std::unique_ptr<TableBase::Cursor> InstantsTable::CreateCursor()
37 {
38 return std::make_unique<Cursor>(dataCache_, this);
39 }
40
Cursor(const TraceDataCache *dataCache, TableBase *table)41 InstantsTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
42 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstInstantsData().Size())),
43 InstantsObj_(dataCache->GetConstInstantsData())
44 {
45 }
46
~Cursor()47 InstantsTable::Cursor::~Cursor() {}
48
FilterByConstraint(FilterConstraints &instantsfc, double &instantsfilterCost, size_t instantsrowCount, uint32_t instantscurrenti)49 void InstantsTable::FilterByConstraint(FilterConstraints &instantsfc,
50 double &instantsfilterCost,
51 size_t instantsrowCount,
52 uint32_t instantscurrenti)
53 {
54 const auto &instantsc = instantsfc.GetConstraints()[instantscurrenti];
55 switch (static_cast<Index>(instantsc.col)) {
56 case Index::TS: {
57 auto instantsoldRowCount = instantsrowCount;
58 if (CanFilterSorted(instantsc.op, instantsrowCount)) {
59 instantsfc.UpdateConstraint(instantscurrenti, true);
60 instantsfilterCost += log2(instantsoldRowCount); // binary search
61 } else {
62 instantsfilterCost += instantsoldRowCount;
63 }
64 break;
65 }
66 default: // other column
67 instantsfilterCost += instantsrowCount; // scan all rows
68 break;
69 }
70 }
71
SortOfIndexMap(const FilterConstraints &fc)72 void InstantsTable::Cursor::SortOfIndexMap(const FilterConstraints &fc)
73 {
74 auto orderbys = fc.GetOrderBys();
75 for (auto i = orderbys.size(); i > 0;) {
76 i--;
77 switch (static_cast<Index>(orderbys[i].iColumn)) {
78 case Index::TS:
79 indexMap_->SortBy(orderbys[i].desc);
80 break;
81 default:
82 break;
83 }
84 }
85 }
86
Filter(const FilterConstraints &fc, sqlite3_value **argv)87 int32_t InstantsTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
88 {
89 // reset
90 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
91 if (rowCount_ <= 0) {
92 return SQLITE_OK;
93 }
94 auto instantsTabCs = fc.GetConstraints();
95 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
96 SwapIndexFront(instantsTabCs, sId);
97 for (size_t i = 0; i < instantsTabCs.size(); i++) {
98 const auto &c = instantsTabCs[i];
99 switch (static_cast<Index>(c.col)) {
100 case Index::TS:
101 FilterTS(c.op, argv[c.idxInaConstraint], InstantsObj_.TimeStampData());
102 break;
103 case Index::NAME:
104 indexMap_->MixRange(c.op,
105 dataCache_->GetConstDataIndex(std::string(
106 reinterpret_cast<const char *>(sqlite3_value_text(argv[c.idxInaConstraint])))),
107 InstantsObj_.NameIndexsData());
108 break;
109 case Index::REF:
110 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
111 InstantsObj_.InternalTidsData());
112 break;
113 case Index::WAKEUP_FROM:
114 indexMap_->MixRange(c.op, static_cast<int64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
115 InstantsObj_.WakeupFromPidsData());
116 break;
117 default:
118 break;
119 }
120 }
121 SortOfIndexMap(fc);
122
123 return SQLITE_OK;
124 }
125
Column(int32_t column) const126 int32_t InstantsTable::Cursor::Column(int32_t column) const
127 {
128 size_t stringIdentity = static_cast<size_t>(InstantsObj_.NameIndexsData()[CurrentRow()]);
129 switch (static_cast<Index>(column)) {
130 case Index::TS:
131 sqlite3_result_int64(context_, static_cast<int64_t>(InstantsObj_.TimeStampData()[CurrentRow()]));
132 break;
133 case Index::NAME: {
134 sqlite3_result_text(context_, dataCache_->GetDataFromDict(stringIdentity).c_str(), STR_DEFAULT_LEN,
135 nullptr);
136 break;
137 }
138 case Index::REF:
139 sqlite3_result_int64(context_, static_cast<int32_t>(InstantsObj_.InternalTidsData()[CurrentRow()]));
140 break;
141 case Index::WAKEUP_FROM:
142 sqlite3_result_int64(context_, static_cast<int32_t>(InstantsObj_.WakeupFromPidsData()[CurrentRow()]));
143 break;
144 case Index::REF_TYPE: {
145 sqlite3_result_text(context_, "itid", STR_DEFAULT_LEN, nullptr);
146 break;
147 }
148 case Index::VALUE: {
149 sqlite3_result_double(context_, 0.0);
150 break;
151 }
152 default:
153 TS_LOGF("Unregistered column : %d", column);
154 break;
155 }
156 return SQLITE_OK;
157 }
GetOrbyes(FilterConstraints &instantsfc, EstimatedIndexInfo &instantsei)158 void InstantsTable::GetOrbyes(FilterConstraints &instantsfc, EstimatedIndexInfo &instantsei)
159 {
160 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
161 // for loop
162 auto instantsorderbys = instantsfc.GetOrderBys();
163 for (auto i = 0; i < instantsorderbys.size(); i++) {
164 switch (static_cast<Index>(instantsorderbys[i].iColumn)) {
165 case Index::TS:
166 break;
167 default: // other columns can be sorted by SQLite
168 instantsei.isOrdered = false;
169 break;
170 }
171 }
172 }
173 } // namespace TraceStreamer
174 } // namespace SysTuning
175