• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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_DB_TABLE_H_
18 #define SRC_TRACE_PROCESSOR_DB_TABLE_H_
19 
20 #include <stdint.h>
21 
22 #include <limits>
23 #include <numeric>
24 #include <optional>
25 #include <vector>
26 
27 #include "perfetto/base/logging.h"
28 #include "src/trace_processor/containers/string_pool.h"
29 #include "src/trace_processor/db/column.h"
30 #include "src/trace_processor/db/column_storage_overlay.h"
31 #include "src/trace_processor/db/typed_column.h"
32 
33 namespace perfetto {
34 namespace trace_processor {
35 
36 // Represents a table of data with named, strongly typed columns.
37 class Table {
38  public:
39   // Iterator over the rows of the table.
40   class Iterator {
41    public:
Iterator(const Table * table)42     explicit Iterator(const Table* table) : table_(table) {
43       its_.reserve(table->overlays().size());
44       for (const auto& rm : table->overlays()) {
45         its_.emplace_back(rm.IterateRows());
46       }
47     }
48 
49     Iterator(Iterator&&) noexcept = default;
50     Iterator& operator=(Iterator&&) = default;
51 
52     Iterator(const Iterator&) = delete;
53     Iterator& operator=(const Iterator&) = delete;
54 
55     // Advances the iterator to the next row of the table.
Next()56     void Next() {
57       for (auto& it : its_) {
58         it.Next();
59       }
60     }
61 
62     // Returns whether the row the iterator is pointing at is valid.
63     explicit operator bool() const { return its_[0]; }
64 
65     // Returns the value at the current row for column |col_idx|.
Get(uint32_t col_idx)66     SqlValue Get(uint32_t col_idx) const {
67       const auto& col = table_->columns_[col_idx];
68       return col.GetAtIdx(its_[col.overlay_index()].index());
69     }
70 
71    private:
72     const Table* table_ = nullptr;
73     std::vector<ColumnStorageOverlay::Iterator> its_;
74   };
75 
76   // Helper class storing the schema of the table. This allows decisions to be
77   // made about operations on the table without materializing the table - this
78   // may be expensive for dynamically computed tables.
79   //
80   // Subclasses of Table usually provide a method (named Schema()) to statically
81   // generate an instance of this class.
82   struct Schema {
83     struct Column {
84       std::string name;
85       SqlValue::Type type;
86       bool is_id;
87       bool is_sorted;
88       bool is_hidden;
89       bool is_set_id;
90     };
91     std::vector<Column> columns;
92   };
93 
94   Table();
95   virtual ~Table();
96 
97   // We explicitly define the move constructor here because we need to update
98   // the Table pointer in each column in the table.
Table(Table && other)99   Table(Table&& other) noexcept { *this = std::move(other); }
100   Table& operator=(Table&& other) noexcept;
101 
102   // Filters the Table using the specified filter constraints.
103   Table Filter(
104       const std::vector<Constraint>& cs,
105       RowMap::OptimizeFor optimize_for = RowMap::OptimizeFor::kMemory) const {
106     if (cs.empty())
107       return Copy();
108     return Apply(FilterToRowMap(cs, optimize_for));
109   }
110 
111   // Filters the Table using the specified filter constraints optionally
112   // specifying what the returned RowMap should optimize for.
113   // Returns a RowMap which, if applied to the table, would contain the rows
114   // post filter.
115   RowMap FilterToRowMap(
116       const std::vector<Constraint>& cs,
117       RowMap::OptimizeFor optimize_for = RowMap::OptimizeFor::kMemory) const {
118     RowMap rm(0, row_count_, optimize_for);
119     for (const Constraint& c : cs) {
120       columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
121     }
122     return rm;
123   }
124 
125   // Applies the given RowMap to the current table by picking out the rows
126   // specified in the RowMap to be present in the output table.
127   // Note: the RowMap should not reorder this table; this is guaranteed if the
128   // passed RowMap is generated using |FilterToRowMap|.
Apply(RowMap rm)129   Table Apply(RowMap rm) const {
130     Table table = CopyExceptOverlays();
131     table.row_count_ = rm.size();
132     table.overlays_.reserve(overlays_.size());
133     for (const ColumnStorageOverlay& map : overlays_) {
134       table.overlays_.emplace_back(map.SelectRows(rm));
135       PERFETTO_DCHECK(table.overlays_.back().size() == table.row_count());
136     }
137     // Pretty much any application of a RowMap will break the requirements on
138     // kSetId so remove it.
139     for (auto& col : table.columns_) {
140       col.flags_ &= ~Column::Flag::kSetId;
141     }
142     return table;
143   }
144 
145   // Sorts the Table using the specified order by constraints.
146   Table Sort(const std::vector<Order>& od) const;
147 
148   // Returns the column at index |idx| in the Table.
GetColumn(uint32_t idx)149   const Column& GetColumn(uint32_t idx) const { return columns_[idx]; }
150 
151   // Returns the column index with the given name or std::nullopt otherwise.
GetColumnIndexByName(const char * name)152   std::optional<uint32_t> GetColumnIndexByName(const char* name) const {
153     auto it = std::find_if(
154         columns_.begin(), columns_.end(),
155         [name](const Column& col) { return strcmp(col.name(), name) == 0; });
156     if (it == columns_.end())
157       return std::nullopt;
158     return static_cast<uint32_t>(std::distance(columns_.begin(), it));
159   }
160 
161   // Returns the column with the given name or nullptr otherwise.
GetColumnByName(const char * name)162   const Column* GetColumnByName(const char* name) const {
163     std::optional<uint32_t> opt_idx = GetColumnIndexByName(name);
164     if (!opt_idx)
165       return nullptr;
166     return &columns_[*opt_idx];
167   }
168 
169   template <typename T>
GetTypedColumnByName(const char * name)170   const TypedColumn<T>& GetTypedColumnByName(const char* name) const {
171     return *TypedColumn<T>::FromColumn(GetColumnByName(name));
172   }
173 
174   template <typename T>
GetIdColumnByName(const char * name)175   const IdColumn<T>& GetIdColumnByName(const char* name) const {
176     return *IdColumn<T>::FromColumn(GetColumnByName(name));
177   }
178 
179   // Returns the number of columns in the Table.
GetColumnCount()180   uint32_t GetColumnCount() const {
181     return static_cast<uint32_t>(columns_.size());
182   }
183 
184   // Returns an iterator into the Table.
IterateRows()185   Iterator IterateRows() const { return Iterator(this); }
186 
187   // Creates a copy of this table.
188   Table Copy() const;
189 
190   // Computes the schema of this table and returns it.
ComputeSchema()191   Schema ComputeSchema() const {
192     Schema schema;
193     schema.columns.reserve(columns_.size());
194     for (const auto& col : columns_) {
195       schema.columns.emplace_back(
196           Schema::Column{col.name(), col.type(), col.IsId(), col.IsSorted(),
197                          col.IsHidden(), col.IsSetId()});
198     }
199     return schema;
200   }
201 
row_count()202   uint32_t row_count() const { return row_count_; }
string_pool()203   StringPool* string_pool() const { return string_pool_; }
overlays()204   const std::vector<ColumnStorageOverlay>& overlays() const {
205     return overlays_;
206   }
columns()207   const std::vector<Column>& columns() const { return columns_; }
208 
209  protected:
210   explicit Table(StringPool* pool);
211 
CopyOverlays()212   std::vector<ColumnStorageOverlay> CopyOverlays() const {
213     std::vector<ColumnStorageOverlay> rm(overlays_.size());
214     for (uint32_t i = 0; i < overlays_.size(); ++i) {
215       rm[i] = overlays_[i].Copy();
216     }
217     return rm;
218   }
219 
220   std::vector<ColumnStorageOverlay> overlays_;
221   std::vector<Column> columns_;
222   uint32_t row_count_ = 0;
223 
224   StringPool* string_pool_ = nullptr;
225 
226  private:
227   friend class Column;
228   friend class View;
229 
230   Table CopyExceptOverlays() const;
231 };
232 
233 }  // namespace trace_processor
234 }  // namespace perfetto
235 
236 #endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
237