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#ifndef TABLE_INDEX_MAP_H
17fb726d48Sopenharmony_ci#define TABLE_INDEX_MAP_H
18fb726d48Sopenharmony_ci
19fb726d48Sopenharmony_ci#include <cstdint>
20fb726d48Sopenharmony_ci#include <deque>
21fb726d48Sopenharmony_ci#include <functional>
22fb726d48Sopenharmony_ci#include <vector>
23fb726d48Sopenharmony_ci#include "sqlite3.h"
24fb726d48Sopenharmony_ci#include "ts_common.h"
25fb726d48Sopenharmony_ci
26fb726d48Sopenharmony_cinamespace SysTuning {
27fb726d48Sopenharmony_cinamespace TraceStreamer {
28fb726d48Sopenharmony_ciclass IndexMap {
29fb726d48Sopenharmony_cipublic:
30fb726d48Sopenharmony_ci    IndexMap() {}
31fb726d48Sopenharmony_ci    ~IndexMap() {}
32fb726d48Sopenharmony_ci
33fb726d48Sopenharmony_ci    IndexMap(TableRowId start, TableRowId end);
34fb726d48Sopenharmony_ci    void ConvertToIndexMap();
35fb726d48Sopenharmony_ci    static void Sort();
36fb726d48Sopenharmony_ci    void Print();
37fb726d48Sopenharmony_ci    void Init();
38fb726d48Sopenharmony_ci    bool Merge(IndexMap *other);
39fb726d48Sopenharmony_ci    void FilterId(unsigned char op, sqlite3_value *argv);
40fb726d48Sopenharmony_ci    void FilterTS(unsigned char op, sqlite3_value *argv, const std::deque<InternalTime> &times);
41fb726d48Sopenharmony_ci    template <class T>
42fb726d48Sopenharmony_ci    void ProcessData(const std::deque<T> &dataQueue,
43fb726d48Sopenharmony_ci                     bool remove,
44fb726d48Sopenharmony_ci                     std::function<bool(TableRowId)> firstCheck,
45fb726d48Sopenharmony_ci                     std::function<bool(TableRowId)> scondCheck)
46fb726d48Sopenharmony_ci    {
47fb726d48Sopenharmony_ci        if (remove) {
48fb726d48Sopenharmony_ci            bool changed = false;
49fb726d48Sopenharmony_ci            for (const auto &val : rowIndex_) {
50fb726d48Sopenharmony_ci                if (!firstCheck(val)) {
51fb726d48Sopenharmony_ci                    changed = true;
52fb726d48Sopenharmony_ci                    rowIndexBak_.push_back(val);
53fb726d48Sopenharmony_ci                }
54fb726d48Sopenharmony_ci            }
55fb726d48Sopenharmony_ci            if (changed) {
56fb726d48Sopenharmony_ci                rowIndex_ = rowIndexBak_;
57fb726d48Sopenharmony_ci            }
58fb726d48Sopenharmony_ci        } else {
59fb726d48Sopenharmony_ci            for (auto i = 0; i < dataQueue.size(); i++) {
60fb726d48Sopenharmony_ci                if (scondCheck(i)) {
61fb726d48Sopenharmony_ci                    rowIndex_.push_back(i);
62fb726d48Sopenharmony_ci                }
63fb726d48Sopenharmony_ci            }
64fb726d48Sopenharmony_ci        }
65fb726d48Sopenharmony_ci        indexType_ = INDEX_TYPE_OUTER_INDEX;
66fb726d48Sopenharmony_ci        FixSize();
67fb726d48Sopenharmony_ci    }
68fb726d48Sopenharmony_ci    void PrepMixRange(bool &remove)
69fb726d48Sopenharmony_ci    {
70fb726d48Sopenharmony_ci        filters_++;
71fb726d48Sopenharmony_ci        if (HasData()) {
72fb726d48Sopenharmony_ci            ConvertToIndexMap();
73fb726d48Sopenharmony_ci            remove = true;
74fb726d48Sopenharmony_ci        }
75fb726d48Sopenharmony_ci        rowIndexBak_.clear();
76fb726d48Sopenharmony_ci    }
77fb726d48Sopenharmony_ci    template <class T>
78fb726d48Sopenharmony_ci    void MixRange(unsigned char op, T value, const std::deque<T> &dataQueue)
79fb726d48Sopenharmony_ci    {
80fb726d48Sopenharmony_ci        auto invalidValue = std::numeric_limits<T>::max();
81fb726d48Sopenharmony_ci        bool remove = false;
82fb726d48Sopenharmony_ci        PrepMixRange(remove);
83fb726d48Sopenharmony_ci        switch (op) {
84fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_EQ:
85fb726d48Sopenharmony_ci                ProcessData(
86fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != value; },
87fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] == value; });
88fb726d48Sopenharmony_ci                break;
89fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_NE:
90fb726d48Sopenharmony_ci                ProcessData(
91fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == value; },
92fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] != value; });
93fb726d48Sopenharmony_ci                break;
94fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_ISNULL:
95fb726d48Sopenharmony_ci                ProcessData(
96fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; },
97fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; });
98fb726d48Sopenharmony_ci                break;
99fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
100fb726d48Sopenharmony_ci                ProcessData(
101fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] == invalidValue; },
102fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] != invalidValue; });
103fb726d48Sopenharmony_ci                break;
104fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_GT:
105fb726d48Sopenharmony_ci                ProcessData(
106fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] <= value; },
107fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] > value; });
108fb726d48Sopenharmony_ci                break;
109fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_GE:
110fb726d48Sopenharmony_ci                ProcessData(
111fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] < value; },
112fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] >= value; });
113fb726d48Sopenharmony_ci                break;
114fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_LE:
115fb726d48Sopenharmony_ci                ProcessData(
116fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] > value; },
117fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] <= value; });
118fb726d48Sopenharmony_ci                break;
119fb726d48Sopenharmony_ci            case SQLITE_INDEX_CONSTRAINT_LT:
120fb726d48Sopenharmony_ci                ProcessData(
121fb726d48Sopenharmony_ci                    dataQueue, remove, [&](TableRowId id) -> bool { return dataQueue[id] >= value; },
122fb726d48Sopenharmony_ci                    [&](TableRowId id) -> bool { return dataQueue[id] < value; });
123fb726d48Sopenharmony_ci                break;
124fb726d48Sopenharmony_ci            default:
125fb726d48Sopenharmony_ci                break;
126fb726d48Sopenharmony_ci        } // end of switch (op)
127fb726d48Sopenharmony_ci        empty_ = false;
128fb726d48Sopenharmony_ci    }
129fb726d48Sopenharmony_ci    void FixSize()
130fb726d48Sopenharmony_ci    {
131fb726d48Sopenharmony_ci        if (indexType_ == INDEX_TYPE_OUTER_INDEX) {
132fb726d48Sopenharmony_ci            end_ = rowIndex_.size();
133fb726d48Sopenharmony_ci            current_ = 0;
134fb726d48Sopenharmony_ci        }
135fb726d48Sopenharmony_ci    }
136fb726d48Sopenharmony_ci    void Remove(TableRowId row)
137fb726d48Sopenharmony_ci    {
138fb726d48Sopenharmony_ci        (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row);
139fb726d48Sopenharmony_ci    }
140fb726d48Sopenharmony_ci    void Set(TableRowId start, TableRowId end)
141fb726d48Sopenharmony_ci    {
142fb726d48Sopenharmony_ci        if (indexType_ == INDEX_TYPE_ID) {
143fb726d48Sopenharmony_ci            end_ = std::min(end_, end);
144fb726d48Sopenharmony_ci            current_ = start_ = std::max(start_, start);
145fb726d48Sopenharmony_ci        }
146fb726d48Sopenharmony_ci    }
147fb726d48Sopenharmony_ci
148fb726d48Sopenharmony_ci    size_t Size() const;
149fb726d48Sopenharmony_ci
150fb726d48Sopenharmony_ci    void Next();
151fb726d48Sopenharmony_ci
152fb726d48Sopenharmony_ci    bool Eof() const;
153fb726d48Sopenharmony_ci
154fb726d48Sopenharmony_ci    TableRowId CurrentRow() const;
155fb726d48Sopenharmony_ci
156fb726d48Sopenharmony_ci    void SortBy(bool desc);
157fb726d48Sopenharmony_ci    void Intersect(TableRowId start, TableRowId end);
158fb726d48Sopenharmony_ci
159fb726d48Sopenharmony_ci    // the follow functions require that thecolData is sotred
160fb726d48Sopenharmony_ci    template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
161fb726d48Sopenharmony_ci    void IntersectabcEqual(const std::deque<Row> &rows, Val v, GetV getValue)
162fb726d48Sopenharmony_ci    {
163fb726d48Sopenharmony_ci        auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v);
164fb726d48Sopenharmony_ci        auto end = std::upper_bound(start, rows.begin() + end_, v);
165fb726d48Sopenharmony_ci        auto newStart = std::distance(rows.begin(), start);
166fb726d48Sopenharmony_ci        auto newEnd = std::distance(rows.begin(), end);
167fb726d48Sopenharmony_ci        Intersect(newStart, newEnd);
168fb726d48Sopenharmony_ci        return;
169fb726d48Sopenharmony_ci    }
170fb726d48Sopenharmony_ci
171fb726d48Sopenharmony_ci    template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
172fb726d48Sopenharmony_ci    void IntersectGreaterEqual(const std::deque<Row> &rows, Val v, GetV getValue)
173fb726d48Sopenharmony_ci    {
174fb726d48Sopenharmony_ci        auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v,
175fb726d48Sopenharmony_ci                                      [&](const Row &row, const Val &v) { return v > getValue(row); });
176fb726d48Sopenharmony_ci        auto newStart = std::distance(rows.begin(), start);
177fb726d48Sopenharmony_ci        Intersect(newStart, INVALID_INT32);
178fb726d48Sopenharmony_ci        return;
179fb726d48Sopenharmony_ci    }
180fb726d48Sopenharmony_ci
181fb726d48Sopenharmony_ci    template <typename Row, typename Val, typename GetV = const Val &(const Row &)>
182fb726d48Sopenharmony_ci    void IntersectLessEqual(const std::deque<Row> &rows, Val v, GetV getValue)
183fb726d48Sopenharmony_ci    {
184fb726d48Sopenharmony_ci        auto end = std::upper_bound(rows.begin() + start_, rows.begin() + end_, v,
185fb726d48Sopenharmony_ci                                    [&](const Row &row, const Val &v) { return v > getValue(row); });
186fb726d48Sopenharmony_ci        auto newEnd = std::distance(rows.begin(), end);
187fb726d48Sopenharmony_ci        Intersect(0, newEnd);
188fb726d48Sopenharmony_ci        return;
189fb726d48Sopenharmony_ci    }
190fb726d48Sopenharmony_ci    template <typename T>
191fb726d48Sopenharmony_ci    void RemoveNullElements(const std::deque<T> &rows, T v)
192fb726d48Sopenharmony_ci    {
193fb726d48Sopenharmony_ci        auto invalidValue = std::numeric_limits<T>::max();
194fb726d48Sopenharmony_ci        bool remove = false;
195fb726d48Sopenharmony_ci        if (HasData()) {
196fb726d48Sopenharmony_ci            ConvertToIndexMap();
197fb726d48Sopenharmony_ci            remove = true;
198fb726d48Sopenharmony_ci        }
199fb726d48Sopenharmony_ci
200fb726d48Sopenharmony_ci        if (remove) {
201fb726d48Sopenharmony_ci            for (auto i = rowIndex_.begin(); i != rowIndex_.end();) {
202fb726d48Sopenharmony_ci                if (rows[*i] == invalidValue) {
203fb726d48Sopenharmony_ci                    i = rowIndex_.erase(i);
204fb726d48Sopenharmony_ci                } else {
205fb726d48Sopenharmony_ci                    i++;
206fb726d48Sopenharmony_ci                }
207fb726d48Sopenharmony_ci            }
208fb726d48Sopenharmony_ci        } else {
209fb726d48Sopenharmony_ci            auto size = rows.size();
210fb726d48Sopenharmony_ci            for (size_t i = 0; i < size; i++) {
211fb726d48Sopenharmony_ci                if (rows[i] != invalidValue) {
212fb726d48Sopenharmony_ci                    rowIndex_.push_back(i);
213fb726d48Sopenharmony_ci                }
214fb726d48Sopenharmony_ci            }
215fb726d48Sopenharmony_ci            empty_ = false;
216fb726d48Sopenharmony_ci        }
217fb726d48Sopenharmony_ci        indexType_ = INDEX_TYPE_OUTER_INDEX;
218fb726d48Sopenharmony_ci        FixSize();
219fb726d48Sopenharmony_ci        return;
220fb726d48Sopenharmony_ci    }
221fb726d48Sopenharmony_ci    bool HasData() const;
222fb726d48Sopenharmony_ci    std::vector<TableRowId> rowIndex_ = {};
223fb726d48Sopenharmony_ci    std::vector<TableRowId> rowIndexBak_ = {};
224fb726d48Sopenharmony_ci
225fb726d48Sopenharmony_ciprivate:
226fb726d48Sopenharmony_ci    bool MergeIndexTypeId(IndexMap *other);
227fb726d48Sopenharmony_ci
228fb726d48Sopenharmony_ciprivate:
229fb726d48Sopenharmony_ci    TableRowId end_ = INVALID_INT32;
230fb726d48Sopenharmony_ci    TableRowId current_ = 0;
231fb726d48Sopenharmony_ci    TableRowId start_ = 0;
232fb726d48Sopenharmony_ci    enum FindIndexType {
233fb726d48Sopenharmony_ci        INDEX_TYPE_ID,
234fb726d48Sopenharmony_ci        INDEX_TYPE_OUTER_INDEX,
235fb726d48Sopenharmony_ci    };
236fb726d48Sopenharmony_ci    FindIndexType indexType_ = INDEX_TYPE_ID;
237fb726d48Sopenharmony_ci
238fb726d48Sopenharmony_ci    enum IndexType { COMPACT, SPARSE };
239fb726d48Sopenharmony_ci    bool empty_ = true;
240fb726d48Sopenharmony_ci    bool desc_ = false;
241fb726d48Sopenharmony_ci    bool converted_ = false;
242fb726d48Sopenharmony_ci    uint8_t filters_ = 0;
243fb726d48Sopenharmony_ci    bool intersectEable_ = false;
244fb726d48Sopenharmony_ci};
245fb726d48Sopenharmony_ci} // namespace TraceStreamer
246fb726d48Sopenharmony_ci} // namespace SysTuning
247fb726d48Sopenharmony_ci
248fb726d48Sopenharmony_ci#endif // TABLE_INDEX_MAP_H
249