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 "instants_table.h"
17 #include <cmath>
18 
19 namespace SysTuning {
20 namespace TraceStreamer {
21 enum class Index : int32_t { TS = 0, NAME, REF, WAKEUP_FROM, REF_TYPE, VALUE };
InstantsTable(const TraceDataCache *dataCache)22 InstantsTable::InstantsTable(const TraceDataCache *dataCache) : TableBase(dataCache)
23 {
24     tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
25     tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
26     tableColumn_.push_back(TableBase::ColumnInfo("ref", "INTEGER"));
27     tableColumn_.push_back(TableBase::ColumnInfo("wakeup_from", "INTEGER"));
28     tableColumn_.push_back(TableBase::ColumnInfo("ref_type", "TEXT"));
29     tableColumn_.push_back(TableBase::ColumnInfo("value", "REAL"));
30     tablePriKey_.push_back("ts");
31     tablePriKey_.push_back("ref");
32 }
33 
~InstantsTable()34 InstantsTable::~InstantsTable() {}
35 
CreateCursor()36 std::unique_ptr<TableBase::Cursor> InstantsTable::CreateCursor()
37 {
38     return std::make_unique<Cursor>(dataCache_, this);
39 }
40 
Cursor(const TraceDataCache *dataCache, TableBase *table)41 InstantsTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
42     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstInstantsData().Size())),
43       InstantsObj_(dataCache->GetConstInstantsData())
44 {
45 }
46 
~Cursor()47 InstantsTable::Cursor::~Cursor() {}
48 
FilterByConstraint(FilterConstraints &instantsfc, double &instantsfilterCost, size_t instantsrowCount, uint32_t instantscurrenti)49 void InstantsTable::FilterByConstraint(FilterConstraints &instantsfc,
50                                        double &instantsfilterCost,
51                                        size_t instantsrowCount,
52                                        uint32_t instantscurrenti)
53 {
54     const auto &instantsc = instantsfc.GetConstraints()[instantscurrenti];
55     switch (static_cast<Index>(instantsc.col)) {
56         case Index::TS: {
57             auto instantsoldRowCount = instantsrowCount;
58             if (CanFilterSorted(instantsc.op, instantsrowCount)) {
59                 instantsfc.UpdateConstraint(instantscurrenti, true);
60                 instantsfilterCost += log2(instantsoldRowCount); // binary search
61             } else {
62                 instantsfilterCost += instantsoldRowCount;
63             }
64             break;
65         }
66         default:                                    // other column
67             instantsfilterCost += instantsrowCount; // scan all rows
68             break;
69     }
70 }
71 
SortOfIndexMap(const FilterConstraints &fc)72 void InstantsTable::Cursor::SortOfIndexMap(const FilterConstraints &fc)
73 {
74     auto orderbys = fc.GetOrderBys();
75     for (auto i = orderbys.size(); i > 0;) {
76         i--;
77         switch (static_cast<Index>(orderbys[i].iColumn)) {
78             case Index::TS:
79                 indexMap_->SortBy(orderbys[i].desc);
80                 break;
81             default:
82                 break;
83         }
84     }
85 }
86 
Filter(const FilterConstraints &fc, sqlite3_value **argv)87 int32_t InstantsTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
88 {
89     // reset
90     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
91     if (rowCount_ <= 0) {
92         return SQLITE_OK;
93     }
94     auto instantsTabCs = fc.GetConstraints();
95     std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
96     SwapIndexFront(instantsTabCs, sId);
97     for (size_t i = 0; i < instantsTabCs.size(); i++) {
98         const auto &c = instantsTabCs[i];
99         switch (static_cast<Index>(c.col)) {
100             case Index::TS:
101                 FilterTS(c.op, argv[c.idxInaConstraint], InstantsObj_.TimeStampData());
102                 break;
103             case Index::NAME:
104                 indexMap_->MixRange(c.op,
105                                     dataCache_->GetConstDataIndex(std::string(
106                                         reinterpret_cast<const char *>(sqlite3_value_text(argv[c.idxInaConstraint])))),
107                                     InstantsObj_.NameIndexsData());
108                 break;
109             case Index::REF:
110                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
111                                     InstantsObj_.InternalTidsData());
112                 break;
113             case Index::WAKEUP_FROM:
114                 indexMap_->MixRange(c.op, static_cast<int64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
115                                     InstantsObj_.WakeupFromPidsData());
116                 break;
117             default:
118                 break;
119         }
120     }
121     SortOfIndexMap(fc);
122 
123     return SQLITE_OK;
124 }
125 
Column(int32_t column) const126 int32_t InstantsTable::Cursor::Column(int32_t column) const
127 {
128     size_t stringIdentity = static_cast<size_t>(InstantsObj_.NameIndexsData()[CurrentRow()]);
129     switch (static_cast<Index>(column)) {
130         case Index::TS:
131             sqlite3_result_int64(context_, static_cast<int64_t>(InstantsObj_.TimeStampData()[CurrentRow()]));
132             break;
133         case Index::NAME: {
134             sqlite3_result_text(context_, dataCache_->GetDataFromDict(stringIdentity).c_str(), STR_DEFAULT_LEN,
135                                 nullptr);
136             break;
137         }
138         case Index::REF:
139             sqlite3_result_int64(context_, static_cast<int32_t>(InstantsObj_.InternalTidsData()[CurrentRow()]));
140             break;
141         case Index::WAKEUP_FROM:
142             sqlite3_result_int64(context_, static_cast<int32_t>(InstantsObj_.WakeupFromPidsData()[CurrentRow()]));
143             break;
144         case Index::REF_TYPE: {
145             sqlite3_result_text(context_, "itid", STR_DEFAULT_LEN, nullptr);
146             break;
147         }
148         case Index::VALUE: {
149             sqlite3_result_double(context_, 0.0);
150             break;
151         }
152         default:
153             TS_LOGF("Unregistered column : %d", column);
154             break;
155     }
156     return SQLITE_OK;
157 }
GetOrbyes(FilterConstraints &instantsfc, EstimatedIndexInfo &instantsei)158 void InstantsTable::GetOrbyes(FilterConstraints &instantsfc, EstimatedIndexInfo &instantsei)
159 {
160     // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
161     // for loop
162     auto instantsorderbys = instantsfc.GetOrderBys();
163     for (auto i = 0; i < instantsorderbys.size(); i++) {
164         switch (static_cast<Index>(instantsorderbys[i].iColumn)) {
165             case Index::TS:
166                 break;
167             default: // other columns can be sorted by SQLite
168                 instantsei.isOrdered = false;
169                 break;
170         }
171     }
172 }
173 } // namespace TraceStreamer
174 } // namespace SysTuning
175