• 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 "thread_state_table.h"
17 #include "thread_state_flag.h"
18 
19 #include <cmath>
20 
21 namespace SysTuning {
22 namespace TraceStreamer {
23 enum class Index : int32_t { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, TID, PID, STATE, ARGSETID };
ThreadStateTable(const TraceDataCache * dataCache)24 ThreadStateTable::ThreadStateTable(const TraceDataCache* dataCache) : TableBase(dataCache)
25 {
26     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
27     tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT"));
28     tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
29     tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
30     tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
31     tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
32     tableColumn_.push_back(TableBase::ColumnInfo("tid", "INTEGER"));
33     tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER"));
34     tableColumn_.push_back(TableBase::ColumnInfo("state", "TEXT"));
35     tableColumn_.push_back(TableBase::ColumnInfo("arg_setid", "INTEGER"));
36     tablePriKey_.push_back("id");
37 }
38 
~ThreadStateTable()39 ThreadStateTable::~ThreadStateTable() {}
40 
FilterByConstraint(FilterConstraints & statefc,double & statefilterCost,size_t staterowCount,uint32_t statecurrenti)41 void ThreadStateTable::FilterByConstraint(FilterConstraints& statefc,
42                                           double& statefilterCost,
43                                           size_t staterowCount,
44                                           uint32_t statecurrenti)
45 {
46     // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
47     // for loop
48     const auto& statec = statefc.GetConstraints()[statecurrenti];
49     switch (static_cast<Index>(statec.col)) {
50         case Index::ID: {
51             if (CanFilterId(statec.op, staterowCount)) {
52                 statefc.UpdateConstraint(statecurrenti, true);
53                 statefilterCost += 1; // id can position by 1 step
54             } else {
55                 statefilterCost += staterowCount; // scan all rows
56             }
57             break;
58         }
59         case Index::TS: {
60             auto stateoldRowCount = staterowCount;
61             if (CanFilterSorted(statec.op, staterowCount)) {
62                 statefc.UpdateConstraint(statecurrenti, true);
63                 statefilterCost += log2(stateoldRowCount); // binary search
64             } else {
65                 statefilterCost += stateoldRowCount;
66             }
67             break;
68         }
69         default:                              // other column
70             statefilterCost += staterowCount; // scan all rows
71             break;
72     }
73 }
74 
CanFilterSorted(const char op,size_t & threadRowCnt) const75 bool ThreadStateTable::CanFilterSorted(const char op, size_t& threadRowCnt) const
76 {
77     switch (op) {
78         case SQLITE_INDEX_CONSTRAINT_EQ:
79             threadRowCnt = threadRowCnt / log2(threadRowCnt);
80             break;
81         case SQLITE_INDEX_CONSTRAINT_GT:
82         case SQLITE_INDEX_CONSTRAINT_GE:
83         case SQLITE_INDEX_CONSTRAINT_LE:
84         case SQLITE_INDEX_CONSTRAINT_LT:
85             threadRowCnt = (threadRowCnt >> 1);
86             break;
87         default:
88             return false;
89     }
90     return true;
91 }
92 
CreateCursor()93 std::unique_ptr<TableBase::Cursor> ThreadStateTable::CreateCursor()
94 {
95     return std::make_unique<Cursor>(dataCache_, this);
96 }
97 
Cursor(const TraceDataCache * dataCache,TableBase * table)98 ThreadStateTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
99     : TableBase::Cursor(dataCache, table, dataCache->GetConstThreadStateData().Size()),
100       threadStateObj_(dataCache->GetConstThreadStateData())
101 {
102 }
103 
~Cursor()104 ThreadStateTable::Cursor::~Cursor() {}
105 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)106 int32_t ThreadStateTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
107 {
108     // reset
109     if (rowCount_ <= 0) {
110         return SQLITE_OK;
111     }
112     IndexMap* indexMapBack = indexMap_.get();
113     if (indexMap_->HasData()) {
114         indexMapBack = std::make_unique<IndexMap>(0, rowCount_).get();
115     }
116     HandleIndex(fc, argv, indexMapBack);
117     if (indexMap_->HasData()) {
118         indexMap_->Merge(indexMapBack);
119     }
120 
121     auto ThreadStateOrderbys = fc.GetOrderBys();
122     for (auto i = ThreadStateOrderbys.size(); i > 0;) {
123         i--;
124         switch (static_cast<Index>(ThreadStateOrderbys[i].iColumn)) {
125             case Index::ID:
126             case Index::TS:
127                 indexMap_->SortBy(ThreadStateOrderbys[i].desc);
128                 break;
129             default:
130                 break;
131         }
132     }
133 
134     return SQLITE_OK;
135 }
136 
HandleIndex(const FilterConstraints & fc,sqlite3_value ** argv,IndexMap * indexMapBack)137 void ThreadStateTable::Cursor::HandleIndex(const FilterConstraints& fc, sqlite3_value** argv, IndexMap* indexMapBack)
138 {
139     auto cs = fc.GetConstraints();
140     std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
141     SwapIndexFront(cs, sId);
142     for (size_t i = 0; i < cs.size(); i++) {
143         const auto& c = cs[i];
144         switch (static_cast<Index>(c.col)) {
145             case Index::ID:
146                 indexMapBack->FilterId(c.op, argv[i]);
147                 break;
148             case Index::TS:
149                 indexMapBack->FilterTS(c.op, argv[i], threadStateObj_.TimeStamsData());
150                 break;
151             case Index::INTERNAL_TID:
152                 indexMapBack->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
153                                        threadStateObj_.ItidsData());
154                 break;
155             case Index::TID:
156                 indexMapBack->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
157                                        threadStateObj_.TidsData());
158                 break;
159             case Index::PID:
160                 indexMapBack->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
161                                        threadStateObj_.PidsData());
162                 break;
163             case Index::DUR:
164                 indexMapBack->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[i])),
165                                        threadStateObj_.DursData());
166                 break;
167             case Index::CPU:
168                 indexMapBack->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
169                                        threadStateObj_.CpusData());
170                 break;
171             case Index::STATE:
172                 indexMapBack->MixRange(c.op,
173                                        static_cast<DataIndex>(dataCache_->GetThreadStateValue(
174                                            std::string(reinterpret_cast<const char*>(sqlite3_value_text(argv[i]))))),
175                                        threadStateObj_.StatesData());
176                 break;
177             case Index::ARGSETID:
178                 indexMapBack->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])),
179                                        threadStateObj_.ArgSetsData());
180                 break;
181             default:
182                 break;
183         }
184     }
185 }
186 
Column(int32_t col) const187 int32_t ThreadStateTable::Cursor::Column(int32_t col) const
188 {
189     switch (static_cast<Index>(col)) {
190         case Index::ID:
191             sqlite3_result_int64(context_, static_cast<sqlite3_int64>(CurrentRow()));
192             break;
193         case Index::TYPE:
194             sqlite3_result_text(context_, "thread_state", STR_DEFAULT_LEN, nullptr);
195             break;
196         case Index::TS:
197             sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.TimeStamsData()[CurrentRow()]));
198             break;
199         case Index::DUR:
200             SetTypeColumnInt64(threadStateObj_.DursData()[CurrentRow()], INVALID_UINT64);
201             break;
202         case Index::CPU:
203             if (threadStateObj_.CpusData()[CurrentRow()] != INVALID_CPU) {
204                 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.CpusData()[CurrentRow()]));
205             }
206             break;
207         case Index::INTERNAL_TID:
208             sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.ItidsData()[CurrentRow()]));
209             break;
210         case Index::TID:
211             sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.TidsData()[CurrentRow()]));
212             break;
213         case Index::PID:
214             sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.PidsData()[CurrentRow()]));
215             break;
216         case Index::STATE: {
217             const std::string& str = dataCache_->GetConstSchedStateData(threadStateObj_.StatesData()[CurrentRow()]);
218             sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
219             break;
220         }
221         case Index::ARGSETID:
222             if (threadStateObj_.ArgSetsData()[CurrentRow()] != INVALID_UINT32) {
223                 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(threadStateObj_.ArgSetsData()[CurrentRow()]));
224             }
225             break;
226         default:
227             TS_LOGF("Unregistered column : %d", col);
228             break;
229     }
230     return SQLITE_OK;
231 }
232 
GetOrbyes(FilterConstraints & statefc,EstimatedIndexInfo & stateei)233 void ThreadStateTable::GetOrbyes(FilterConstraints& statefc, EstimatedIndexInfo& stateei)
234 {
235     auto stateorderbys = statefc.GetOrderBys();
236     for (auto i = 0; i < stateorderbys.size(); i++) {
237         switch (static_cast<Index>(stateorderbys[i].iColumn)) {
238             case Index::ID:
239             case Index::TS:
240                 break;
241             default: // other columns can be sorted by SQLite
242                 stateei.isOrdered = false;
243                 break;
244         }
245     }
246 }
247 } // namespace TraceStreamer
248 } // namespace SysTuning
249