1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_ 19 20 #include "src/trace_processor/storage/trace_storage.h" 21 #include "src/trace_processor/types/trace_processor_context.h" 22 23 namespace perfetto { 24 namespace trace_processor { 25 26 // Tracks and stores tracks based on track types, ids and scopes. 27 class TrackEventTracker { 28 public: 29 explicit TrackEventTracker(TraceProcessorContext*); 30 31 // Associate a TrackDescriptor track identified by the given |uuid| with a 32 // process's |pid|. This is called during tokenization. If a reservation for 33 // the same |uuid| already exists, verifies that the present reservation 34 // matches the new one. 35 // 36 // The track will be resolved to the process track (see InternProcessTrack()) 37 // upon the first call to GetDescriptorTrack() with the same |uuid|. At this 38 // time, |pid| will also be resolved to a |upid|. 39 void ReserveDescriptorProcessTrack(uint64_t uuid, 40 StringId name, 41 uint32_t pid, 42 int64_t timestamp); 43 44 // Associate a TrackDescriptor track identified by the given |uuid| with a 45 // thread's |pid| and |tid|. This is called during tokenization. If a 46 // reservation for the same |uuid| already exists, verifies that the present 47 // reservation matches the new one. 48 // 49 // The track will be resolved to the thread track (see InternThreadTrack()) 50 // upon the first call to GetDescriptorTrack() with the same |uuid|. At this 51 // time, |pid| will also be resolved to a |upid|. 52 void ReserveDescriptorThreadTrack(uint64_t uuid, 53 uint64_t parent_uuid, 54 StringId name, 55 uint32_t pid, 56 uint32_t tid, 57 int64_t timestamp); 58 59 // Associate a TrackDescriptor track identified by the given |uuid| with a 60 // parent track (usually a process- or thread-associated track). This is 61 // called during tokenization. If a reservation for the same |uuid| already 62 // exists, will attempt to update it. 63 // 64 // The track will be created upon the first call to GetDescriptorTrack() with 65 // the same |uuid|. If |parent_uuid| is 0, the track will become a global 66 // track. Otherwise, it will become a new track of the same type as its parent 67 // track. 68 void ReserveDescriptorChildTrack(uint64_t uuid, 69 uint64_t parent_uuid, 70 StringId name); 71 72 // Associate a counter-type TrackDescriptor track identified by the given 73 // |uuid| with a parent track (usually a process or thread track). This is 74 // called during tokenization. If a reservation for the same |uuid| already 75 // exists, will attempt to update it. The provided |category| will be stored 76 // into the track's args. 77 // 78 // If |is_incremental| is true, the counter will only be valid on the packet 79 // sequence identified by |packet_sequence_id|. |unit_multiplier| is an 80 // optional multiplication factor applied to counter values. Values for the 81 // counter will be translated during tokenization via 82 // ConvertToAbsoluteCounterValue(). 83 // 84 // The track will be created upon the first call to GetDescriptorTrack() with 85 // the same |uuid|. If |parent_uuid| is 0, the track will become a global 86 // track. Otherwise, it will become a new counter track for the same 87 // process/thread as its parent track. 88 void ReserveDescriptorCounterTrack(uint64_t uuid, 89 uint64_t parent_uuid, 90 StringId name, 91 StringId category, 92 int64_t unit_multiplier, 93 bool is_incremental, 94 uint32_t packet_sequence_id); 95 96 // Returns the ID of the track for the TrackDescriptor with the given |uuid|. 97 // This is called during parsing. The first call to GetDescriptorTrack() for 98 // each |uuid| resolves and inserts the track (and its parent tracks, 99 // following the parent_uuid chain recursively) based on reservations made for 100 // the |uuid|. If the track is a child track and doesn't have a name yet, 101 // updates the track's name to event_name. Returns nullopt if no track for a 102 // descriptor with this |uuid| has been reserved. 103 // TODO(lalitm): this method needs to be split up and moved back to 104 // TrackTracker. 105 base::Optional<TrackId> GetDescriptorTrack( 106 uint64_t uuid, 107 StringId event_name = kNullStringId); 108 109 // Converts the given counter value to an absolute value in the unit of the 110 // counter, applying incremental delta encoding or unit multipliers as 111 // necessary. If the counter uses incremental encoding, |packet_sequence_id| 112 // must match the one in its track reservation. Returns base::nullopt if the 113 // counter track is unknown or an invalid |packet_sequence_id| was passed. 114 base::Optional<double> ConvertToAbsoluteCounterValue( 115 uint64_t counter_track_uuid, 116 uint32_t packet_sequence_id, 117 double value); 118 119 // Returns the ID of the implicit trace-global default TrackDescriptor track. 120 // TODO(lalitm): this method needs to be moved back to TrackTracker once 121 // GetDescriptorTrack is moved back. 122 TrackId GetOrCreateDefaultDescriptorTrack(); 123 124 // Called by ProtoTraceReader whenever incremental state is cleared on a 125 // packet sequence. Resets counter values for any incremental counters of 126 // the sequence identified by |packet_sequence_id|. 127 void OnIncrementalStateCleared(uint32_t packet_sequence_id); 128 129 private: 130 struct DescriptorTrackReservation { 131 uint64_t parent_uuid = 0; 132 base::Optional<uint32_t> pid; 133 base::Optional<uint32_t> tid; 134 int64_t min_timestamp = 0; // only set if |pid| and/or |tid| is set. 135 StringId name = kNullStringId; 136 137 // For counter tracks. 138 bool is_counter = false; 139 StringId category = kNullStringId; 140 int64_t unit_multiplier = 1; 141 bool is_incremental = false; 142 uint32_t packet_sequence_id = 0; 143 double latest_value = 0; 144 145 // Whether |other| is a valid descriptor for this track reservation. A track 146 // should always remain nested underneath its original parent. IsForSameTrackDescriptorTrackReservation147 bool IsForSameTrack(const DescriptorTrackReservation& other) { 148 // Note that |min_timestamp|, |latest_value|, and |name| are ignored for 149 // this comparison. 150 return std::tie(parent_uuid, pid, tid, is_counter, category, 151 unit_multiplier, is_incremental, packet_sequence_id) == 152 std::tie(other.parent_uuid, pid, tid, is_counter, category, 153 unit_multiplier, is_incremental, packet_sequence_id); 154 } 155 }; 156 157 class ResolvedDescriptorTrack { 158 public: 159 enum class Scope { 160 kThread, 161 kProcess, 162 kGlobal, 163 }; 164 165 static ResolvedDescriptorTrack Process(UniquePid upid, 166 bool is_counter, 167 bool is_root); 168 static ResolvedDescriptorTrack Thread(UniqueTid utid, 169 bool is_counter, 170 bool is_root); 171 static ResolvedDescriptorTrack Global(bool is_counter, bool is_root); 172 scope()173 Scope scope() const { return scope_; } is_counter()174 bool is_counter() const { return is_counter_; } utid()175 UniqueTid utid() const { 176 PERFETTO_DCHECK(scope() == Scope::kThread); 177 return utid_; 178 } upid()179 UniquePid upid() const { 180 PERFETTO_DCHECK(scope() == Scope::kProcess); 181 return upid_; 182 } is_root_in_scope()183 UniqueTid is_root_in_scope() const { return is_root_in_scope_; } 184 185 private: 186 Scope scope_; 187 bool is_counter_; 188 bool is_root_in_scope_; 189 190 // Only set when |scope| == |Scope::kThread|. 191 UniqueTid utid_; 192 193 // Only set when |scope| == |Scope::kProcess|. 194 UniquePid upid_; 195 }; 196 197 base::Optional<TrackId> GetDescriptorTrackImpl(uint64_t uuid); 198 TrackId CreateTrackFromResolved(const ResolvedDescriptorTrack&); 199 base::Optional<ResolvedDescriptorTrack> ResolveDescriptorTrack( 200 uint64_t uuid, 201 std::vector<uint64_t>* descendent_uuids); 202 ResolvedDescriptorTrack ResolveDescriptorTrackImpl( 203 uint64_t uuid, 204 const DescriptorTrackReservation&, 205 std::vector<uint64_t>* descendent_uuids); 206 207 static constexpr uint64_t kDefaultDescriptorTrackUuid = 0u; 208 209 std::map<UniqueTid, TrackId> thread_tracks_; 210 std::map<UniquePid, TrackId> process_tracks_; 211 212 std::map<uint64_t /* uuid */, DescriptorTrackReservation> 213 reserved_descriptor_tracks_; 214 std::map<uint64_t /* uuid */, ResolvedDescriptorTrack> 215 resolved_descriptor_tracks_; 216 std::map<uint64_t /* uuid */, TrackId> descriptor_tracks_; 217 218 // Stores the descriptor uuid used for the primary process/thread track 219 // for the given upid / utid. Used for pid/tid reuse detection. 220 std::map<UniquePid, uint64_t /*uuid*/> descriptor_uuids_by_upid_; 221 std::map<UniqueTid, uint64_t /*uuid*/> descriptor_uuids_by_utid_; 222 223 const StringId source_key_ = kNullStringId; 224 const StringId source_id_key_ = kNullStringId; 225 const StringId is_root_in_scope_key_ = kNullStringId; 226 const StringId category_key_ = kNullStringId; 227 228 const StringId descriptor_source_ = kNullStringId; 229 230 const StringId default_descriptor_track_name_ = kNullStringId; 231 232 TraceProcessorContext* const context_; 233 }; 234 235 } // namespace trace_processor 236 } // namespace perfetto 237 238 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TRACKER_H_ 239