• 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 <cstdint>
21 #include <memory>
22 #include <optional>
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 #include "perfetto/base/logging.h"
28 #include "perfetto/ext/base/status_or.h"
29 #include "perfetto/trace_processor/basic_types.h"
30 #include "perfetto/trace_processor/ref_counted.h"
31 #include "src/trace_processor/containers/row_map.h"
32 #include "src/trace_processor/containers/string_pool.h"
33 #include "src/trace_processor/db/column.h"
34 #include "src/trace_processor/db/column/data_layer.h"
35 #include "src/trace_processor/db/column/types.h"
36 #include "src/trace_processor/db/column_storage_overlay.h"
37 
38 namespace perfetto::trace_processor {
39 
40 // Represents a table of data with named, strongly typed columns.
41 class Table {
42  public:
43   // Iterator over the rows of the table.
44   class Iterator {
45    public:
Iterator(const Table * table)46     explicit Iterator(const Table* table) : table_(table) {
47       its_.reserve(table->overlays().size());
48       for (const auto& rm : table->overlays()) {
49         its_.emplace_back(rm.IterateRows());
50       }
51     }
52 
53     // Creates an iterator which iterates over |table| by first creating
54     // overlays by Applying |apply| to the existing overlays and using the
55     // indices there for iteration.
Iterator(const Table * table,RowMap apply)56     explicit Iterator(const Table* table, RowMap apply) : table_(table) {
57       overlays_.reserve(table->overlays().size());
58       its_.reserve(table->overlays().size());
59       for (const auto& rm : table->overlays()) {
60         overlays_.emplace_back(rm.SelectRows(apply));
61         its_.emplace_back(overlays_.back().IterateRows());
62       }
63     }
64 
65     Iterator(Iterator&&) noexcept = default;
66     Iterator& operator=(Iterator&&) = default;
67 
68     Iterator(const Iterator&) = delete;
69     Iterator& operator=(const Iterator&) = delete;
70 
71     // Advances the iterator to the next row of the table.
72     Iterator& operator++() {
73       for (auto& it : its_) {
74         it.Next();
75       }
76       return *this;
77     }
78 
79     // Returns whether the row the iterator is pointing at is valid.
80     explicit operator bool() const { return bool(its_[0]); }
81 
82     // Returns the value at the current row for column |col_idx|.
Get(uint32_t col_idx)83     SqlValue Get(uint32_t col_idx) const {
84       const auto& col = table_->columns_[col_idx];
85       return col.GetAtIdx(its_[col.overlay_index()].index());
86     }
87 
88     // Returns the storage index for the current row for column |col_idx|.
StorageIndexForColumn(uint32_t col_idx)89     uint32_t StorageIndexForColumn(uint32_t col_idx) const {
90       const auto& col = table_->columns_[col_idx];
91       return its_[col.overlay_index()].index();
92     }
93 
94     // Returns the storage index for the last overlay.
StorageIndexForLastOverlay()95     uint32_t StorageIndexForLastOverlay() const { return its_.back().index(); }
96 
97    private:
98     const Table* table_ = nullptr;
99     std::vector<ColumnStorageOverlay> overlays_;
100     std::vector<ColumnStorageOverlay::Iterator> its_;
101   };
102 
103   // Helper class storing the schema of the table. This allows decisions to be
104   // made about operations on the table without materializing the table - this
105   // may be expensive for dynamically computed tables.
106   //
107   // Subclasses of Table usually provide a method (named Schema()) to statically
108   // generate an instance of this class.
109   struct Schema {
110     struct Column {
111       std::string name;
112       SqlValue::Type type;
113       bool is_id;
114       bool is_sorted;
115       bool is_hidden;
116       bool is_set_id;
117     };
118     std::vector<Column> columns;
119   };
120 
121   virtual ~Table();
122 
123   // We explicitly define the move constructor here because we need to update
124   // the Table pointer in each column in the table.
Table(Table && other)125   Table(Table&& other) noexcept { *this = std::move(other); }
126   Table& operator=(Table&& other) noexcept;
127 
128   // Return a chain corresponding to a given column.
ChainForColumn(uint32_t col_idx)129   const column::DataLayerChain& ChainForColumn(uint32_t col_idx) const {
130     return *chains_[col_idx];
131   }
132 
133   // Filters and sorts the tables with the arguments specified, returning the
134   // result as a RowMap.
135   RowMap QueryToRowMap(const Query&) const;
136 
137   // Applies the RowMap |rm| onto this table and returns an iterator over the
138   // resulting rows.
ApplyAndIterateRows(RowMap rm)139   Iterator ApplyAndIterateRows(RowMap rm) const {
140     return Iterator(this, std::move(rm));
141   }
142 
143   // Sorts the table using the specified order by constraints.
144   Table Sort(const std::vector<Order>&) const;
145 
146   // Returns an iterator over the rows in this table.
IterateRows()147   Iterator IterateRows() const { return Iterator(this); }
148 
149   // Creates a copy of this table.
150   Table Copy() const;
151 
152   // Looks for a column in a table.
153   // TODO(mayzner): This is not a long term function, it should be used with
154   // caution.
ColumnIdxFromName(const std::string & col_name)155   std::optional<uint32_t> ColumnIdxFromName(const std::string& col_name) const {
156     auto x = std::find_if(columns_.begin(), columns_.end(),
157                           [col_name](const ColumnLegacy& col) {
158                             return col_name.compare(col.name()) == 0;
159                           });
160 
161     return (x == columns_.end()) ? std::nullopt
162                                  : std::make_optional(x->index_in_table());
163   }
164 
row_count()165   uint32_t row_count() const { return row_count_; }
string_pool()166   StringPool* string_pool() const { return string_pool_; }
columns()167   const std::vector<ColumnLegacy>& columns() const { return columns_; }
storage_layers()168   const std::vector<RefPtr<column::DataLayer>>& storage_layers() const {
169     return storage_layers_;
170   }
null_layers()171   const std::vector<RefPtr<column::DataLayer>>& null_layers() const {
172     return null_layers_;
173   }
174 
175  protected:
176   Table(StringPool*,
177         uint32_t row_count,
178         std::vector<ColumnLegacy>,
179         std::vector<ColumnStorageOverlay>);
180 
CopyLastInsertFrom(const std::vector<ColumnStorageOverlay> & overlays)181   void CopyLastInsertFrom(const std::vector<ColumnStorageOverlay>& overlays) {
182     PERFETTO_DCHECK(overlays.size() <= overlays_.size());
183 
184     // Add the last inserted row in each of the parent row maps to the
185     // corresponding row map in the child.
186     for (uint32_t i = 0; i < overlays.size(); ++i) {
187       const ColumnStorageOverlay& other = overlays[i];
188       overlays_[i].Insert(other.Get(other.size() - 1));
189     }
190   }
191 
IncrementRowCountAndAddToLastOverlay()192   void IncrementRowCountAndAddToLastOverlay() {
193     // Also add the index of the new row to the identity row map and increment
194     // the size.
195     overlays_.back().Insert(row_count_++);
196   }
197 
198   void OnConstructionCompleted(
199       std::vector<RefPtr<column::DataLayer>> storage_layers,
200       std::vector<RefPtr<column::DataLayer>> null_layers,
201       std::vector<RefPtr<column::DataLayer>> overlay_layers);
202 
GetColumn(uint32_t index)203   ColumnLegacy* GetColumn(uint32_t index) { return &columns_[index]; }
204 
overlays()205   const std::vector<ColumnStorageOverlay>& overlays() const {
206     return overlays_;
207   }
208 
209  private:
210   friend class ColumnLegacy;
211 
212   void CreateChains() const;
213 
214   Table CopyExceptOverlays() const;
215 
216   void ApplyDistinct(const Query&, RowMap*) const;
217   void ApplySort(const Query&, RowMap*) const;
218 
219   StringPool* string_pool_ = nullptr;
220   uint32_t row_count_ = 0;
221   std::vector<ColumnStorageOverlay> overlays_;
222   std::vector<ColumnLegacy> columns_;
223 
224   std::vector<RefPtr<column::DataLayer>> storage_layers_;
225   std::vector<RefPtr<column::DataLayer>> null_layers_;
226   std::vector<RefPtr<column::DataLayer>> overlay_layers_;
227   mutable std::vector<std::unique_ptr<column::DataLayerChain>> chains_;
228 };
229 
230 }  // namespace perfetto::trace_processor
231 
232 #endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
233