1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ci#include "thread_table.h" 17fb726d48Sopenharmony_ci 18fb726d48Sopenharmony_cinamespace SysTuning { 19fb726d48Sopenharmony_cinamespace TraceStreamer { 20fb726d48Sopenharmony_cienum class Index : int32_t { ID = 0, ITID, TID, NAME, START_TS, END_TS, INTERNAL_PID, IS_MAIN_THREAD, SWITCH_COUNT }; 21fb726d48Sopenharmony_ciThreadTable::ThreadTable(const TraceDataCache *dataCache) : TableBase(dataCache) 22fb726d48Sopenharmony_ci{ 23fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); 24fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); 25fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("tid", "INTEGER")); 26fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); 27fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); 28fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); 29fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); 30fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("is_main_thread", "INTEGER")); 31fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("switch_count", "INTEGER")); 32fb726d48Sopenharmony_ci tablePriKey_.push_back("id"); 33fb726d48Sopenharmony_ci} 34fb726d48Sopenharmony_ci 35fb726d48Sopenharmony_ciThreadTable::~ThreadTable() {} 36fb726d48Sopenharmony_ci 37fb726d48Sopenharmony_civoid ThreadTable::FilterByConstraint(FilterConstraints &threadfc, 38fb726d48Sopenharmony_ci double &threadfilterCost, 39fb726d48Sopenharmony_ci size_t threadrowCount, 40fb726d48Sopenharmony_ci uint32_t threadcurrenti) 41fb726d48Sopenharmony_ci{ 42fb726d48Sopenharmony_ci // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each 43fb726d48Sopenharmony_ci // for loop 44fb726d48Sopenharmony_ci const auto &threadc = threadfc.GetConstraints()[threadcurrenti]; 45fb726d48Sopenharmony_ci switch (static_cast<Index>(threadc.col)) { 46fb726d48Sopenharmony_ci case Index::ITID: 47fb726d48Sopenharmony_ci case Index::ID: { 48fb726d48Sopenharmony_ci if (CanFilterId(threadc.op, threadrowCount)) { 49fb726d48Sopenharmony_ci threadfc.UpdateConstraint(threadcurrenti, true); 50fb726d48Sopenharmony_ci threadfilterCost += 1; // id can position by 1 step 51fb726d48Sopenharmony_ci } else { 52fb726d48Sopenharmony_ci threadfilterCost += threadrowCount; // scan all rows 53fb726d48Sopenharmony_ci } 54fb726d48Sopenharmony_ci break; 55fb726d48Sopenharmony_ci } 56fb726d48Sopenharmony_ci default: // other column 57fb726d48Sopenharmony_ci threadfilterCost += threadrowCount; // scan all rows 58fb726d48Sopenharmony_ci break; 59fb726d48Sopenharmony_ci } 60fb726d48Sopenharmony_ci} 61fb726d48Sopenharmony_ci 62fb726d48Sopenharmony_cistd::unique_ptr<TableBase::Cursor> ThreadTable::CreateCursor() 63fb726d48Sopenharmony_ci{ 64fb726d48Sopenharmony_ci return std::make_unique<Cursor>(dataCache_, this); 65fb726d48Sopenharmony_ci} 66fb726d48Sopenharmony_ci 67fb726d48Sopenharmony_ciThreadTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table) 68fb726d48Sopenharmony_ci : TableBase::Cursor(dataCache, table, dataCache->ThreadSize()) 69fb726d48Sopenharmony_ci{ 70fb726d48Sopenharmony_ci} 71fb726d48Sopenharmony_ci 72fb726d48Sopenharmony_ciThreadTable::Cursor::~Cursor() {} 73fb726d48Sopenharmony_ci 74fb726d48Sopenharmony_ciint32_t ThreadTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv) 75fb726d48Sopenharmony_ci{ 76fb726d48Sopenharmony_ci // reset indexMapBack_ 77fb726d48Sopenharmony_ci if (rowCount_ <= 0) { 78fb726d48Sopenharmony_ci return SQLITE_OK; 79fb726d48Sopenharmony_ci } 80fb726d48Sopenharmony_ci indexMapBack_ = indexMap_.get(); 81fb726d48Sopenharmony_ci if (indexMap_->HasData()) { 82fb726d48Sopenharmony_ci indexMapBack_ = std::make_unique<IndexMap>(0, rowCount_).get(); 83fb726d48Sopenharmony_ci } 84fb726d48Sopenharmony_ci auto cs = fc.GetConstraints(); 85fb726d48Sopenharmony_ci std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)}; 86fb726d48Sopenharmony_ci SwapIndexFront(cs, sId); 87fb726d48Sopenharmony_ci for (size_t i = 0; i < cs.size(); i++) { 88fb726d48Sopenharmony_ci const auto &c = cs[i]; 89fb726d48Sopenharmony_ci switch (static_cast<Index>(c.col)) { 90fb726d48Sopenharmony_ci case Index::ID: 91fb726d48Sopenharmony_ci case Index::ITID: 92fb726d48Sopenharmony_ci FilterId(c.op, argv[c.idxInaConstraint]); 93fb726d48Sopenharmony_ci break; 94fb726d48Sopenharmony_ci default: 95fb726d48Sopenharmony_ci break; 96fb726d48Sopenharmony_ci } 97fb726d48Sopenharmony_ci } 98fb726d48Sopenharmony_ci if (indexMap_->HasData()) { 99fb726d48Sopenharmony_ci indexMap_->Merge(indexMapBack_); 100fb726d48Sopenharmony_ci } 101fb726d48Sopenharmony_ci 102fb726d48Sopenharmony_ci auto orderbys = fc.GetOrderBys(); 103fb726d48Sopenharmony_ci for (auto i = orderbys.size(); i > 0;) { 104fb726d48Sopenharmony_ci i--; 105fb726d48Sopenharmony_ci switch (static_cast<Index>(orderbys[i].iColumn)) { 106fb726d48Sopenharmony_ci case Index::ID: 107fb726d48Sopenharmony_ci case Index::ITID: 108fb726d48Sopenharmony_ci indexMap_->SortBy(orderbys[i].desc); 109fb726d48Sopenharmony_ci break; 110fb726d48Sopenharmony_ci default: 111fb726d48Sopenharmony_ci break; 112fb726d48Sopenharmony_ci } 113fb726d48Sopenharmony_ci } 114fb726d48Sopenharmony_ci 115fb726d48Sopenharmony_ci return SQLITE_OK; 116fb726d48Sopenharmony_ci} 117fb726d48Sopenharmony_ci 118fb726d48Sopenharmony_ciint32_t ThreadTable::Cursor::Column(int32_t col) const 119fb726d48Sopenharmony_ci{ 120fb726d48Sopenharmony_ci const auto &thread = dataCache_->GetConstThreadData(CurrentRow()); 121fb726d48Sopenharmony_ci switch (static_cast<Index>(col)) { 122fb726d48Sopenharmony_ci case Index::ID: 123fb726d48Sopenharmony_ci case Index::ITID: { 124fb726d48Sopenharmony_ci sqlite3_result_int64(context_, CurrentRow()); 125fb726d48Sopenharmony_ci break; 126fb726d48Sopenharmony_ci } 127fb726d48Sopenharmony_ci case Index::TID: { 128fb726d48Sopenharmony_ci SetTypeColumnInt64(thread.tid_, INVALID_UINT32); 129fb726d48Sopenharmony_ci break; 130fb726d48Sopenharmony_ci } 131fb726d48Sopenharmony_ci case Index::NAME: { 132fb726d48Sopenharmony_ci SetNameColumn(thread); 133fb726d48Sopenharmony_ci break; 134fb726d48Sopenharmony_ci } 135fb726d48Sopenharmony_ci case Index::START_TS: 136fb726d48Sopenharmony_ci SetTypeColumnInt64NotZero(thread.startT_); 137fb726d48Sopenharmony_ci break; 138fb726d48Sopenharmony_ci case Index::END_TS: 139fb726d48Sopenharmony_ci SetTypeColumnInt64NotZero(thread.endT_); 140fb726d48Sopenharmony_ci 141fb726d48Sopenharmony_ci break; 142fb726d48Sopenharmony_ci case Index::INTERNAL_PID: 143fb726d48Sopenharmony_ci SetTypeColumnInt32(thread.internalPid_, INVALID_UINT32); 144fb726d48Sopenharmony_ci break; 145fb726d48Sopenharmony_ci case Index::IS_MAIN_THREAD: { 146fb726d48Sopenharmony_ci // When it is not clear which process the thread belongs to, is_main_thread should be set to null 147fb726d48Sopenharmony_ci if (thread.internalPid_ == INVALID_UINT32) { 148fb726d48Sopenharmony_ci break; 149fb726d48Sopenharmony_ci } 150fb726d48Sopenharmony_ci const auto &process = dataCache_->GetConstProcessData(thread.internalPid_); 151fb726d48Sopenharmony_ci sqlite3_result_int(context_, thread.tid_ == process.pid_); 152fb726d48Sopenharmony_ci break; 153fb726d48Sopenharmony_ci } 154fb726d48Sopenharmony_ci case Index::SWITCH_COUNT: { 155fb726d48Sopenharmony_ci // When it is not clear which process the thread belongs to, is_main_thread should be set to null 156fb726d48Sopenharmony_ci sqlite3_result_int(context_, thread.switchCount_); 157fb726d48Sopenharmony_ci break; 158fb726d48Sopenharmony_ci } 159fb726d48Sopenharmony_ci default: 160fb726d48Sopenharmony_ci TS_LOGF("Unregistered column : %d", col); 161fb726d48Sopenharmony_ci break; 162fb726d48Sopenharmony_ci } 163fb726d48Sopenharmony_ci return SQLITE_OK; 164fb726d48Sopenharmony_ci} 165fb726d48Sopenharmony_ci 166fb726d48Sopenharmony_civoid ThreadTable::Cursor::SetNameColumn(const Thread &thread) const 167fb726d48Sopenharmony_ci{ 168fb726d48Sopenharmony_ci const auto &name = dataCache_->GetDataFromDict(thread.nameIndex_); 169fb726d48Sopenharmony_ci if (name.size()) { 170fb726d48Sopenharmony_ci sqlite3_result_text(context_, name.c_str(), static_cast<int32_t>(name.length()), nullptr); 171fb726d48Sopenharmony_ci } 172fb726d48Sopenharmony_ci} 173fb726d48Sopenharmony_ci 174fb726d48Sopenharmony_civoid ThreadTable::Cursor::FilterId(unsigned char op, sqlite3_value *argv) 175fb726d48Sopenharmony_ci{ 176fb726d48Sopenharmony_ci auto type = sqlite3_value_type(argv); 177fb726d48Sopenharmony_ci if (type != SQLITE_INTEGER) { 178fb726d48Sopenharmony_ci // other type consider it NULL 179fb726d48Sopenharmony_ci indexMapBack_->Intersect(0, 0); 180fb726d48Sopenharmony_ci return; 181fb726d48Sopenharmony_ci } 182fb726d48Sopenharmony_ci 183fb726d48Sopenharmony_ci auto threadTabArgv = static_cast<TableRowId>(sqlite3_value_int64(argv)); 184fb726d48Sopenharmony_ci switch (op) { 185fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_EQ: 186fb726d48Sopenharmony_ci indexMapBack_->Intersect(threadTabArgv, threadTabArgv + 1); 187fb726d48Sopenharmony_ci break; 188fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_GE: 189fb726d48Sopenharmony_ci indexMapBack_->Intersect(threadTabArgv, rowCount_); 190fb726d48Sopenharmony_ci break; 191fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_GT: 192fb726d48Sopenharmony_ci threadTabArgv++; 193fb726d48Sopenharmony_ci indexMapBack_->Intersect(threadTabArgv, rowCount_); 194fb726d48Sopenharmony_ci break; 195fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_LE: 196fb726d48Sopenharmony_ci threadTabArgv++; 197fb726d48Sopenharmony_ci indexMapBack_->Intersect(0, threadTabArgv); 198fb726d48Sopenharmony_ci break; 199fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_LT: 200fb726d48Sopenharmony_ci indexMapBack_->Intersect(0, threadTabArgv); 201fb726d48Sopenharmony_ci break; 202fb726d48Sopenharmony_ci default: 203fb726d48Sopenharmony_ci // can't filter, all rows 204fb726d48Sopenharmony_ci break; 205fb726d48Sopenharmony_ci } 206fb726d48Sopenharmony_ci} 207fb726d48Sopenharmony_civoid ThreadTable::GetOrbyes(FilterConstraints &fc, EstimatedIndexInfo &ei) 208fb726d48Sopenharmony_ci{ 209fb726d48Sopenharmony_ci auto orderbys = fc.GetOrderBys(); 210fb726d48Sopenharmony_ci for (auto i = 0; i < orderbys.size(); i++) { 211fb726d48Sopenharmony_ci switch (static_cast<Index>(orderbys[i].iColumn)) { 212fb726d48Sopenharmony_ci case Index::ITID: 213fb726d48Sopenharmony_ci case Index::ID: 214fb726d48Sopenharmony_ci break; 215fb726d48Sopenharmony_ci default: // other columns can be sorted by SQLite 216fb726d48Sopenharmony_ci ei.isOrdered = false; 217fb726d48Sopenharmony_ci break; 218fb726d48Sopenharmony_ci } 219fb726d48Sopenharmony_ci } 220fb726d48Sopenharmony_ci} 221fb726d48Sopenharmony_ci} // namespace TraceStreamer 222fb726d48Sopenharmony_ci} // namespace SysTuning 223