trace_processor: insert ftrace events into trace storage

This CL introduces the trace inserter class which correltates sched
switch events to compute durations using data in TraceStorage.
TraceParser utilises the inserter as an indirect way of inserting into
the trace storage.

Bug: 80416541
Change-Id: I26ac07a972994c067136c161b0b590f762a8df42
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index beb9e4f..3b62135 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -21,30 +21,56 @@
 namespace perfetto {
 namespace trace_processor {
 
-void TraceStorage::AddSliceForCpu(uint32_t cpu,
-                                  uint64_t start_timestamp,
-                                  uint64_t duration,
-                                  const char* thread_name) {
-  if (cpu_events_.size() <= cpu)
-    cpu_events_.resize(cpu + 1);
+TraceStorage::~TraceStorage() {}
 
-  SlicesPerCpu* slices = &cpu_events_[cpu];
-  slices->cpu_ = cpu;
-  slices->start_timestamps.emplace_back(start_timestamp);
-  slices->durations.emplace_back(duration);
+void TraceStorage::PushSchedSwitch(uint32_t cpu,
+                                   uint64_t timestamp,
+                                   uint32_t prev_pid,
+                                   uint32_t prev_state,
+                                   const char* prev_comm,
+                                   size_t prev_comm_len,
+                                   uint32_t next_pid) {
+  SchedSwitchEvent* prev = &last_sched_per_cpu_[cpu];
 
+  // If we had a valid previous event, then inform the storage about the
+  // slice.
+  if (prev->valid()) {
+    uint64_t duration = timestamp - prev->timestamp;
+    cpu_events_[cpu].AddSlice(prev->timestamp, duration, prev->prev_thread_id);
+  }
+
+  // If the this events previous pid does not match the previous event's next
+  // pid, make a note of this.
+  if (prev_pid != prev->next_pid) {
+    stats_.mismatched_sched_switch_tids_++;
+  }
+
+  // Update the map with the current event.
+  prev->cpu = cpu;
+  prev->timestamp = timestamp;
+  prev->prev_pid = prev_pid;
+  prev->prev_state = prev_state;
+  prev->prev_thread_id = InternString(prev_comm, prev_comm_len);
+  prev->next_pid = next_pid;
+}
+
+TraceStorage::StringId TraceStorage::InternString(const char* data,
+                                                  size_t length) {
   uint32_t hash = 0;
-  for (size_t i = 0; i < strlen(thread_name); ++i) {
-    hash = static_cast<uint32_t>(thread_name[i]) + (hash * 31);
+  for (uint64_t i = 0; i < length; ++i) {
+    hash = static_cast<uint32_t>(data[i]) + (hash * 31);
   }
-  auto id_it = string_pool_.find(hash);
-  if (id_it == string_pool_.end()) {
-    strings_.emplace_back(thread_name);
-    string_pool_.emplace(hash, strings_.size() - 1);
-    slices->thread_names.emplace_back(strings_.size() - 1);
-  } else {
-    slices->thread_names.emplace_back(id_it->second);
+  auto id_it = string_index_.find(hash);
+  if (id_it != string_index_.end()) {
+    // TODO(lalitm): check if this DCHECK happens and if so, then change hash
+    // to 64bit.
+    PERFETTO_DCHECK(string_pool_[id_it->second] == std::string(data, length));
+    return id_it->second;
   }
+  string_pool_.emplace_back(data, length);
+  StringId string_id = string_pool_.size() - 1;
+  string_index_.emplace(hash, string_id);
+  return string_id;
 }
 
 }  // namespace trace_processor