trace_processor: initial definition of columnar trace class

This class will form the common point which other classes will read
from/write to. It will be shared across the three virtual tables (event, thread
and process) and be read from.

Bug: 80416541
Change-Id: I9d431a98c2f4d7359338d55a03af09a04c01859e
diff --git a/BUILD.gn b/BUILD.gn
index 203b6fe..3faa1f1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -106,6 +106,9 @@
       "tools/sanitizers_unittests",
     ]
   }
+  if (build_standalone) {
+    deps += [ "src/trace_processor:unittests" ]
+  }
 }
 
 if (!build_with_chromium) {
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 3bc6b0a..2c70692 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -27,3 +27,25 @@
     "../../protos/perfetto/trace_processor:lite",
   ]
 }
+
+source_set("lib") {
+  sources = [
+    "trace_storage.cc",
+    "trace_storage.h",
+  ]
+  deps = [
+    "../../gn:default_deps",
+  ]
+}
+
+source_set("unittests") {
+  testonly = true
+  deps = [
+    ":lib",
+    "../../gn:default_deps",
+    "../../gn:gtest_deps",
+  ]
+  sources = [
+    "trace_storage_unittest.cc",
+  ]
+}
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
new file mode 100644
index 0000000..beb9e4f
--- /dev/null
+++ b/src/trace_processor/trace_storage.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include "src/trace_processor/trace_storage.h"
+
+#include <string.h>
+
+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);
+
+  SlicesPerCpu* slices = &cpu_events_[cpu];
+  slices->cpu_ = cpu;
+  slices->start_timestamps.emplace_back(start_timestamp);
+  slices->durations.emplace_back(duration);
+
+  uint32_t hash = 0;
+  for (size_t i = 0; i < strlen(thread_name); ++i) {
+    hash = static_cast<uint32_t>(thread_name[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);
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
new file mode 100644
index 0000000..ea2cdf1
--- /dev/null
+++ b/src/trace_processor/trace_storage.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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_STORAGE_H_
+#define SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
+
+#include <deque>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace perfetto {
+namespace trace_processor {
+
+// Stores a data inside a trace file in a columnar form. This makes it efficient
+// to read or search across a single field of the trace (e.g. all the thread
+// names for a given CPU).
+class TraceStorage {
+ public:
+  // Adds a sched slice for a given cpu.
+  void AddSliceForCpu(uint32_t cpu,
+                      uint64_t start_timestamp,
+                      uint64_t duration,
+                      const char* thread_name);
+
+  // Reading methods.
+  const std::deque<uint64_t>& start_timestamps_for_cpu(uint32_t cpu) {
+    return cpu_events_[cpu].start_timestamps;
+  }
+
+ private:
+  // Each StringId is an offset into |strings_|.
+  typedef size_t StringId;
+  typedef uint32_t StringHash;
+
+  struct SlicesPerCpu {
+    uint32_t cpu_ = 0;
+
+    // Each vector below has the same number of entries (the number of slices
+    // in the trace for the CPU).
+    std::deque<uint64_t> start_timestamps;
+    std::deque<uint64_t> durations;
+    std::deque<StringId> thread_names;
+  };
+
+  // One entry for each CPU in the trace.
+  std::vector<SlicesPerCpu> cpu_events_;
+
+  // One entry for each unique string in the trace.
+  std::deque<std::string> strings_;
+
+  // One entry for each unique string in the trace.
+  std::unordered_map<StringHash, StringId> string_pool_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
diff --git a/src/trace_processor/trace_storage_unittest.cc b/src/trace_processor/trace_storage_unittest.cc
new file mode 100644
index 0000000..4c98a93
--- /dev/null
+++ b/src/trace_processor/trace_storage_unittest.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 The Android Open foo 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.
+ */
+
+#include "src/trace_processor/trace_storage.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+
+TEST(TraceStorage, AddSliceForCpu) {
+  TraceStorage trace;
+  trace.AddSliceForCpu(2, 1000, 42, "test");
+  ASSERT_EQ(trace.start_timestamps_for_cpu(2)[0], 1000);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto