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 "perf_sample_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t {
21 ID = 0,
22 CALLCHAIN_ID,
23 TIMESTAMP,
24 THREAD_ID,
25 EVENT_COUNT,
26 EVENT_TYPE_ID,
27 TIMESTAMP_TRACE,
28 CPU_ID,
29 THREAD_STATE
30 };
PerfSampleTable(const TraceDataCache * dataCache)31 PerfSampleTable::PerfSampleTable(const TraceDataCache* dataCache) : TableBase(dataCache)
32 {
33 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
34 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
35 tableColumn_.push_back(TableBase::ColumnInfo("timeStamp", "INTEGER"));
36 tableColumn_.push_back(TableBase::ColumnInfo("thread_id", "INTEGER"));
37 tableColumn_.push_back(TableBase::ColumnInfo("event_count", "INTEGER"));
38 tableColumn_.push_back(TableBase::ColumnInfo("event_type_id", "INTEGER"));
39 tableColumn_.push_back(TableBase::ColumnInfo("timestamp_trace", "INTEGER"));
40 tableColumn_.push_back(TableBase::ColumnInfo("cpu_id", "INTEGER"));
41 tableColumn_.push_back(TableBase::ColumnInfo("thread_state", "TEXT"));
42 tablePriKey_.push_back("id");
43 }
44
~PerfSampleTable()45 PerfSampleTable::~PerfSampleTable() {}
46
FilterByConstraint(FilterConstraints & samplefc,double & samplefilterCost,size_t samplerowCount,uint32_t samplecurrenti)47 void PerfSampleTable::FilterByConstraint(FilterConstraints& samplefc,
48 double& samplefilterCost,
49 size_t samplerowCount,
50 uint32_t samplecurrenti)
51 {
52 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
53 // for loop
54 const auto& samplec = samplefc.GetConstraints()[samplecurrenti];
55 switch (static_cast<Index>(samplec.col)) {
56 case Index::ID: {
57 if (CanFilterId(samplec.op, samplerowCount)) {
58 samplefc.UpdateConstraint(samplecurrenti, true);
59 samplefilterCost += 1; // id can position by 1 step
60 } else {
61 samplefilterCost += samplerowCount; // scan all rows
62 }
63 break;
64 }
65 default: // other column
66 samplefilterCost += samplerowCount; // scan all rows
67 break;
68 }
69 }
70
CreateCursor()71 std::unique_ptr<TableBase::Cursor> PerfSampleTable::CreateCursor()
72 {
73 return std::make_unique<Cursor>(dataCache_, this);
74 }
75
Cursor(const TraceDataCache * dataCache,TableBase * table)76 PerfSampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
77 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstPerfSampleData().Size())),
78 perfSampleObj_(dataCache->GetConstPerfSampleData())
79 {
80 }
81
~Cursor()82 PerfSampleTable::Cursor::~Cursor() {}
83
Filter(const FilterConstraints & fc,sqlite3_value ** argv)84 int32_t PerfSampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
85 {
86 // reset indexMap_
87 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
88
89 if (rowCount_ <= 0) {
90 return SQLITE_OK;
91 }
92
93 auto perfSampleCs = fc.GetConstraints();
94 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)};
95 SwapIndexFront(perfSampleCs, sId);
96 for (size_t i = 0; i < perfSampleCs.size(); i++) {
97 const auto& c = perfSampleCs[i];
98 switch (static_cast<Index>(c.col)) {
99 case Index::ID:
100 FilterId(c.op, argv[i]);
101 break;
102 case Index::CALLCHAIN_ID:
103 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[i])),
104 perfSampleObj_.SampleIds());
105 break;
106 case Index::THREAD_ID:
107 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[i])), perfSampleObj_.Tids());
108 break;
109 case Index::EVENT_TYPE_ID:
110 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[i])),
111 perfSampleObj_.EventTypeIds());
112 break;
113 case Index::CPU_ID:
114 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[i])), perfSampleObj_.CpuIds());
115 break;
116 default:
117 break;
118 }
119 }
120 auto perfSampleOrderbys = fc.GetOrderBys();
121 for (auto i = perfSampleOrderbys.size(); i > 0;) {
122 i--;
123 switch (static_cast<Index>(perfSampleOrderbys[i].iColumn)) {
124 case Index::ID:
125 indexMap_->SortBy(perfSampleOrderbys[i].desc);
126 break;
127 default:
128 break;
129 }
130 }
131
132 return SQLITE_OK;
133 }
134
Column(int32_t column) const135 int32_t PerfSampleTable::Cursor::Column(int32_t column) const
136 {
137 switch (static_cast<Index>(column)) {
138 case Index::ID:
139 sqlite3_result_int64(context_, static_cast<int32_t>(perfSampleObj_.IdsData()[CurrentRow()]));
140 break;
141 case Index::CALLCHAIN_ID:
142 if (perfSampleObj_.SampleIds()[CurrentRow()] != INVALID_UINT32) {
143 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.SampleIds()[CurrentRow()]));
144 } else {
145 sqlite3_result_int64(context_, static_cast<int64_t>(INVALID_CALL_CHAIN_ID));
146 }
147 break;
148 case Index::TIMESTAMP:
149 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.TimeStampData()[CurrentRow()]));
150 break;
151 case Index::THREAD_ID:
152 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.Tids()[CurrentRow()]));
153 break;
154 case Index::EVENT_COUNT:
155 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.EventCounts()[CurrentRow()]));
156 break;
157 case Index::EVENT_TYPE_ID:
158 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.EventTypeIds()[CurrentRow()]));
159 break;
160 case Index::TIMESTAMP_TRACE:
161 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.TimestampTraces()[CurrentRow()]));
162 break;
163 case Index::CPU_ID:
164 sqlite3_result_int64(context_, static_cast<int64_t>(perfSampleObj_.CpuIds()[CurrentRow()]));
165 break;
166 case Index::THREAD_STATE:
167 if (perfSampleObj_.ThreadStates()[CurrentRow()] != INVALID_UINT64) {
168 auto threadStateIndex = static_cast<size_t>(perfSampleObj_.ThreadStates()[CurrentRow()]);
169 sqlite3_result_text(context_, dataCache_->GetDataFromDict(threadStateIndex).c_str(), STR_DEFAULT_LEN,
170 nullptr);
171 }
172 break;
173 default:
174 TS_LOGF("Unregistered column : %d", column);
175 break;
176 }
177 return SQLITE_OK;
178 }
179
GetOrbyes(FilterConstraints & samplefc,EstimatedIndexInfo & sampleei)180 void PerfSampleTable::GetOrbyes(FilterConstraints& samplefc, EstimatedIndexInfo& sampleei)
181 {
182 auto sampleorderbys = samplefc.GetOrderBys();
183 for (auto i = 0; i < sampleorderbys.size(); i++) {
184 switch (static_cast<Index>(sampleorderbys[i].iColumn)) {
185 case Index::ID:
186 break;
187 default: // other columns can be sorted by SQLite
188 sampleei.isOrdered = false;
189 break;
190 }
191 }
192 }
193 } // namespace TraceStreamer
194 } // namespace SysTuning
195