• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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