blob: ea8a70c77050a95dbc2f614bbe77b25e36d057fa [file] [log] [blame]
/*
* Copyright (C) 2020 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.
*/
#include "src/trace_processor/dynamic/describe_slice_generator.h"
#include "src/trace_processor/analysis/describe_slice.h"
#include "src/trace_processor/types/trace_processor_context.h"
#include "src/trace_processor/util/status_macros.h"
namespace perfetto {
namespace trace_processor {
namespace {
DescribeSliceGenerator::InputValues GetDescribeSliceInputValues(
const std::vector<Constraint>& cs) {
using DST = tables::DescribeSliceTable;
auto slice_id_fn = [](const Constraint& c) {
return c.col_idx == static_cast<uint32_t>(DST::ColumnIndex::slice_id) &&
c.op == FilterOp::kEq;
};
auto slice_id_it = std::find_if(cs.begin(), cs.end(), slice_id_fn);
PERFETTO_CHECK(slice_id_it != cs.end());
// TODO(rsavitski): consider checking type of the SqlValue, as erroneous
// queries that pass a null here (or otherwise unexpected type) will crash.
uint32_t slice_id_value = static_cast<uint32_t>(slice_id_it->value.AsLong());
return DescribeSliceGenerator::InputValues{slice_id_value};
}
} // namespace
DescribeSliceGenerator::DescribeSliceGenerator(TraceProcessorContext* context)
: context_(context) {}
DescribeSliceGenerator::~DescribeSliceGenerator() = default;
base::Status DescribeSliceGenerator::ValidateConstraints(
const QueryConstraints& qc) {
using T = tables::DescribeSliceTable;
const auto& cs = qc.constraints();
auto slice_id_fn = [](const QueryConstraints::Constraint& c) {
return c.column == static_cast<int>(T::ColumnIndex::slice_id) &&
c.op == SQLITE_INDEX_CONSTRAINT_EQ;
};
bool has_slice_id_cs =
std::find_if(cs.begin(), cs.end(), slice_id_fn) != cs.end();
return has_slice_id_cs
? base::OkStatus()
: base::ErrStatus("Failed to find required constraints");
}
base::Status DescribeSliceGenerator::ComputeTable(
const std::vector<Constraint>& cs,
const std::vector<Order>&,
const BitVector&,
std::unique_ptr<Table>& table_return) {
auto input = GetDescribeSliceInputValues(cs);
const auto& slices = context_->storage->slice_table();
base::Optional<SliceDescription> opt_desc;
RETURN_IF_ERROR(
DescribeSlice(slices, SliceId{input.slice_id_value}, &opt_desc));
auto* pool = context_->storage->mutable_string_pool();
std::unique_ptr<tables::DescribeSliceTable> table(
new tables::DescribeSliceTable(pool, nullptr));
if (opt_desc) {
tables::DescribeSliceTable::Row row;
row.description = context_->storage->InternString(
base::StringView(opt_desc->description));
row.doc_link =
context_->storage->InternString(base::StringView(opt_desc->doc_link));
row.slice_id = input.slice_id_value;
table->Insert(row);
}
table_return = std::move(table);
return base::OkStatus();
}
Table::Schema DescribeSliceGenerator::CreateSchema() {
return tables::DescribeSliceTable::Schema();
}
std::string DescribeSliceGenerator::TableName() {
return "describe_slice";
}
uint32_t DescribeSliceGenerator::EstimateRowCount() {
return 1;
}
} // namespace trace_processor
} // namespace perfetto