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 "file_system_sample_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 namespace {
21 enum Index {
22 ID = 0,
23 CALLCHAIN_ID,
24 TYPE,
25 IPID,
26 ITID,
27 START_TS,
28 END_TS,
29 DUR,
30 RETURN_VALUE,
31 ERROR_VALUE,
32 FD,
33 FILE_ID,
34 SIZE,
35 FIRST_ARGUMENT,
36 SECOND_ARGUMENT,
37 THIRD_ARGUMENT,
38 FOURTH_ARGUMENT,
39 };
40 }
FileSystemSampleTable(const TraceDataCache * dataCache)41 FileSystemSampleTable::FileSystemSampleTable(const TraceDataCache* dataCache) : TableBase(dataCache)
42 {
43 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
44 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
45 tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER"));
46 tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER"));
47 tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
48 tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER"));
49 tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER"));
50 tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
51 tableColumn_.push_back(TableBase::ColumnInfo("return_value", "TEXT"));
52 tableColumn_.push_back(TableBase::ColumnInfo("error_code", "TEXT"));
53 tableColumn_.push_back(TableBase::ColumnInfo("fd", "INTEGER"));
54 tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER"));
55 tableColumn_.push_back(TableBase::ColumnInfo("size", "INTEGER"));
56 tableColumn_.push_back(TableBase::ColumnInfo("first_argument", "TEXT"));
57 tableColumn_.push_back(TableBase::ColumnInfo("second_argument", "TEXT"));
58 tableColumn_.push_back(TableBase::ColumnInfo("third_argument", "TEXT"));
59 tableColumn_.push_back(TableBase::ColumnInfo("fourth_argument", "TEXT"));
60 tablePriKey_.push_back("id");
61 }
62
~FileSystemSampleTable()63 FileSystemSampleTable::~FileSystemSampleTable() {}
64
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)65 void FileSystemSampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
66 {
67 constexpr double filterBaseCost = 1000.0; // set-up and tear-down
68 constexpr double indexCost = 2.0;
69 ei.estimatedCost = filterBaseCost;
70
71 auto rowCount = dataCache_->GetConstHidumpData().Size();
72 if (rowCount == 0 || rowCount == 1) {
73 ei.estimatedRows = rowCount;
74 ei.estimatedCost += indexCost * rowCount;
75 return;
76 }
77
78 double filterCost = 0.0;
79 auto constraints = fc.GetConstraints();
80 if (constraints.empty()) { // scan all rows
81 filterCost = rowCount;
82 } else {
83 FilterByConstraint(fc, filterCost, rowCount);
84 }
85 ei.estimatedCost += filterCost;
86 ei.estimatedRows = rowCount;
87 ei.estimatedCost += rowCount * indexCost;
88
89 ei.isOrdered = true;
90 auto orderbys = fc.GetOrderBys();
91 for (auto i = 0; i < orderbys.size(); i++) {
92 switch (orderbys[i].iColumn) {
93 case ID:
94 break;
95 default: // other columns can be sorted by SQLite
96 ei.isOrdered = false;
97 break;
98 }
99 }
100 }
101
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)102 void FileSystemSampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
103 {
104 auto fcConstraints = fc.GetConstraints();
105 for (int i = 0; i < static_cast<int>(fcConstraints.size()); i++) {
106 if (rowCount <= 1) {
107 // only one row or nothing, needn't filter by constraint
108 filterCost += rowCount;
109 break;
110 }
111 const auto& c = fcConstraints[i];
112 switch (c.col) {
113 case ID: {
114 if (CanFilterId(c.op, rowCount)) {
115 fc.UpdateConstraint(i, true);
116 filterCost += 1; // id can position by 1 step
117 } else {
118 filterCost += rowCount; // scan all rows
119 }
120 break;
121 }
122 default: // other column
123 filterCost += rowCount; // scan all rows
124 break;
125 }
126 }
127 }
128
CanFilterId(const char op,size_t & rowCount)129 bool FileSystemSampleTable::CanFilterId(const char op, size_t& rowCount)
130 {
131 switch (op) {
132 case SQLITE_INDEX_CONSTRAINT_EQ:
133 rowCount = 1;
134 break;
135 case SQLITE_INDEX_CONSTRAINT_GT:
136 case SQLITE_INDEX_CONSTRAINT_GE:
137 case SQLITE_INDEX_CONSTRAINT_LE:
138 case SQLITE_INDEX_CONSTRAINT_LT:
139 // assume filter out a half of rows
140 rowCount = (rowCount >> 1);
141 break;
142 default:
143 return false;
144 }
145 return true;
146 }
147
CreateCursor()148 std::unique_ptr<TableBase::Cursor> FileSystemSampleTable::CreateCursor()
149 {
150 return std::make_unique<Cursor>(dataCache_, this);
151 }
152
Cursor(const TraceDataCache * dataCache,TableBase * table)153 FileSystemSampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
154 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstFileSystemSample().Size())),
155 fileSystemSampleTableObj_(dataCache->GetConstFileSystemSample())
156 {
157 }
158
~Cursor()159 FileSystemSampleTable::Cursor::~Cursor() {}
160
Filter(const FilterConstraints & fc,sqlite3_value ** argv)161 int FileSystemSampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
162 {
163 // reset indexMap_
164 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
165
166 if (rowCount_ <= 0) {
167 return SQLITE_OK;
168 }
169
170 auto& cs = fc.GetConstraints();
171 for (size_t i = 0; i < cs.size(); i++) {
172 const auto& c = cs[i];
173 switch (c.col) {
174 case ID:
175 FilterId(c.op, argv[i]);
176 break;
177 case TYPE:
178 indexMap_->MixRange(c.op, static_cast<uint16_t>(sqlite3_value_int(argv[i])),
179 fileSystemSampleTableObj_.Types());
180 break;
181 default:
182 break;
183 }
184 }
185
186 auto orderbys = fc.GetOrderBys();
187 for (auto i = orderbys.size(); i > 0;) {
188 i--;
189 switch (orderbys[i].iColumn) {
190 case ID:
191 indexMap_->SortBy(orderbys[i].desc);
192 break;
193 default:
194 break;
195 }
196 }
197 return SQLITE_OK;
198 }
199
Column(int column) const200 int FileSystemSampleTable::Cursor::Column(int column) const
201 {
202 switch (column) {
203 case ID:
204 sqlite3_result_int64(context_, static_cast<int32_t>(fileSystemSampleTableObj_.IdsData()[CurrentRow()]));
205 break;
206 case CALLCHAIN_ID:
207 sqlite3_result_int64(context_,
208 static_cast<int64_t>(fileSystemSampleTableObj_.CallChainIds()[CurrentRow()]));
209 break;
210 case TYPE:
211 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Types()[CurrentRow()]));
212 break;
213 case IPID:
214 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Ipids()[CurrentRow()]));
215 break;
216 case ITID:
217 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Itids()[CurrentRow()]));
218 break;
219 case START_TS:
220 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.StartTs()[CurrentRow()]));
221 break;
222 case END_TS:
223 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.EndTs()[CurrentRow()]));
224 break;
225 case DUR:
226 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Durs()[CurrentRow()]));
227 break;
228 case RETURN_VALUE: {
229 if (fileSystemSampleTableObj_.ReturnValues()[CurrentRow()] != INVALID_UINT64) {
230 auto returnValueIndex = fileSystemSampleTableObj_.ReturnValues()[CurrentRow()];
231 sqlite3_result_text(context_, dataCache_->GetDataFromDict(returnValueIndex).c_str(), STR_DEFAULT_LEN,
232 nullptr);
233 }
234 break;
235 }
236 case ERROR_VALUE: {
237 if (fileSystemSampleTableObj_.ErrorCodes()[CurrentRow()] != INVALID_UINT64) {
238 auto errorValueIndex = fileSystemSampleTableObj_.ErrorCodes()[CurrentRow()];
239 sqlite3_result_text(context_, dataCache_->GetDataFromDict(errorValueIndex).c_str(), STR_DEFAULT_LEN,
240 nullptr);
241 }
242 break;
243 }
244 case FD: {
245 if (fileSystemSampleTableObj_.Fds()[CurrentRow()] != INVALID_INT32) {
246 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Fds()[CurrentRow()]));
247 }
248 break;
249 }
250 case FILE_ID: {
251 if (fileSystemSampleTableObj_.FileIds()[CurrentRow()] != INVALID_UINT64) {
252 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.FileIds()[CurrentRow()]));
253 }
254 break;
255 }
256 case SIZE: {
257 if (fileSystemSampleTableObj_.Sizes()[CurrentRow()] != MAX_SIZE_T) {
258 sqlite3_result_int64(context_, static_cast<int64_t>(fileSystemSampleTableObj_.Sizes()[CurrentRow()]));
259 }
260 break;
261 }
262 case FIRST_ARGUMENT: {
263 if (fileSystemSampleTableObj_.FirstArguments()[CurrentRow()] != INVALID_UINT64) {
264 auto firstArgIndex = fileSystemSampleTableObj_.FirstArguments()[CurrentRow()];
265 sqlite3_result_text(context_, dataCache_->GetDataFromDict(firstArgIndex).c_str(), STR_DEFAULT_LEN,
266 nullptr);
267 }
268 break;
269 }
270 case SECOND_ARGUMENT: {
271 if (fileSystemSampleTableObj_.SecondArguments()[CurrentRow()] != INVALID_UINT64) {
272 auto secondArgIndex = fileSystemSampleTableObj_.SecondArguments()[CurrentRow()];
273 sqlite3_result_text(context_, dataCache_->GetDataFromDict(secondArgIndex).c_str(), STR_DEFAULT_LEN,
274 nullptr);
275 }
276 break;
277 }
278 case THIRD_ARGUMENT: {
279 if (fileSystemSampleTableObj_.ThirdArguments()[CurrentRow()] != INVALID_UINT64) {
280 auto thirdArgIndex = fileSystemSampleTableObj_.ThirdArguments()[CurrentRow()];
281 sqlite3_result_text(context_, dataCache_->GetDataFromDict(thirdArgIndex).c_str(), STR_DEFAULT_LEN,
282 nullptr);
283 }
284 break;
285 }
286 case FOURTH_ARGUMENT: {
287 if (fileSystemSampleTableObj_.FourthArguments()[CurrentRow()] != INVALID_UINT64) {
288 auto fourthArgIndex = fileSystemSampleTableObj_.FourthArguments()[CurrentRow()];
289 sqlite3_result_text(context_, dataCache_->GetDataFromDict(fourthArgIndex).c_str(), STR_DEFAULT_LEN,
290 nullptr);
291 }
292 break;
293 }
294 default:
295 TS_LOGF("Unregistered column : %d", column);
296 break;
297 }
298 return SQLITE_OK;
299 }
300 } // namespace TraceStreamer
301 } // namespace SysTuning
302