• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_OPERATORS_INTERVAL_INTERSECT_OPERATOR_H_
18 #define SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_OPERATORS_INTERVAL_INTERSECT_OPERATOR_H_
19 
20 #include <sqlite3.h>
21 #include <array>
22 #include <cstdint>
23 #include <memory>
24 #include <vector>
25 
26 #include "perfetto/ext/base/hash.h"
27 #include "perfetto/trace_processor/basic_types.h"
28 #include "src/trace_processor/containers/bit_vector.h"
29 #include "src/trace_processor/containers/interval_tree.h"
30 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
31 #include "src/trace_processor/sqlite/bindings/sqlite_module.h"
32 #include "src/trace_processor/sqlite/module_lifecycle_manager.h"
33 
34 namespace perfetto::trace_processor {
35 
36 struct IntervalIntersectOperator : sqlite::Module<IntervalIntersectOperator> {
37   static constexpr uint16_t kSchemaColumnsCount = 16;
38   using SchemaCol = uint16_t;
39   using SchemaToTableColumnMap =
40       std::array<std::optional<SchemaCol>, kSchemaColumnsCount>;
41 
42   enum OperatorType { kInner = 0, kOuter = 1 };
43   struct State {
44     PerfettoSqlEngine* engine;
45     std::array<std::optional<uint16_t>, kSchemaColumnsCount> argv_to_col_map{};
46   };
47 
48   struct Context {
ContextIntervalIntersectOperator::Context49     explicit Context(PerfettoSqlEngine* _engine) : engine(_engine) {}
50     PerfettoSqlEngine* engine;
51     sqlite::ModuleStateManager<IntervalIntersectOperator> manager;
52   };
53 
54   struct Vtab : sqlite::Module<IntervalIntersectOperator>::Vtab {
55     sqlite::ModuleStateManager<IntervalIntersectOperator>::PerVtabState* state;
56   };
57 
58   struct Cursor : sqlite::Module<IntervalIntersectOperator>::Cursor {
59     using TreesKey = uint64_t;
60     using TreesMap = base::FlatHashMap<TreesKey,
61                                        std::unique_ptr<IntervalTree>,
62                                        base::AlreadyHashed<TreesKey>>;
63 
64     struct InnerData {
65       TreesMap trees;
66       SchemaToTableColumnMap additional_cols;
67 
68       std::vector<uint32_t> query_results;
69       uint32_t index = 0;
70 
GetResultIdIntervalIntersectOperator::Cursor::InnerData71       inline uint32_t GetResultId() const { return query_results[index]; }
QueryIntervalIntersectOperator::Cursor::InnerData72       inline void Query(uint64_t start,
73                         uint64_t end,
74                         const TreesKey& tree_key) {
75         query_results.clear();
76         index = 0;
77         auto* tree_ptr = trees.Find(tree_key);
78         PERFETTO_DCHECK(tree_ptr);
79         (*tree_ptr)->FindOverlaps(start, end, query_results);
80       }
81     };
82 
83     struct OuterData {
84       std::unique_ptr<Table::Iterator> it;
85       SchemaToTableColumnMap additional_cols;
86 
GetIntervalIntersectOperator::Cursor::OuterData87       inline SqlValue Get(int col) {
88         return it->Get(*additional_cols[static_cast<size_t>(col)]);
89       }
90     };
91 
92     OperatorType type;
93     std::string table_name;
94     std::string exposed_cols_str;
95     const Table* table = nullptr;
96 
97     // Only one of those can be non null.
98     InnerData inner;
99     OuterData outer;
100   };
101 
102   static constexpr auto kType = kEponymousOnly;
103   static constexpr bool kSupportsWrites = false;
104   static constexpr bool kDoesOverloadFunctions = false;
105 
106   static int Connect(sqlite3*,
107                      void*,
108                      int,
109                      const char* const*,
110                      sqlite3_vtab**,
111                      char**);
112 
113   static int Disconnect(sqlite3_vtab*);
114 
115   static int BestIndex(sqlite3_vtab*, sqlite3_index_info*);
116 
117   static int Open(sqlite3_vtab*, sqlite3_vtab_cursor**);
118   static int Close(sqlite3_vtab_cursor*);
119 
120   static int Filter(sqlite3_vtab_cursor*,
121                     int,
122                     const char*,
123                     int,
124                     sqlite3_value**);
125   static int Next(sqlite3_vtab_cursor*);
126   static int Eof(sqlite3_vtab_cursor*);
127   static int Column(sqlite3_vtab_cursor*, sqlite3_context*, int);
128   static int Rowid(sqlite3_vtab_cursor*, sqlite_int64*);
129 
130   // This needs to happen at the end as it depends on the functions
131   // defined above.
132   static constexpr sqlite3_module kModule = CreateModule();
133 };
134 
135 }  // namespace perfetto::trace_processor
136 
137 #endif  // SRC_TRACE_PROCESSOR_PERFETTO_SQL_INTRINSICS_OPERATORS_INTERVAL_INTERSECT_OPERATOR_H_
138