blob: 83ff7c5c4fdbb7100de4ad068bf51f89aac414e7 [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_DB_TABLE_H_
#define SRC_TRACE_PROCESSOR_DB_TABLE_H_
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "perfetto/base/compiler.h"
#include "perfetto/base/logging.h"
#include "perfetto/trace_processor/basic_types.h"
#include "perfetto/trace_processor/ref_counted.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/types.h"
#include "src/trace_processor/db/column_storage_overlay.h"
#include "src/trace_processor/db/query_executor.h"
namespace perfetto::trace_processor {
// Represents a table of data with named, strongly typed columns.
class Table {
public:
// Iterator over the rows of the table.
class Iterator {
public:
explicit Iterator(const Table* table) : table_(table) {
its_.reserve(table->overlays().size());
for (const auto& rm : table->overlays()) {
its_.emplace_back(rm.IterateRows());
}
}
// Creates an iterator which iterates over |table| by first creating
// overlays by Applying |apply| to the existing overlays and using the
// indices there for iteration.
explicit Iterator(const Table* table, RowMap apply) : table_(table) {
overlays_.reserve(table->overlays().size());
its_.reserve(table->overlays().size());
for (const auto& rm : table->overlays()) {
overlays_.emplace_back(rm.SelectRows(apply));
its_.emplace_back(overlays_.back().IterateRows());
}
}
Iterator(Iterator&&) noexcept = default;
Iterator& operator=(Iterator&&) = default;
Iterator(const Iterator&) = delete;
Iterator& operator=(const Iterator&) = delete;
// Advances the iterator to the next row of the table.
Iterator& operator++() {
for (auto& it : its_) {
it.Next();
}
return *this;
}
// Returns whether the row the iterator is pointing at is valid.
explicit operator bool() const { return its_[0]; }
// Returns the value at the current row for column |col_idx|.
SqlValue Get(uint32_t col_idx) const {
const auto& col = table_->columns_[col_idx];
return col.GetAtIdx(its_[col.overlay_index()].index());
}
// Returns the storage index for the current row for column |col_idx|.
uint32_t StorageIndexForColumn(uint32_t col_idx) const {
const auto& col = table_->columns_[col_idx];
return its_[col.overlay_index()].index();
}
// Returns the storage index for the last overlay.
uint32_t StorageIndexForLastOverlay() const { return its_.back().index(); }
private:
const Table* table_ = nullptr;
std::vector<ColumnStorageOverlay> overlays_;
std::vector<ColumnStorageOverlay::Iterator> its_;
};
// Helper class storing the schema of the table. This allows decisions to be
// made about operations on the table without materializing the table - this
// may be expensive for dynamically computed tables.
//
// Subclasses of Table usually provide a method (named Schema()) to statically
// generate an instance of this class.
struct Schema {
struct Column {
std::string name;
SqlValue::Type type;
bool is_id;
bool is_sorted;
bool is_hidden;
bool is_set_id;
};
std::vector<Column> columns;
};
static bool kUseFilterV2;
virtual ~Table();
// We explicitly define the move constructor here because we need to update
// the Table pointer in each column in the table.
Table(Table&& other) noexcept { *this = std::move(other); }
Table& operator=(Table&& other) noexcept;
// Return a chain corresponding to a given column.
const column::DataLayerChain& ChainForColumn(uint32_t col_idx) const {
return *chains_[col_idx];
}
// Filters and sorts the tables with the arguments specified, returning the
// result as a RowMap.
RowMap QueryToRowMap(
const std::vector<Constraint>&,
const std::vector<Order>&,
RowMap::OptimizeFor = RowMap::OptimizeFor::kMemory) const;
// Applies the RowMap |rm| onto this table and returns an iterator over the
// resulting rows.
Iterator ApplyAndIterateRows(RowMap rm) const {
return Iterator(this, std::move(rm));
}
// Sorts the table using the specified order by constraints.
Table Sort(const std::vector<Order>&) const;
// Returns an iterator over the rows in this table.
Iterator IterateRows() const { return Iterator(this); }
// Creates a copy of this table.
Table Copy() const;
uint32_t row_count() const { return row_count_; }
StringPool* string_pool() const { return string_pool_; }
const std::vector<ColumnLegacy>& columns() const { return columns_; }
const std::vector<RefPtr<column::DataLayer>>& storage_layers() const {
return storage_layers_;
}
const std::vector<RefPtr<column::DataLayer>>& null_layers() const {
return null_layers_;
}
protected:
Table(StringPool*,
uint32_t row_count,
std::vector<ColumnLegacy>,
std::vector<ColumnStorageOverlay>);
void CopyLastInsertFrom(const std::vector<ColumnStorageOverlay>& overlays) {
PERFETTO_DCHECK(overlays.size() <= overlays_.size());
// Add the last inserted row in each of the parent row maps to the
// corresponding row map in the child.
for (uint32_t i = 0; i < overlays.size(); ++i) {
const ColumnStorageOverlay& other = overlays[i];
overlays_[i].Insert(other.Get(other.size() - 1));
}
}
void IncrementRowCountAndAddToLastOverlay() {
// Also add the index of the new row to the identity row map and increment
// the size.
overlays_.back().Insert(row_count_++);
}
void OnConstructionCompleted(
std::vector<RefPtr<column::DataLayer>> storage_layers,
std::vector<RefPtr<column::DataLayer>> null_layers,
std::vector<RefPtr<column::DataLayer>> overlay_layers);
ColumnLegacy* GetColumn(uint32_t index) { return &columns_[index]; }
const std::vector<ColumnStorageOverlay>& overlays() const {
return overlays_;
}
private:
friend class ColumnLegacy;
PERFETTO_ALWAYS_INLINE RowMap FilterToRowMap(
const std::vector<Constraint>& cs,
RowMap::OptimizeFor optimize_for = RowMap::OptimizeFor::kMemory) const {
if (cs.empty()) {
return {0, row_count_, optimize_for};
}
if (kUseFilterV2) {
if (optimize_for == RowMap::OptimizeFor::kMemory) {
return QueryExecutor::FilterLegacy(this, cs);
}
return RowMap(QueryExecutor::FilterLegacy(this, cs).TakeAsIndexVector());
}
RowMap rm(0, row_count_, optimize_for);
for (const Constraint& c : cs) {
columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
}
return rm;
}
Table CopyExceptOverlays() const;
StringPool* string_pool_ = nullptr;
uint32_t row_count_ = 0;
std::vector<ColumnStorageOverlay> overlays_;
std::vector<ColumnLegacy> columns_;
std::vector<RefPtr<column::DataLayer>> storage_layers_;
std::vector<RefPtr<column::DataLayer>> null_layers_;
std::vector<RefPtr<column::DataLayer>> overlay_layers_;
std::vector<std::unique_ptr<column::DataLayerChain>> chains_;
};
} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_DB_TABLE_H_