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 "process_table.h" 17fb726d48Sopenharmony_ci 18fb726d48Sopenharmony_cinamespace SysTuning { 19fb726d48Sopenharmony_cinamespace TraceStreamer { 20fb726d48Sopenharmony_cienum class Index : int32_t { ID = 0, IPID, PID, NAME, START_TS, SWITCH_COUNT, THREAD_COUNT, SLICE_COUNT, MEM_COUNT }; 21fb726d48Sopenharmony_ciProcessTable::ProcessTable(const TraceDataCache *dataCache) : TableBase(dataCache) 22fb726d48Sopenharmony_ci{ 23fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); 24fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); 25fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("pid", "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("switch_count", "INTEGER")); 29fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("thread_count", "INTEGER")); 30fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("slice_count", "INTEGER")); 31fb726d48Sopenharmony_ci tableColumn_.push_back(TableBase::ColumnInfo("mem_count", "INTEGER")); 32fb726d48Sopenharmony_ci tablePriKey_.push_back("id"); 33fb726d48Sopenharmony_ci} 34fb726d48Sopenharmony_ci 35fb726d48Sopenharmony_ciProcessTable::~ProcessTable() {} 36fb726d48Sopenharmony_ci 37fb726d48Sopenharmony_civoid ProcessTable::FilterByConstraint(FilterConstraints &processfc, 38fb726d48Sopenharmony_ci double &processfilterCost, 39fb726d48Sopenharmony_ci size_t processrowCount, 40fb726d48Sopenharmony_ci uint32_t processcurrenti) 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 &processc = processfc.GetConstraints()[processcurrenti]; 45fb726d48Sopenharmony_ci switch (static_cast<Index>(processc.col)) { 46fb726d48Sopenharmony_ci case Index::IPID: 47fb726d48Sopenharmony_ci case Index::ID: { 48fb726d48Sopenharmony_ci if (CanFilterId(processc.op, processrowCount)) { 49fb726d48Sopenharmony_ci processfc.UpdateConstraint(processcurrenti, true); 50fb726d48Sopenharmony_ci processfilterCost += 1; // id can position by 1 step 51fb726d48Sopenharmony_ci } else { 52fb726d48Sopenharmony_ci processfilterCost += processrowCount; // scan all rows 53fb726d48Sopenharmony_ci } 54fb726d48Sopenharmony_ci break; 55fb726d48Sopenharmony_ci } 56fb726d48Sopenharmony_ci default: // other column 57fb726d48Sopenharmony_ci processfilterCost += processrowCount; // scan all rows 58fb726d48Sopenharmony_ci break; 59fb726d48Sopenharmony_ci } 60fb726d48Sopenharmony_ci} 61fb726d48Sopenharmony_ci 62fb726d48Sopenharmony_ciint32_t ProcessTable::Update(int32_t argc, sqlite3_value **argv, sqlite3_int64 *pRowid) 63fb726d48Sopenharmony_ci{ 64fb726d48Sopenharmony_ci if (argc <= 1) { 65fb726d48Sopenharmony_ci return SQLITE_READONLY; 66fb726d48Sopenharmony_ci } 67fb726d48Sopenharmony_ci if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { 68fb726d48Sopenharmony_ci return SQLITE_READONLY; 69fb726d48Sopenharmony_ci } 70fb726d48Sopenharmony_ci auto id = sqlite3_value_int64(argv[0]); 71fb726d48Sopenharmony_ci auto process = wdataCache_->GetProcessData(static_cast<InternalPid>(id)); 72fb726d48Sopenharmony_ci constexpr int32_t colOffset = 2; 73fb726d48Sopenharmony_ci for (auto i = colOffset; i < argc; i++) { 74fb726d48Sopenharmony_ci auto col = i - colOffset; 75fb726d48Sopenharmony_ci if (static_cast<Index>(col) != Index::NAME) { 76fb726d48Sopenharmony_ci continue; 77fb726d48Sopenharmony_ci } 78fb726d48Sopenharmony_ci const char *name = reinterpret_cast<const char *>(sqlite3_value_text(argv[i])); 79fb726d48Sopenharmony_ci if (name == nullptr) { 80fb726d48Sopenharmony_ci process->cmdLine_.clear(); 81fb726d48Sopenharmony_ci } else { 82fb726d48Sopenharmony_ci process->cmdLine_ = name; 83fb726d48Sopenharmony_ci } 84fb726d48Sopenharmony_ci break; 85fb726d48Sopenharmony_ci } 86fb726d48Sopenharmony_ci return SQLITE_OK; 87fb726d48Sopenharmony_ci} 88fb726d48Sopenharmony_ci 89fb726d48Sopenharmony_cistd::unique_ptr<TableBase::Cursor> ProcessTable::CreateCursor() 90fb726d48Sopenharmony_ci{ 91fb726d48Sopenharmony_ci return std::make_unique<Cursor>(dataCache_, this); 92fb726d48Sopenharmony_ci} 93fb726d48Sopenharmony_ci 94fb726d48Sopenharmony_ciProcessTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table) 95fb726d48Sopenharmony_ci : TableBase::Cursor(dataCache, table, dataCache->ProcessSize()) 96fb726d48Sopenharmony_ci{ 97fb726d48Sopenharmony_ci} 98fb726d48Sopenharmony_ci 99fb726d48Sopenharmony_ciProcessTable::Cursor::~Cursor() {} 100fb726d48Sopenharmony_ci 101fb726d48Sopenharmony_ciint32_t ProcessTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv) 102fb726d48Sopenharmony_ci{ 103fb726d48Sopenharmony_ci // reset indexMap_ 104fb726d48Sopenharmony_ci indexMap_ = std::make_unique<IndexMap>(0, rowCount_); 105fb726d48Sopenharmony_ci 106fb726d48Sopenharmony_ci if (rowCount_ <= 0) { 107fb726d48Sopenharmony_ci return SQLITE_OK; 108fb726d48Sopenharmony_ci } 109fb726d48Sopenharmony_ci 110fb726d48Sopenharmony_ci auto processTableCs = fc.GetConstraints(); 111fb726d48Sopenharmony_ci std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)}; 112fb726d48Sopenharmony_ci SwapIndexFront(processTableCs, sId); 113fb726d48Sopenharmony_ci for (size_t i = 0; i < processTableCs.size(); i++) { 114fb726d48Sopenharmony_ci const auto &c = processTableCs[i]; 115fb726d48Sopenharmony_ci switch (static_cast<Index>(c.col)) { 116fb726d48Sopenharmony_ci case Index::ID: 117fb726d48Sopenharmony_ci case Index::IPID: 118fb726d48Sopenharmony_ci FilterId(c.op, argv[c.idxInaConstraint]); 119fb726d48Sopenharmony_ci break; 120fb726d48Sopenharmony_ci case Index::PID: 121fb726d48Sopenharmony_ci FilterIndex(c.col, c.op, argv[c.idxInaConstraint]); 122fb726d48Sopenharmony_ci break; 123fb726d48Sopenharmony_ci default: 124fb726d48Sopenharmony_ci break; 125fb726d48Sopenharmony_ci } 126fb726d48Sopenharmony_ci } 127fb726d48Sopenharmony_ci 128fb726d48Sopenharmony_ci auto processTableOrderbys = fc.GetOrderBys(); 129fb726d48Sopenharmony_ci for (auto i = processTableOrderbys.size(); i > 0;) { 130fb726d48Sopenharmony_ci i--; 131fb726d48Sopenharmony_ci switch (static_cast<Index>(processTableOrderbys[i].iColumn)) { 132fb726d48Sopenharmony_ci case Index::ID: 133fb726d48Sopenharmony_ci case Index::IPID: 134fb726d48Sopenharmony_ci indexMap_->SortBy(processTableOrderbys[i].desc); 135fb726d48Sopenharmony_ci break; 136fb726d48Sopenharmony_ci default: 137fb726d48Sopenharmony_ci break; 138fb726d48Sopenharmony_ci } 139fb726d48Sopenharmony_ci } 140fb726d48Sopenharmony_ci 141fb726d48Sopenharmony_ci return SQLITE_OK; 142fb726d48Sopenharmony_ci} 143fb726d48Sopenharmony_ci 144fb726d48Sopenharmony_ciint32_t ProcessTable::Cursor::Column(int32_t col) const 145fb726d48Sopenharmony_ci{ 146fb726d48Sopenharmony_ci const auto &process = dataCache_->GetConstProcessData(CurrentRow()); 147fb726d48Sopenharmony_ci switch (static_cast<Index>(col)) { 148fb726d48Sopenharmony_ci case Index::ID: 149fb726d48Sopenharmony_ci case Index::IPID: 150fb726d48Sopenharmony_ci sqlite3_result_int64(context_, CurrentRow()); 151fb726d48Sopenharmony_ci break; 152fb726d48Sopenharmony_ci case Index::PID: 153fb726d48Sopenharmony_ci sqlite3_result_int64(context_, process.pid_); 154fb726d48Sopenharmony_ci break; 155fb726d48Sopenharmony_ci case Index::NAME: 156fb726d48Sopenharmony_ci if (process.cmdLine_.size()) { 157fb726d48Sopenharmony_ci sqlite3_result_text(context_, process.cmdLine_.c_str(), static_cast<int32_t>(process.cmdLine_.length()), 158fb726d48Sopenharmony_ci nullptr); 159fb726d48Sopenharmony_ci } 160fb726d48Sopenharmony_ci break; 161fb726d48Sopenharmony_ci case Index::START_TS: 162fb726d48Sopenharmony_ci if (process.startT_) { 163fb726d48Sopenharmony_ci sqlite3_result_int64(context_, static_cast<int64_t>(process.startT_)); 164fb726d48Sopenharmony_ci } 165fb726d48Sopenharmony_ci break; 166fb726d48Sopenharmony_ci case Index::SWITCH_COUNT: 167fb726d48Sopenharmony_ci sqlite3_result_int64(context_, process.switchCount_); 168fb726d48Sopenharmony_ci break; 169fb726d48Sopenharmony_ci case Index::THREAD_COUNT: 170fb726d48Sopenharmony_ci sqlite3_result_int64(context_, process.threadCount_); 171fb726d48Sopenharmony_ci break; 172fb726d48Sopenharmony_ci case Index::SLICE_COUNT: 173fb726d48Sopenharmony_ci sqlite3_result_int64(context_, process.sliceSize_); 174fb726d48Sopenharmony_ci break; 175fb726d48Sopenharmony_ci case Index::MEM_COUNT: 176fb726d48Sopenharmony_ci sqlite3_result_int64(context_, process.memSize_); 177fb726d48Sopenharmony_ci break; 178fb726d48Sopenharmony_ci default: 179fb726d48Sopenharmony_ci TS_LOGF("Unregistered column : %d", col); 180fb726d48Sopenharmony_ci break; 181fb726d48Sopenharmony_ci } 182fb726d48Sopenharmony_ci return SQLITE_OK; 183fb726d48Sopenharmony_ci} 184fb726d48Sopenharmony_ci 185fb726d48Sopenharmony_civoid ProcessTable::Cursor::FilterPid(unsigned char op, uint64_t value) 186fb726d48Sopenharmony_ci{ 187fb726d48Sopenharmony_ci bool remove = false; 188fb726d48Sopenharmony_ci if (indexMap_->HasData()) { 189fb726d48Sopenharmony_ci indexMap_->ConvertToIndexMap(); 190fb726d48Sopenharmony_ci remove = true; 191fb726d48Sopenharmony_ci } 192fb726d48Sopenharmony_ci switch (op) { 193fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_EQ: 194fb726d48Sopenharmony_ci HandleIndexConstraintEQ(remove, value); 195fb726d48Sopenharmony_ci break; 196fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_NE: 197fb726d48Sopenharmony_ci HandleIndexConstraintNQ(remove, value); 198fb726d48Sopenharmony_ci break; 199fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: 200fb726d48Sopenharmony_ci break; 201fb726d48Sopenharmony_ci default: 202fb726d48Sopenharmony_ci break; 203fb726d48Sopenharmony_ci } // end of switch (op) 204fb726d48Sopenharmony_ci} 205fb726d48Sopenharmony_civoid ProcessTable::Cursor::HandleIndexConstraintEQ(bool remove, uint64_t value) 206fb726d48Sopenharmony_ci{ 207fb726d48Sopenharmony_ci if (remove) { 208fb726d48Sopenharmony_ci for (auto i = indexMap_->rowIndex_.begin(); i != indexMap_->rowIndex_.end();) { 209fb726d48Sopenharmony_ci if (dataCache_->GetConstProcessData()[*i].pid_ != value) { 210fb726d48Sopenharmony_ci i = indexMap_->rowIndex_.erase(i); 211fb726d48Sopenharmony_ci } else { 212fb726d48Sopenharmony_ci i++; 213fb726d48Sopenharmony_ci } 214fb726d48Sopenharmony_ci } 215fb726d48Sopenharmony_ci } else { 216fb726d48Sopenharmony_ci for (auto i = 0; i < dataCache_->GetConstProcessData().size(); i++) { 217fb726d48Sopenharmony_ci if (dataCache_->GetConstProcessData()[i].pid_ == value) { 218fb726d48Sopenharmony_ci indexMap_->rowIndex_.push_back(i); 219fb726d48Sopenharmony_ci } 220fb726d48Sopenharmony_ci } 221fb726d48Sopenharmony_ci } 222fb726d48Sopenharmony_ci indexMap_->FixSize(); 223fb726d48Sopenharmony_ci} 224fb726d48Sopenharmony_civoid ProcessTable::Cursor::HandleIndexConstraintNQ(bool remove, uint64_t value) 225fb726d48Sopenharmony_ci{ 226fb726d48Sopenharmony_ci if (remove) { 227fb726d48Sopenharmony_ci for (auto i = indexMap_->rowIndex_.begin(); i != indexMap_->rowIndex_.end();) { 228fb726d48Sopenharmony_ci if (dataCache_->GetConstProcessData()[*i].pid_ == value) { 229fb726d48Sopenharmony_ci i = indexMap_->rowIndex_.erase(i); 230fb726d48Sopenharmony_ci } else { 231fb726d48Sopenharmony_ci i++; 232fb726d48Sopenharmony_ci } 233fb726d48Sopenharmony_ci } 234fb726d48Sopenharmony_ci } else { 235fb726d48Sopenharmony_ci for (auto i = 0; i < dataCache_->GetConstProcessData().size(); i++) { 236fb726d48Sopenharmony_ci if (dataCache_->GetConstProcessData()[i].pid_ != value) { 237fb726d48Sopenharmony_ci indexMap_->rowIndex_.push_back(i); 238fb726d48Sopenharmony_ci } 239fb726d48Sopenharmony_ci } 240fb726d48Sopenharmony_ci } 241fb726d48Sopenharmony_ci indexMap_->FixSize(); 242fb726d48Sopenharmony_ci} 243fb726d48Sopenharmony_civoid ProcessTable::Cursor::FilterIndex(int32_t col, unsigned char op, sqlite3_value *argv) 244fb726d48Sopenharmony_ci{ 245fb726d48Sopenharmony_ci switch (static_cast<Index>(col)) { 246fb726d48Sopenharmony_ci case Index::PID: 247fb726d48Sopenharmony_ci /* code */ 248fb726d48Sopenharmony_ci FilterPid(op, static_cast<uint64_t>(sqlite3_value_int64(argv))); 249fb726d48Sopenharmony_ci break; 250fb726d48Sopenharmony_ci 251fb726d48Sopenharmony_ci default: 252fb726d48Sopenharmony_ci break; 253fb726d48Sopenharmony_ci } 254fb726d48Sopenharmony_ci} 255fb726d48Sopenharmony_civoid ProcessTable::Cursor::FilterId(unsigned char op, sqlite3_value *argv) 256fb726d48Sopenharmony_ci{ 257fb726d48Sopenharmony_ci auto procArgv = static_cast<TableRowId>(sqlite3_value_int64(argv)); 258fb726d48Sopenharmony_ci switch (op) { 259fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_EQ: 260fb726d48Sopenharmony_ci indexMap_->Intersect(procArgv, procArgv + 1); 261fb726d48Sopenharmony_ci break; 262fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_GE: 263fb726d48Sopenharmony_ci indexMap_->Intersect(procArgv, rowCount_); 264fb726d48Sopenharmony_ci break; 265fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_GT: 266fb726d48Sopenharmony_ci procArgv++; 267fb726d48Sopenharmony_ci indexMap_->Intersect(procArgv, rowCount_); 268fb726d48Sopenharmony_ci break; 269fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_LE: 270fb726d48Sopenharmony_ci procArgv++; 271fb726d48Sopenharmony_ci indexMap_->Intersect(0, procArgv); 272fb726d48Sopenharmony_ci break; 273fb726d48Sopenharmony_ci case SQLITE_INDEX_CONSTRAINT_LT: 274fb726d48Sopenharmony_ci indexMap_->Intersect(0, procArgv); 275fb726d48Sopenharmony_ci break; 276fb726d48Sopenharmony_ci default: 277fb726d48Sopenharmony_ci // can't filter, all rows 278fb726d48Sopenharmony_ci break; 279fb726d48Sopenharmony_ci } 280fb726d48Sopenharmony_ci} 281fb726d48Sopenharmony_ci 282fb726d48Sopenharmony_civoid ProcessTable::GetOrbyes(FilterConstraints &processfc, EstimatedIndexInfo &processei) 283fb726d48Sopenharmony_ci{ 284fb726d48Sopenharmony_ci auto processorderbys = processfc.GetOrderBys(); 285fb726d48Sopenharmony_ci for (auto i = 0; i < processorderbys.size(); i++) { 286fb726d48Sopenharmony_ci switch (static_cast<Index>(processorderbys[i].iColumn)) { 287fb726d48Sopenharmony_ci case Index::IPID: 288fb726d48Sopenharmony_ci case Index::ID: 289fb726d48Sopenharmony_ci break; 290fb726d48Sopenharmony_ci default: // other columns can be sorted by SQLite 291fb726d48Sopenharmony_ci processei.isOrdered = false; 292fb726d48Sopenharmony_ci break; 293fb726d48Sopenharmony_ci } 294fb726d48Sopenharmony_ci } 295fb726d48Sopenharmony_ci} 296fb726d48Sopenharmony_ci} // namespace TraceStreamer 297fb726d48Sopenharmony_ci} // namespace SysTuning 298