1/* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 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 "irq_table.h" 17 18namespace SysTuning { 19namespace TraceStreamer { 20enum class Index : int32_t { ID = 0, TS, DURS, CALL_IDS, CAT, NAME, DEPTH, COOKIE_ID, PARENT_ID, ARGSET, FLAG }; 21IrqTable::IrqTable(const TraceDataCache *dataCache) : TableBase(dataCache) 22{ 23 tableColumn_.emplace_back(TableBase::ColumnInfo("id", "INTEGER")); 24 tableColumn_.emplace_back(TableBase::ColumnInfo("ts", "INTEGER")); 25 tableColumn_.emplace_back(TableBase::ColumnInfo("dur", "INTEGER")); 26 tableColumn_.emplace_back(TableBase::ColumnInfo("callid", "INTEGER")); 27 tableColumn_.emplace_back(TableBase::ColumnInfo("cat", "TEXT")); 28 tableColumn_.emplace_back(TableBase::ColumnInfo("name", "TEXT")); 29 tableColumn_.emplace_back(TableBase::ColumnInfo("depth", "INTEGER")); 30 tableColumn_.emplace_back(TableBase::ColumnInfo("cookie", "INTEGER")); 31 tableColumn_.emplace_back(TableBase::ColumnInfo("parent_id", "INTEGER")); 32 tableColumn_.emplace_back(TableBase::ColumnInfo("argsetid", "INTEGER")); 33 tableColumn_.emplace_back(TableBase::ColumnInfo("flag", "TEXT")); 34 tablePriKey_.emplace_back("callid"); 35 tablePriKey_.emplace_back("ts"); 36 tablePriKey_.emplace_back("depth"); 37} 38 39IrqTable::~IrqTable() {} 40 41void IrqTable::FilterByConstraint(FilterConstraints &irqfc, 42 double &irqfilterCost, 43 size_t irqrowCount, 44 uint32_t irqcurrenti) 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 &irqc = irqfc.GetConstraints()[irqcurrenti]; 49 switch (static_cast<Index>(irqc.col)) { 50 case Index::ID: { 51 if (CanFilterId(irqc.op, irqrowCount)) { 52 irqfc.UpdateConstraint(irqcurrenti, true); 53 irqfilterCost += 1; // id can position by 1 step 54 } else { 55 irqfilterCost += irqrowCount; // scan all rows 56 } 57 break; 58 } 59 default: // other column 60 irqfilterCost += irqrowCount; // scan all rows 61 break; 62 } 63} 64 65std::unique_ptr<TableBase::Cursor> IrqTable::CreateCursor() 66{ 67 return std::make_unique<Cursor>(dataCache_, this); 68} 69 70IrqTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table) 71 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstIrqData().Size())), 72 slicesObj_(dataCache->GetConstIrqData()) 73{ 74} 75 76IrqTable::Cursor::~Cursor() {} 77 78int32_t IrqTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv) 79{ 80 // reset indexMap_ 81 indexMap_ = std::make_unique<IndexMap>(0, rowCount_); 82 83 if (rowCount_ <= 0) { 84 return SQLITE_OK; 85 } 86 87 auto &irqCs = fc.GetConstraints(); 88 for (size_t i = 0; i < irqCs.size(); i++) { 89 const auto &c = irqCs[i]; 90 switch (static_cast<Index>(c.col)) { 91 case Index::ID: 92 FilterId(c.op, argv[i]); 93 break; 94 default: 95 break; 96 } 97 } 98 99 auto irqTableOrderbys = fc.GetOrderBys(); 100 for (auto i = irqTableOrderbys.size(); i > 0;) { 101 i--; 102 switch (static_cast<Index>(irqTableOrderbys[i].iColumn)) { 103 case Index::ID: 104 indexMap_->SortBy(irqTableOrderbys[i].desc); 105 break; 106 default: 107 break; 108 } 109 } 110 111 return SQLITE_OK; 112} 113 114int32_t IrqTable::Cursor::Column(int32_t column) const 115{ 116 switch (static_cast<Index>(column)) { 117 case Index::ID: 118 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.IdsData()[CurrentRow()])); 119 break; 120 case Index::TS: 121 SetTypeColumnInt64(slicesObj_.TimeStampData()[CurrentRow()], INVALID_UINT64); 122 break; 123 case Index::DURS: 124 SetTypeColumnInt64(slicesObj_.DursData()[CurrentRow()], INVALID_UINT64); 125 break; 126 case Index::CALL_IDS: 127 SetTypeColumnInt64(slicesObj_.CallIds()[CurrentRow()], INVALID_UINT64); 128 break; 129 case Index::CAT: { 130 SetTypeColumnText(slicesObj_.CatsData()[CurrentRow()], INVALID_UINT64); 131 break; 132 } 133 case Index::NAME: { 134 SetTypeColumnText(slicesObj_.NamesData()[CurrentRow()], INVALID_UINT64); 135 break; 136 } 137 case Index::DEPTH: 138 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.Depths()[CurrentRow()])); 139 break; 140 default: 141 HandleTypeColumns(column); 142 } 143 return SQLITE_OK; 144} 145void IrqTable::Cursor::HandleTypeColumns(int32_t column) const 146{ 147 switch (static_cast<Index>(column)) { 148 case Index::COOKIE_ID: 149 SetTypeColumnInt64(slicesObj_.Cookies()[CurrentRow()], INVALID_INT64); 150 break; 151 case Index::PARENT_ID: { 152 if (slicesObj_.ParentIdData()[CurrentRow()].has_value()) { 153 sqlite3_result_int64(context_, static_cast<int64_t>(slicesObj_.ParentIdData()[CurrentRow()].value())); 154 } 155 break; 156 } 157 case Index::ARGSET: 158 SetTypeColumnInt64(slicesObj_.ArgSetIdsData()[CurrentRow()], INVALID_UINT32); 159 break; 160 case Index::FLAG: 161 sqlite3_result_text(context_, slicesObj_.Flags()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); 162 break; 163 default: 164 TS_LOGF("Unregistered column : %d", column); 165 break; 166 } 167} 168void IrqTable::GetOrbyes(FilterConstraints &irqfc, EstimatedIndexInfo &irqei) 169{ 170 auto irqorderbys = irqfc.GetOrderBys(); 171 for (auto i = 0; i < irqorderbys.size(); i++) { 172 switch (static_cast<Index>(irqorderbys[i].iColumn)) { 173 case Index::ID: 174 break; 175 default: // other columns can be sorted by SQLite 176 irqei.isOrdered = false; 177 break; 178 } 179 } 180} 181} // namespace TraceStreamer 182} // namespace SysTuning 183