1 /*
2  * Copyright (C) 2019 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 #include "src/trace_processor/importers/common/track_tracker.h"
18 
19 #include "src/trace_processor/importers/common/args_tracker.h"
20 #include "src/trace_processor/importers/common/process_tracker.h"
21 
22 namespace perfetto {
23 namespace trace_processor {
24 
TrackTracker(TraceProcessorContext * context)25 TrackTracker::TrackTracker(TraceProcessorContext* context)
26     : source_key_(context->storage->InternString("source")),
27       source_id_key_(context->storage->InternString("source_id")),
28       source_id_is_process_scoped_key_(
29           context->storage->InternString("source_id_is_process_scoped")),
30       source_scope_key_(context->storage->InternString("source_scope")),
31       category_key_(context->storage->InternString("category")),
32       fuchsia_source_(context->storage->InternString("fuchsia")),
33       chrome_source_(context->storage->InternString("chrome")),
34       android_source_(context->storage->InternString("android")),
35       context_(context) {}
36 
InternThreadTrack(UniqueTid utid)37 TrackId TrackTracker::InternThreadTrack(UniqueTid utid) {
38   auto it = thread_tracks_.find(utid);
39   if (it != thread_tracks_.end())
40     return it->second;
41 
42   tables::ThreadTrackTable::Row row;
43   row.utid = utid;
44   auto id = context_->storage->mutable_thread_track_table()->Insert(row).id;
45   thread_tracks_[utid] = id;
46   return id;
47 }
48 
InternProcessTrack(UniquePid upid)49 TrackId TrackTracker::InternProcessTrack(UniquePid upid) {
50   auto it = process_tracks_.find(upid);
51   if (it != process_tracks_.end())
52     return it->second;
53 
54   tables::ProcessTrackTable::Row row;
55   row.upid = upid;
56   auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
57   process_tracks_[upid] = id;
58   return id;
59 }
60 
InternFuchsiaAsyncTrack(StringId name,uint32_t upid,int64_t correlation_id)61 TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
62                                               uint32_t upid,
63                                               int64_t correlation_id) {
64   return InternLegacyChromeAsyncTrack(name, upid, correlation_id, false,
65                                       StringId());
66 }
67 
InternCpuTrack(StringId name,uint32_t cpu)68 TrackId TrackTracker::InternCpuTrack(StringId name, uint32_t cpu) {
69   auto it = cpu_tracks_.find(std::make_pair(name, cpu));
70   if (it != cpu_tracks_.end()) {
71     return it->second;
72   }
73 
74   tables::TrackTable::Row row(name);
75   auto id = context_->storage->mutable_track_table()->Insert(row).id;
76   cpu_tracks_[std::make_pair(name, cpu)] = id;
77 
78   return id;
79 }
80 
InternGpuTrack(const tables::GpuTrackTable::Row & row)81 TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
82   GpuTrackTuple tuple{row.name, row.scope, row.context_id.value_or(0)};
83 
84   auto it = gpu_tracks_.find(tuple);
85   if (it != gpu_tracks_.end())
86     return it->second;
87 
88   auto id = context_->storage->mutable_gpu_track_table()->Insert(row).id;
89   gpu_tracks_[tuple] = id;
90   return id;
91 }
92 
InternLegacyChromeAsyncTrack(StringId name,uint32_t upid,int64_t source_id,bool source_id_is_process_scoped,StringId source_scope)93 TrackId TrackTracker::InternLegacyChromeAsyncTrack(
94     StringId name,
95     uint32_t upid,
96     int64_t source_id,
97     bool source_id_is_process_scoped,
98     StringId source_scope) {
99   ChromeTrackTuple tuple;
100   if (source_id_is_process_scoped)
101     tuple.upid = upid;
102   tuple.source_id = source_id;
103   tuple.source_scope = source_scope;
104 
105   auto it = chrome_tracks_.find(tuple);
106   if (it != chrome_tracks_.end()) {
107     if (name != kNullStringId) {
108       // The track may have been created for an end event without name. In that
109       // case, update it with this event's name.
110       auto* tracks = context_->storage->mutable_track_table();
111       uint32_t track_row = *tracks->id().IndexOf(it->second);
112       if (tracks->name()[track_row] == kNullStringId)
113         tracks->mutable_name()->Set(track_row, name);
114     }
115     return it->second;
116   }
117 
118   // Legacy async tracks are always drawn in the context of a process, even if
119   // the ID's scope is global.
120   tables::ProcessTrackTable::Row track(name);
121   track.upid = upid;
122   TrackId id =
123       context_->storage->mutable_process_track_table()->Insert(track).id;
124   chrome_tracks_[tuple] = id;
125 
126   context_->args_tracker->AddArgsTo(id)
127       .AddArg(source_key_, Variadic::String(chrome_source_))
128       .AddArg(source_id_key_, Variadic::Integer(source_id))
129       .AddArg(source_id_is_process_scoped_key_,
130               Variadic::Boolean(source_id_is_process_scoped))
131       .AddArg(source_scope_key_, Variadic::String(source_scope));
132 
133   return id;
134 }
135 
CreateGlobalAsyncTrack(StringId name)136 TrackId TrackTracker::CreateGlobalAsyncTrack(StringId name) {
137   tables::TrackTable::Row row(name);
138   auto id = context_->storage->mutable_track_table()->Insert(row).id;
139   return id;
140 }
141 
CreateAndroidAsyncTrack(StringId name,UniquePid upid)142 TrackId TrackTracker::CreateAndroidAsyncTrack(StringId name, UniquePid upid) {
143   tables::ProcessTrackTable::Row row(name);
144   row.upid = upid;
145   auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
146   context_->args_tracker->AddArgsTo(id).AddArg(
147       source_key_, Variadic::String(android_source_));
148   return id;
149 }
150 
CreateFrameTimelineAsyncTrack(StringId name,UniquePid upid)151 TrackId TrackTracker::CreateFrameTimelineAsyncTrack(StringId name,
152                                                     UniquePid upid) {
153   tables::ProcessTrackTable::Row row(name);
154   row.upid = upid;
155   return context_->storage->mutable_process_track_table()->Insert(row).id;
156 }
157 
InternLegacyChromeProcessInstantTrack(UniquePid upid)158 TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
159   auto it = chrome_process_instant_tracks_.find(upid);
160   if (it != chrome_process_instant_tracks_.end())
161     return it->second;
162 
163   tables::ProcessTrackTable::Row row;
164   row.upid = upid;
165   auto id = context_->storage->mutable_process_track_table()->Insert(row).id;
166   chrome_process_instant_tracks_[upid] = id;
167 
168   context_->args_tracker->AddArgsTo(id).AddArg(
169       source_key_, Variadic::String(chrome_source_));
170 
171   return id;
172 }
173 
GetOrCreateLegacyChromeGlobalInstantTrack()174 TrackId TrackTracker::GetOrCreateLegacyChromeGlobalInstantTrack() {
175   if (!chrome_global_instant_track_id_) {
176     chrome_global_instant_track_id_ =
177         context_->storage->mutable_track_table()->Insert({}).id;
178 
179     context_->args_tracker->AddArgsTo(*chrome_global_instant_track_id_)
180         .AddArg(source_key_, Variadic::String(chrome_source_));
181   }
182   return *chrome_global_instant_track_id_;
183 }
184 
GetOrCreateTriggerTrack()185 TrackId TrackTracker::GetOrCreateTriggerTrack() {
186   if (trigger_track_id_) {
187     return *trigger_track_id_;
188   }
189   tables::TrackTable::Row row;
190   row.name = context_->storage->InternString("Trace Triggers");
191   trigger_track_id_ = context_->storage->mutable_track_table()->Insert(row).id;
192   return *trigger_track_id_;
193 }
194 
InternGlobalCounterTrack(StringId name,StringId unit,StringId description)195 TrackId TrackTracker::InternGlobalCounterTrack(StringId name,
196                                                StringId unit,
197                                                StringId description) {
198   auto it = global_counter_tracks_by_name_.find(name);
199   if (it != global_counter_tracks_by_name_.end()) {
200     return it->second;
201   }
202 
203   tables::CounterTrackTable::Row row(name);
204   row.unit = unit;
205   row.description = description;
206   TrackId track =
207       context_->storage->mutable_counter_track_table()->Insert(row).id;
208   global_counter_tracks_by_name_[name] = track;
209   return track;
210 }
211 
InternCpuCounterTrack(StringId name,uint32_t cpu)212 TrackId TrackTracker::InternCpuCounterTrack(StringId name, uint32_t cpu) {
213   auto it = cpu_counter_tracks_.find(std::make_pair(name, cpu));
214   if (it != cpu_counter_tracks_.end()) {
215     return it->second;
216   }
217 
218   tables::CpuCounterTrackTable::Row row(name);
219   row.cpu = cpu;
220 
221   TrackId track =
222       context_->storage->mutable_cpu_counter_track_table()->Insert(row).id;
223   cpu_counter_tracks_[std::make_pair(name, cpu)] = track;
224   return track;
225 }
226 
InternThreadCounterTrack(StringId name,UniqueTid utid)227 TrackId TrackTracker::InternThreadCounterTrack(StringId name, UniqueTid utid) {
228   auto it = utid_counter_tracks_.find(std::make_pair(name, utid));
229   if (it != utid_counter_tracks_.end()) {
230     return it->second;
231   }
232 
233   tables::ThreadCounterTrackTable::Row row(name);
234   row.utid = utid;
235 
236   TrackId track =
237       context_->storage->mutable_thread_counter_track_table()->Insert(row).id;
238   utid_counter_tracks_[std::make_pair(name, utid)] = track;
239   return track;
240 }
241 
InternProcessCounterTrack(StringId name,UniquePid upid,StringId unit,StringId description)242 TrackId TrackTracker::InternProcessCounterTrack(StringId name,
243                                                 UniquePid upid,
244                                                 StringId unit,
245                                                 StringId description) {
246   auto it = upid_counter_tracks_.find(std::make_pair(name, upid));
247   if (it != upid_counter_tracks_.end()) {
248     return it->second;
249   }
250 
251   tables::ProcessCounterTrackTable::Row row(name);
252   row.upid = upid;
253   row.unit = unit;
254   row.description = description;
255 
256   TrackId track =
257       context_->storage->mutable_process_counter_track_table()->Insert(row).id;
258   upid_counter_tracks_[std::make_pair(name, upid)] = track;
259   return track;
260 }
261 
InternIrqCounterTrack(StringId name,int32_t irq)262 TrackId TrackTracker::InternIrqCounterTrack(StringId name, int32_t irq) {
263   auto it = irq_counter_tracks_.find(std::make_pair(name, irq));
264   if (it != irq_counter_tracks_.end()) {
265     return it->second;
266   }
267 
268   tables::IrqCounterTrackTable::Row row(name);
269   row.irq = irq;
270 
271   TrackId track =
272       context_->storage->mutable_irq_counter_track_table()->Insert(row).id;
273   irq_counter_tracks_[std::make_pair(name, irq)] = track;
274   return track;
275 }
276 
InternSoftirqCounterTrack(StringId name,int32_t softirq)277 TrackId TrackTracker::InternSoftirqCounterTrack(StringId name,
278                                                 int32_t softirq) {
279   auto it = softirq_counter_tracks_.find(std::make_pair(name, softirq));
280   if (it != softirq_counter_tracks_.end()) {
281     return it->second;
282   }
283 
284   tables::SoftirqCounterTrackTable::Row row(name);
285   row.softirq = softirq;
286 
287   TrackId track =
288       context_->storage->mutable_softirq_counter_track_table()->Insert(row).id;
289   softirq_counter_tracks_[std::make_pair(name, softirq)] = track;
290   return track;
291 }
292 
InternGpuCounterTrack(StringId name,uint32_t gpu_id)293 TrackId TrackTracker::InternGpuCounterTrack(StringId name, uint32_t gpu_id) {
294   auto it = gpu_counter_tracks_.find(std::make_pair(name, gpu_id));
295   if (it != gpu_counter_tracks_.end()) {
296     return it->second;
297   }
298   TrackId track = CreateGpuCounterTrack(name, gpu_id);
299   gpu_counter_tracks_[std::make_pair(name, gpu_id)] = track;
300   return track;
301 }
302 
CreateGpuCounterTrack(StringId name,uint32_t gpu_id,StringId description,StringId unit)303 TrackId TrackTracker::CreateGpuCounterTrack(StringId name,
304                                             uint32_t gpu_id,
305                                             StringId description,
306                                             StringId unit) {
307   tables::GpuCounterTrackTable::Row row(name);
308   row.gpu_id = gpu_id;
309   row.description = description;
310   row.unit = unit;
311 
312   return context_->storage->mutable_gpu_counter_track_table()->Insert(row).id;
313 }
314 
CreatePerfCounterTrack(StringId name,uint32_t perf_session_id,uint32_t cpu,bool is_timebase)315 TrackId TrackTracker::CreatePerfCounterTrack(StringId name,
316                                              uint32_t perf_session_id,
317                                              uint32_t cpu,
318                                              bool is_timebase) {
319   tables::PerfCounterTrackTable::Row row(name);
320   row.perf_session_id = perf_session_id;
321   row.cpu = cpu;
322   row.is_timebase = is_timebase;
323   return context_->storage->mutable_perf_counter_track_table()->Insert(row).id;
324 }
325 
326 }  // namespace trace_processor
327 }  // namespace perfetto
328