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"
17namespace SysTuning {
18namespace TraceStreamer {
19enum class Index : int32_t { ID = 0, TS, NAME, CPU, INTERNAL_TID };
20enum RawType { RAW_CPU_IDLE = 1, RAW_SCHED_WAKEUP = 2, RAW_SCHED_WAKING = 3 };
21uint32_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}
33RawTable::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
43RawTable::~RawTable() {}
44
45void 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
69std::unique_ptr<TableBase::Cursor> RawTable::CreateCursor()
70{
71    return std::make_unique<Cursor>(dataCache_, this);
72}
73
74RawTable::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
80RawTable::Cursor::~Cursor() {}
81int32_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
132int32_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}
163void 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