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