blob: 306a78e831e87fbc3bf4678fcc866ba19c353a45 [file]
/*
* Copyright (C) 2026 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_TRACE_SUMMARY_SUMMARIZER_H_
#define SRC_TRACE_PROCESSOR_TRACE_SUMMARY_SUMMARIZER_H_
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
#include "perfetto/base/status.h"
#include "perfetto/ext/base/flat_hash_map.h"
#include "perfetto/trace_processor/summarizer.h"
namespace perfetto::trace_processor {
class DescriptorPool;
class TraceProcessor;
namespace perfetto_sql::generator {
class StructuredQueryGenerator;
} // namespace perfetto_sql::generator
namespace summary {
// Internal implementation of the public Summarizer interface.
// Manages lazy materialization of structured queries.
//
// Key behaviors:
// - Lazy: Queries materialized only when Query() is called.
// - Change detection: Uses proto hash to detect changes.
// - Dependency propagation: If A changes, dependents B->C->D re-materialize.
// - Table substitution: Unchanged queries reference their materialized tables.
// - Cleanup: All materialized tables/views are dropped when the SummarizerImpl
// is destroyed.
class SummarizerImpl : public Summarizer {
public:
SummarizerImpl(TraceProcessor* tp,
DescriptorPool* descriptor_pool,
std::string id);
~SummarizerImpl() override;
SummarizerImpl(const SummarizerImpl&) = delete;
SummarizerImpl& operator=(const SummarizerImpl&) = delete;
// Summarizer implementation.
base::Status UpdateSpec(const uint8_t* spec_data,
size_t spec_size,
SummarizerUpdateSpecResult* result) override;
base::Status Query(const std::string& query_id,
SummarizerQueryResult* result) override;
// Determines whether a query should be created as a VIEW instead of a
// materialized TABLE. Uses an allowlist of simple pass-through source types;
// unrecognized or complex sources default to TABLE (safe by default).
static bool ShouldUseView(const uint8_t* data, size_t size);
private:
struct QueryState {
std::string table_name;
std::string proto_hash; // Hash of the structured query proto bytes.
std::vector<std::string> columns;
int64_t row_count = 0;
double duration_ms = 0.0;
std::optional<std::string> error;
// For lazy materialization:
std::vector<uint8_t> proto_data; // Stored proto for deferred execution.
// All query IDs this query depends on, extracted recursively from all
// embedded query fields (inner_query, inner_query_id, join.left_query,
// filter_to_intervals.base, etc.). Used for transitive invalidation:
// if any dependency changes, this query must also be re-materialized.
std::vector<std::string> inner_query_ids;
bool needs_materialization = true; // True until successfully materialized.
bool is_view = false; // Whether materialized as VIEW (not TABLE).
std::string
old_table_name; // Old table/view to drop after new one created.
bool old_is_view = false; // Whether old_table_name is a VIEW.
// Analysis results (populated during materialization):
std::string sql; // Complete runnable SQL (includes + preambles + query).
std::string textproto; // Text proto representation.
std::string standalone_sql; // Fully standalone SQL (no materialized refs).
};
// Computes a hash of raw proto bytes for change detection.
std::string ComputeProtoHash(const uint8_t* data, size_t size);
// Materializes a single query using a pre-configured generator.
// The generator must have all queries added and modules/preambles executed.
base::Status MaterializeQuery(
const std::string& query_id,
QueryState& state,
perfetto_sql::generator::StructuredQueryGenerator& generator);
// Collects all dependencies for a query (in materialization order).
std::vector<std::string> CollectDependencies(const std::string& query_id);
// Prepares the generator for materialization (adds queries, executes modules
// and preambles). Called once per Query() invocation.
base::Status PrepareGenerator(
perfetto_sql::generator::StructuredQueryGenerator& generator,
std::vector<std::vector<uint8_t>>& table_source_protos);
// Drops a table or view by name.
void DropTableOrView(const std::string& name, bool is_view);
// Drops all materialized tables and views.
void DropAll();
// Generates standalone SQL for a query (deferred from materialization).
void GenerateStandaloneSql(QueryState& state);
TraceProcessor* tp_;
DescriptorPool* descriptor_pool_;
std::string id_;
base::FlatHashMap<std::string, QueryState> query_states_;
base::FlatHashMap<std::string, bool>
included_modules_; // Track included modules.
uint32_t next_materialized_id_ = 0;
};
} // namespace summary
} // namespace perfetto::trace_processor
#endif // SRC_TRACE_PROCESSOR_TRACE_SUMMARY_SUMMARIZER_H_