/* * 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. */ #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_ #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_ #include #include "src/trace_processor/importers/common/args_tracker.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/types/trace_processor_context.h" namespace perfetto { namespace trace_processor { using FlowId = uint64_t; class FlowTracker { public: explicit FlowTracker(TraceProcessorContext*); virtual ~FlowTracker(); void InsertFlow(SliceId slice_out_id, SliceId slice_in_id); // These methods assume you have created a FlowId via GetFlowIdForV1Event. // If you don't have a v1 event you should use the InsertFlow method above. virtual void Begin(TrackId track_id, FlowId flow_id); virtual void Step(TrackId track_id, FlowId flow_id); // When |bind_enclosing_slice| is true we will connect the flow to the // currently open slice on the track, when false we will connect the flow to // the next slice to be opened on the track. // When |close_flow| is true it will mark this as the singular end of the // flow, however if there are multiple end points this should be set to // false. Both parameters are only needed for v1 flow events support virtual void End(TrackId track_id, FlowId flow_id, bool bind_enclosing_slice, bool close_flow); bool IsActive(FlowId flow_id) const; FlowId GetFlowIdForV1Event(uint64_t source_id, StringId cat, StringId name); void ClosePendingEventsOnTrack(TrackId track_id, SliceId slice_id); private: struct V1FlowId { uint64_t source_id; StringId cat; StringId name; bool operator==(const V1FlowId& o) const { return o.source_id == source_id && o.cat == cat && o.name == name; } }; struct V1FlowIdHasher { size_t operator()(const V1FlowId& c) const { base::Hash hasher; hasher.Update(c.source_id); hasher.Update(c.cat.raw_id()); hasher.Update(c.name.raw_id()); return std::hash{}(hasher.digest()); } }; using FlowToSourceSliceMap = std::unordered_map; using PendingFlowsMap = std::unordered_map>; using V1FlowIdToFlowIdMap = std::unordered_map; using FlowIdToV1FlowId = std::unordered_map; void InsertFlow(FlowId flow_id, SliceId outgoing_slice_id, SliceId incoming_slice_id); // List of flow end calls waiting for the next slice PendingFlowsMap pending_flow_ids_map_; // Flows generated by Begin() or Step() FlowToSourceSliceMap flow_to_slice_map_; V1FlowIdToFlowIdMap v1_flow_id_to_flow_id_map_; FlowIdToV1FlowId flow_id_to_v1_flow_id_map_; uint32_t v1_id_counter_ = 0; TraceProcessorContext* const context_; StringId name_key_id_; StringId cat_key_id_; }; } // namespace trace_processor } // namespace perfetto #endif // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_FLOW_TRACKER_H_