blob: ebb76bb67ce69fd8afab21b8938ad95650602854 [file] [log] [blame]
/*
* 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 <type_traits>
#include <utility>
#include <vector>
#include "perfetto/base/logging.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_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.
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;
void UpdateOverlaysAfterParentInsert() {
CopyLastInsertFrom(parent_->overlays());
}
void UpdateSelfOverlayAfterInsert() {
IncrementRowCountAndAddToLastOverlay();
}
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;
}
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:
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;
}
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_