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 "raw_table.h"
17 namespace SysTuning {
18 namespace TraceStreamer {
19 enum class Index : int32_t { ID = 0, TS, NAME, CPU, INTERNAL_TID };
20 enum RawType { RAW_CPU_IDLE = 1, RAW_SCHED_WAKEUP = 2, RAW_SCHED_WAKING = 3 };
GetNameIndex(const std::string &name)21 uint32_t GetNameIndex(const std::string &name)
22 {
23     if (name == "cpu_idle") {
24         return RAW_CPU_IDLE;
25     } else if (name == "sched_wakeup") {
26         return RAW_SCHED_WAKEUP;
27     } else if (name == "sched_waking") {
28         return RAW_SCHED_WAKING;
29     } else {
30         return INVALID_UINT32;
31     }
32 }
RawTable(const TraceDataCache *dataCache)33 RawTable::RawTable(const TraceDataCache *dataCache) : TableBase(dataCache)
34 {
35     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
36     tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
37     tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
38     tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
39     tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
40     tablePriKey_.push_back("id");
41 }
42 
~RawTable()43 RawTable::~RawTable() {}
44 
FilterByConstraint(FilterConstraints &rawfc, double &rawfilterCost, size_t rawrowCount, uint32_t rawcurrenti)45 void RawTable::FilterByConstraint(FilterConstraints &rawfc,
46                                   double &rawfilterCost,
47                                   size_t rawrowCount,
48                                   uint32_t rawcurrenti)
49 {
50     // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
51     // for loop
52     const auto &rawc = rawfc.GetConstraints()[rawcurrenti];
53     switch (static_cast<Index>(rawc.col)) {
54         case Index::ID: {
55             if (CanFilterId(rawc.op, rawrowCount)) {
56                 rawfc.UpdateConstraint(rawcurrenti, true);
57                 rawfilterCost += 1; // id can position by 1 step
58             } else {
59                 rawfilterCost += rawrowCount; // scan all rows
60             }
61             break;
62         }
63         default:                          // other column
64             rawfilterCost += rawrowCount; // scan all rows
65             break;
66     }
67 }
68 
CreateCursor()69 std::unique_ptr<TableBase::Cursor> RawTable::CreateCursor()
70 {
71     return std::make_unique<Cursor>(dataCache_, this);
72 }
73 
Cursor(const TraceDataCache *dataCache, TableBase *table)74 RawTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
75     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstRawTableData().Size())),
76       rawObj_(dataCache->GetConstRawTableData())
77 {
78 }
79 
~Cursor()80 RawTable::Cursor::~Cursor() {}
Filter(const FilterConstraints &fc, sqlite3_value **argv)81 int32_t RawTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
82 {
83     // reset indexMap_
84     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
85 
86     if (rowCount_ <= 0) {
87         return SQLITE_OK;
88     }
89 
90     auto RawTableCs = fc.GetConstraints();
91     std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
92     SwapIndexFront(RawTableCs, sId);
93     for (size_t i = 0; i < RawTableCs.size(); i++) {
94         const auto &c = RawTableCs[i];
95         switch (static_cast<Index>(c.col)) {
96             case Index::ID:
97                 FilterId(c.op, argv[c.idxInaConstraint]);
98                 break;
99             case Index::NAME:
100                 indexMap_->MixRange(c.op,
101                                     GetNameIndex(std::string(
102                                         reinterpret_cast<const char *>(sqlite3_value_text(argv[c.idxInaConstraint])))),
103                                     rawObj_.NameData());
104                 break;
105             case Index::TS:
106                 FilterTS(c.op, argv[c.idxInaConstraint], rawObj_.TimeStampData());
107                 break;
108             case Index::INTERNAL_TID:
109                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
110                                     rawObj_.InternalTidsData());
111                 break;
112             default:
113                 break;
114         }
115     }
116 
117     auto rawTableOrderbys = fc.GetOrderBys();
118     for (auto i = rawTableOrderbys.size(); i > 0;) {
119         i--;
120         switch (static_cast<Index>(rawTableOrderbys[i].iColumn)) {
121             case Index::ID:
122                 indexMap_->SortBy(rawTableOrderbys[i].desc);
123                 break;
124             default:
125                 break;
126         }
127     }
128 
129     return SQLITE_OK;
130 }
131 
Column(int32_t column) const132 int32_t RawTable::Cursor::Column(int32_t column) const
133 {
134     switch (static_cast<Index>(column)) {
135         case Index::ID:
136             sqlite3_result_int64(context_, static_cast<int32_t>(rawObj_.IdsData()[CurrentRow()]));
137             break;
138         case Index::TS:
139             sqlite3_result_int64(context_, static_cast<int64_t>(rawObj_.TimeStampData()[CurrentRow()]));
140             break;
141         case Index::NAME: {
142             if (rawObj_.NameData()[CurrentRow()] == RAW_CPU_IDLE) {
143                 sqlite3_result_text(context_, "cpu_idle", STR_DEFAULT_LEN, nullptr);
144             } else if (rawObj_.NameData()[CurrentRow()] == RAW_SCHED_WAKEUP) {
145                 sqlite3_result_text(context_, "sched_wakeup", STR_DEFAULT_LEN, nullptr);
146             } else if (rawObj_.NameData()[CurrentRow()] == RAW_SCHED_WAKING) {
147                 sqlite3_result_text(context_, "sched_waking", STR_DEFAULT_LEN, nullptr);
148             }
149             break;
150         }
151         case Index::CPU:
152             sqlite3_result_int64(context_, static_cast<int32_t>(rawObj_.CpuData()[CurrentRow()]));
153             break;
154         case Index::INTERNAL_TID:
155             sqlite3_result_int64(context_, static_cast<int32_t>(rawObj_.InternalTidsData()[CurrentRow()]));
156             break;
157         default:
158             TS_LOGF("Unregistered column : %d", column);
159             break;
160     }
161     return SQLITE_OK;
162 }
GetOrbyes(FilterConstraints &rawfc, EstimatedIndexInfo &rawei)163 void RawTable::GetOrbyes(FilterConstraints &rawfc, EstimatedIndexInfo &rawei)
164 {
165     auto raworderbys = rawfc.GetOrderBys();
166     for (auto i = 0; i < raworderbys.size(); i++) {
167         switch (static_cast<Index>(raworderbys[i].iColumn)) {
168             case Index::ID:
169                 break;
170             default: // other columns can be sorted by SQLite
171                 rawei.isOrdered = false;
172                 break;
173         }
174     }
175 }
176 } // namespace TraceStreamer
177 } // namespace SysTuning
178