|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ | 
|  | #define SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <cstdint> | 
|  | #include <initializer_list> | 
|  | #include <type_traits> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "perfetto/base/compiler.h" | 
|  | #include "perfetto/base/logging.h" | 
|  | #include "perfetto/trace_processor/ref_counted.h" | 
|  | #include "src/trace_processor/containers/bit_vector.h" | 
|  | #include "src/trace_processor/containers/row_map.h" | 
|  | #include "src/trace_processor/containers/string_pool.h" | 
|  | #include "src/trace_processor/db/column.h" | 
|  | #include "src/trace_processor/db/column/data_layer.h" | 
|  | #include "src/trace_processor/db/column/selector_overlay.h" | 
|  | #include "src/trace_processor/db/column_storage.h" | 
|  | #include "src/trace_processor/db/column_storage_overlay.h" | 
|  | #include "src/trace_processor/db/table.h" | 
|  |  | 
|  | namespace perfetto::trace_processor::macros_internal { | 
|  |  | 
|  | // We define this class to allow the table macro below to compile without | 
|  | // needing templates; in reality none of the methods will be called because the | 
|  | // pointer to this class will always be null. | 
|  | class RootParentTable : public Table { | 
|  | public: | 
|  | struct Row { | 
|  | public: | 
|  | explicit Row(std::nullptr_t = nullptr) {} | 
|  |  | 
|  | const char* type() const { return type_; } | 
|  |  | 
|  | protected: | 
|  | const char* type_ = nullptr; | 
|  | }; | 
|  | // This class only exists to allow typechecking to work correctly in Insert | 
|  | // below. If we had C++17 and if constexpr, we could statically verify that | 
|  | // this was never created but for now, we still need to define it to satisfy | 
|  | // the typechecker. | 
|  | struct IdAndRow { | 
|  | uint32_t id; | 
|  | }; | 
|  | struct RowNumber { | 
|  | static uint32_t row_number() { PERFETTO_FATAL("Should not be called"); } | 
|  | }; | 
|  | static IdAndRow Insert(const Row&) { PERFETTO_FATAL("Should not be called"); } | 
|  |  | 
|  | private: | 
|  | explicit RootParentTable(std::nullptr_t); | 
|  | }; | 
|  |  | 
|  | // The parent class for all macro generated tables. | 
|  | // This class is used to extract common code from the macro tables to reduce | 
|  | // code size. | 
|  | class MacroTable : public Table { | 
|  | public: | 
|  | // We don't want a move or copy constructor because we store pointers to | 
|  | // fields of macro tables which will be invalidated if we move/copy them. | 
|  | MacroTable(const MacroTable&) = delete; | 
|  | MacroTable& operator=(const MacroTable&) = delete; | 
|  |  | 
|  | MacroTable(MacroTable&&) = delete; | 
|  | MacroTable& operator=(MacroTable&&) noexcept = delete; | 
|  |  | 
|  | protected: | 
|  | // Constructors for tables created by the regular constructor. | 
|  | PERFETTO_NO_INLINE explicit MacroTable(StringPool* pool, | 
|  | std::vector<ColumnLegacy> columns, | 
|  | const MacroTable* parent) | 
|  | : Table(pool, 0u, std::move(columns), EmptyOverlaysFromParent(parent)), | 
|  | allow_inserts_(true), | 
|  | parent_(parent) {} | 
|  |  | 
|  | // Constructor for tables created by SelectAndExtendParent. | 
|  | MacroTable(StringPool* pool, | 
|  | std::vector<ColumnLegacy> columns, | 
|  | const MacroTable& parent, | 
|  | const RowMap& parent_overlay) | 
|  | : Table(pool, | 
|  | parent_overlay.size(), | 
|  | std::move(columns), | 
|  | SelectedOverlaysFromParent(parent, parent_overlay)), | 
|  | allow_inserts_(false), | 
|  | parent_(&parent) {} | 
|  |  | 
|  | ~MacroTable() override; | 
|  |  | 
|  | PERFETTO_NO_INLINE void UpdateOverlaysAfterParentInsert() { | 
|  | CopyLastInsertFrom(parent_->overlays()); | 
|  | } | 
|  |  | 
|  | PERFETTO_NO_INLINE void UpdateSelfOverlayAfterInsert() { | 
|  | IncrementRowCountAndAddToLastOverlay(); | 
|  | } | 
|  |  | 
|  | PERFETTO_NO_INLINE static std::vector<ColumnLegacy> | 
|  | CopyColumnsFromParentOrAddRootColumns(MacroTable* self, | 
|  | const MacroTable* parent) { | 
|  | std::vector<ColumnLegacy> columns; | 
|  | if (parent) { | 
|  | for (const ColumnLegacy& col : parent->columns()) { | 
|  | columns.emplace_back(col, col.index_in_table(), col.overlay_index()); | 
|  | } | 
|  | } else { | 
|  | columns.emplace_back(ColumnLegacy::IdColumn(0, 0)); | 
|  | columns.emplace_back("type", &self->type_, ColumnLegacy::kNonNull, 1, 0); | 
|  | } | 
|  | return columns; | 
|  | } | 
|  |  | 
|  | PERFETTO_NO_INLINE void OnConstructionCompletedRegularConstructor( | 
|  | std::initializer_list<RefPtr<column::DataLayer>> storage_layers, | 
|  | std::initializer_list<RefPtr<column::DataLayer>> null_layers) { | 
|  | std::vector<RefPtr<column::DataLayer>> overlay_layers( | 
|  | OverlayCount(parent_) + 1); | 
|  | for (uint32_t i = 0; i < overlay_layers.size() - 1; ++i) { | 
|  | PERFETTO_CHECK(overlays()[i].row_map().IsBitVector()); | 
|  | overlay_layers[i].reset(new column::SelectorOverlay( | 
|  | overlays()[i].row_map().GetIfBitVector())); | 
|  | } | 
|  | Table::OnConstructionCompleted(storage_layers, null_layers, | 
|  | std::move(overlay_layers)); | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | PERFETTO_NO_INLINE static void AddColumnToVector( | 
|  | std::vector<ColumnLegacy>& columns, | 
|  | const char* name, | 
|  | ColumnStorage<T>* storage, | 
|  | uint32_t flags, | 
|  | uint32_t column_index, | 
|  | uint32_t overlay_index) { | 
|  | columns.emplace_back(name, storage, flags, column_index, overlay_index); | 
|  | } | 
|  |  | 
|  | static uint32_t OverlayCount(const MacroTable* parent) { | 
|  | return parent ? static_cast<uint32_t>(parent->overlays().size()) : 0; | 
|  | } | 
|  |  | 
|  | // Stores whether inserts are allowed into this macro table; by default | 
|  | // inserts are allowed but they are disallowed when a parent table is extended | 
|  | // with |ExtendParent|; the rationale for this is that extensions usually | 
|  | // happen in dynamic tables and they should not be allowed to insert rows into | 
|  | // the real (static) tables. | 
|  | bool allow_inserts_ = true; | 
|  |  | 
|  | // Stores the most specific "derived" type of this row in the table. | 
|  | // | 
|  | // For example, suppose a row is inserted into the gpu_slice table. This will | 
|  | // also cause a row to be inserted into the slice table. For users querying | 
|  | // the slice table, they will want to know the "real" type of this slice (i.e. | 
|  | // they will want to see that the type is gpu_slice). This sparse vector | 
|  | // stores precisely the real type. | 
|  | // | 
|  | // Only relevant for parentless tables. Will be empty and unreferenced by | 
|  | // tables with parents. | 
|  | ColumnStorage<StringPool::Id> type_; | 
|  |  | 
|  | private: | 
|  | PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> | 
|  | EmptyOverlaysFromParent(const MacroTable* parent) { | 
|  | std::vector<ColumnStorageOverlay> overlays( | 
|  | parent ? parent->overlays().size() : 0); | 
|  | for (auto& overlay : overlays) { | 
|  | overlay = ColumnStorageOverlay(BitVector()); | 
|  | } | 
|  | overlays.emplace_back(); | 
|  | return overlays; | 
|  | } | 
|  | PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> | 
|  | SelectedOverlaysFromParent(const macros_internal::MacroTable& parent, | 
|  | const RowMap& rm) { | 
|  | std::vector<ColumnStorageOverlay> overlays; | 
|  | for (const auto& overlay : parent.overlays()) { | 
|  | overlays.emplace_back(overlay.SelectRows(rm)); | 
|  | PERFETTO_DCHECK(overlays.back().size() == rm.size()); | 
|  | } | 
|  | overlays.emplace_back(rm.size()); | 
|  | return overlays; | 
|  | } | 
|  |  | 
|  | const MacroTable* parent_ = nullptr; | 
|  | }; | 
|  |  | 
|  | // Abstract iterator class for macro tables. | 
|  | // Extracted to allow sharing with view code. | 
|  | template <typename Iterator, | 
|  | typename MacroTable, | 
|  | typename RowNumber, | 
|  | typename ConstRowReference> | 
|  | class AbstractConstIterator { | 
|  | public: | 
|  | explicit operator bool() const { return bool(iterator_); } | 
|  |  | 
|  | Iterator& operator++() { | 
|  | ++iterator_; | 
|  | return *this_it(); | 
|  | } | 
|  |  | 
|  | // Returns a RowNumber for the current row. | 
|  | RowNumber row_number() const { | 
|  | return RowNumber(this_it()->CurrentRowNumber()); | 
|  | } | 
|  |  | 
|  | // Returns a ConstRowReference to the current row. | 
|  | ConstRowReference row_reference() const { | 
|  | return ConstRowReference(table_, this_it()->CurrentRowNumber()); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | explicit AbstractConstIterator(const MacroTable* table, | 
|  | Table::Iterator iterator) | 
|  | : iterator_(std::move(iterator)), table_(table) { | 
|  | static_assert(std::is_base_of<Table, MacroTable>::value, | 
|  | "Template param should be a subclass of Table."); | 
|  | } | 
|  |  | 
|  | Table::Iterator iterator_; | 
|  | const MacroTable* table_; | 
|  |  | 
|  | private: | 
|  | Iterator* this_it() { return static_cast<Iterator*>(this); } | 
|  | const Iterator* this_it() const { return static_cast<const Iterator*>(this); } | 
|  | }; | 
|  |  | 
|  | // Abstract RowNumber class for macro tables. | 
|  | // Extracted to allow sharing with view code. | 
|  | template <typename MacroTable, | 
|  | typename ConstRowReference, | 
|  | typename RowReference = void> | 
|  | class AbstractRowNumber { | 
|  | public: | 
|  | // Converts this RowNumber to a RowReference for the given |table|. | 
|  | template < | 
|  | typename RR = RowReference, | 
|  | typename = typename std::enable_if<!std::is_same<RR, void>::value>::type> | 
|  | RR ToRowReference(MacroTable* table) const { | 
|  | return RR(table, row_number_); | 
|  | } | 
|  |  | 
|  | // Converts this RowNumber to a ConstRowReference for the given |table|. | 
|  | ConstRowReference ToRowReference(const MacroTable& table) const { | 
|  | return ConstRowReference(&table, row_number_); | 
|  | } | 
|  |  | 
|  | // Converts this object to the underlying int value. | 
|  | uint32_t row_number() const { return row_number_; } | 
|  |  | 
|  | // Allows sorting + storage in a map/set. | 
|  | bool operator<(const AbstractRowNumber& other) const { | 
|  | return row_number_ < other.row_number_; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | explicit AbstractRowNumber(uint32_t row_number) : row_number_(row_number) {} | 
|  |  | 
|  | private: | 
|  | uint32_t row_number_ = 0; | 
|  | }; | 
|  |  | 
|  | // Abstract ConstRowReference class for macro tables. | 
|  | // Extracted to allow sharing with view code. | 
|  | template <typename MacroTable, typename RowNumber> | 
|  | class AbstractConstRowReference { | 
|  | public: | 
|  | // Converts this RowReference to a RowNumber object which is more memory | 
|  | // efficient to store. | 
|  | RowNumber ToRowNumber() { return RowNumber(row_number_); } | 
|  |  | 
|  | protected: | 
|  | AbstractConstRowReference(const MacroTable* table, uint32_t row_number) | 
|  | : table_(table), row_number_(row_number) {} | 
|  |  | 
|  | const MacroTable* table_ = nullptr; | 
|  | uint32_t row_number_ = 0; | 
|  | }; | 
|  |  | 
|  | }  // namespace perfetto::trace_processor::macros_internal | 
|  |  | 
|  | #endif  // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ |