| /* | 
 |  * 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_ |