tp: switch track table to be a Python table

Change-Id: Ic40ccc427a5013e251909cf5ef21b81e40a61800
diff --git a/Android.bp b/Android.bp
index 4502a31..6ed4c87 100644
--- a/Android.bp
+++ b/Android.bp
@@ -10101,6 +10101,7 @@
     srcs: [
         "src/trace_processor/tables/android_tables.py",
         "src/trace_processor/tables/metadata_tables.py",
+        "src/trace_processor/tables/track_tables.py",
     ],
     tools: [
         "perfetto_src_trace_processor_tables_tables_python_binary",
@@ -10109,6 +10110,7 @@
     out: [
         "src/trace_processor/tables/android_tables_py.h",
         "src/trace_processor/tables/metadata_tables_py.h",
+        "src/trace_processor/tables/track_tables_py.h",
     ],
 }
 
@@ -10121,6 +10123,7 @@
         "python/generators/trace_processor_table/util.py",
         "src/trace_processor/tables/android_tables.py",
         "src/trace_processor/tables/metadata_tables.py",
+        "src/trace_processor/tables/track_tables.py",
         "tools/gen_tp_table_headers.py",
     ],
     main: "tools/gen_tp_table_headers.py",
diff --git a/BUILD b/BUILD
index 1d80406..877f5d9 100644
--- a/BUILD
+++ b/BUILD
@@ -1986,10 +1986,12 @@
     srcs = [
         "src/trace_processor/tables/android_tables.py",
         "src/trace_processor/tables/metadata_tables.py",
+        "src/trace_processor/tables/track_tables.py",
     ],
     outs = [
         "src/trace_processor/tables/android_tables_py.h",
         "src/trace_processor/tables/metadata_tables_py.h",
+        "src/trace_processor/tables/track_tables_py.h",
     ],
 )
 
diff --git a/python/generators/trace_processor_table/public.py b/python/generators/trace_processor_table/public.py
index 6b326e8..6d51877 100644
--- a/python/generators/trace_processor_table/public.py
+++ b/python/generators/trace_processor_table/public.py
@@ -124,15 +124,17 @@
     class_name: Name of the C++ table class.
     sql_name: Name of the table in SQL.
     columns: The columns in this table.
-    wrapping_sql_view: See |WrappingSqlView|.
     tabledoc: Documentation for this table. Can include
     documentation overrides for auto-added columns (i.e.
     id and type) and aliases added in |wrapping_sql_view|.
+    parent: The parent ("super-class") table for this table.
+    wrapping_sql_view: See |WrappingSqlView|.
   """
   class_name: str
   sql_name: str
   columns: List[Column]
   tabledoc: TableDoc
+  parent: Optional['Table'] = None
   wrapping_sql_view: Optional[WrappingSqlView] = None
 
 
@@ -152,6 +154,11 @@
 
 
 @dataclass
+class CppDouble(CppColumnType):
+  """Represents the double C++ type."""
+
+
+@dataclass
 class CppString(CppColumnType):
   """Represents the StringPool::Id C++ type."""
 
diff --git a/python/generators/trace_processor_table/serialize.py b/python/generators/trace_processor_table/serialize.py
index 43ca5cd..5b3cb92 100644
--- a/python/generators/trace_processor_table/serialize.py
+++ b/python/generators/trace_processor_table/serialize.py
@@ -56,6 +56,19 @@
       return None
     return f'{self.name}(std::move(in_{self.name}))'
 
+  def const_row_ref_getter(self) -> Optional[str]:
+    return f'''ColumnType::{self.name}::type {self.name}() const {{
+      return table_->{self.name}()[row_number_];
+    }}'''
+
+  def row_ref_getter(self) -> Optional[str]:
+    if self.col._is_auto_added_id or self.col._is_auto_added_type:
+      return None
+    return f'''void set_{self.name}(
+        ColumnType::{self.name}::non_optional_type v) {{
+      return mutable_table()->mutable_{self.name}()->Set(row_number_, v);
+    }}'''
+
   def flag(self) -> Optional[str]:
     if self.col._is_auto_added_id or self.col._is_auto_added_type:
       return None
@@ -155,7 +168,8 @@
         ColumnSerializer.row_initializer, delimiter=',\n          ')
     return f'''
   struct Row : public macros_internal::RootParentTable::Row {{
-    Row({param})
+    Row({param},
+        std::nullptr_t = nullptr)
         : macros_internal::RootParentTable::Row(nullptr),
           {row_init} {{
       type_ = "{self.table.sql_name}";
@@ -164,6 +178,42 @@
   }};
     '''
 
+  def const_row_reference_struct(self) -> str:
+    row_ref_getters = self.foreach_col(
+        ColumnSerializer.const_row_ref_getter, delimiter='\n    ')
+    return f'''
+  class ConstRowReference : public macros_internal::AbstractConstRowReference<
+    {self.table_name}, RowNumber> {{
+   public:
+    ConstRowReference(const {self.table_name}* table, uint32_t row_number)
+        : AbstractConstRowReference(table, row_number) {{}}
+
+    {row_ref_getters}
+  }};
+  static_assert(std::is_trivially_destructible<ConstRowReference>::value,
+                "Inheritance used without trivial destruction");
+    '''
+
+  def row_reference_struct(self) -> str:
+    row_ref_getters = self.foreach_col(
+        ColumnSerializer.row_ref_getter, delimiter='\n    ')
+    return f'''
+  class RowReference : public ConstRowReference {{
+   public:
+    RowReference(const {self.table_name}* table, uint32_t row_number)
+        : ConstRowReference(table, row_number) {{}}
+
+    {row_ref_getters}
+
+   private:
+    {self.table_name}* mutable_table() const {{
+      return const_cast<{self.table_name}*>(table_);
+    }}
+  }};
+  static_assert(std::is_trivially_destructible<RowReference>::value,
+                "Inheritance used without trivial destruction");
+    '''
+
   def constructor(self) -> str:
     col_init = self.foreach_col(
         ColumnSerializer.storage_init, delimiter=',\n        ')
@@ -190,11 +240,28 @@
   {self.row_struct().strip()}
   struct IdAndRow {{
     uint32_t row;
+    Id id;
   }};
   struct ColumnFlag {{
     {self.foreach_col(ColumnSerializer.flag)}
   }};
 
+  class RowNumber;
+  class ConstRowReference;
+  class RowReference;
+
+  class RowNumber : public macros_internal::AbstractRowNumber<
+      {self.table_name}, ConstRowReference, RowReference> {{
+   public:
+    explicit RowNumber(uint32_t row_number)
+        : AbstractRowNumber(row_number) {{}}
+  }};
+  static_assert(std::is_trivially_destructible<RowNumber>::value,
+                "Inheritance used without trivial destruction");
+
+  {self.const_row_reference_struct().strip()}
+  {self.row_reference_struct().strip()}
+
   {self.constructor().strip()}
   ~{self.table_name}() override;
 
@@ -204,12 +271,26 @@
     {self.foreach_col(ColumnSerializer.shrink_to_fit)}
   }}
 
+  base::Optional<ConstRowReference> FindById(Id find_id) const {{
+    base::Optional<uint32_t> row = id().IndexOf(find_id);
+    if (!row)
+      return base::nullopt;
+    return ConstRowReference(this, *row);
+  }}
+
+  base::Optional<RowReference> FindById(Id find_id) {{
+    base::Optional<uint32_t> row = id().IndexOf(find_id);
+    if (!row)
+      return base::nullopt;
+    return RowReference(this, *row);
+  }}
+
   IdAndRow Insert(const Row& row) {{
     uint32_t row_number = row_count();
     type_.Append(string_pool_->InternString(row.type()));
     {self.foreach_col(ColumnSerializer.append)}
     UpdateSelfOverlayAfterInsert();
-    return IdAndRow{{row_number}};
+    return IdAndRow{{row_number, Id{{row_number}}}};
   }}
 
   {self.foreach_col(ColumnSerializer.accessor)}
diff --git a/src/trace_processor/storage/trace_storage.h b/src/trace_processor/storage/trace_storage.h
index 325f3b0..5790beb 100644
--- a/src/trace_processor/storage/trace_storage.h
+++ b/src/trace_processor/storage/trace_storage.h
@@ -828,7 +828,7 @@
   tables::ClockSnapshotTable clock_snapshot_table_{&string_pool_, nullptr};
 
   // Metadata for tracks.
-  tables::TrackTable track_table_{&string_pool_, nullptr};
+  tables::TrackTable track_table_{&string_pool_};
   tables::ThreadStateTable thread_state_table_{&string_pool_, nullptr};
   tables::GpuTrackTable gpu_track_table_{&string_pool_, &track_table_};
   tables::ProcessTrackTable process_track_table_{&string_pool_, &track_table_};
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index dfa7781..955fbc1 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -19,6 +19,7 @@
   sources = [
     "android_tables.py",
     "metadata_tables.py",
+    "track_tables.py",
   ]
   generate_docs = true
 }
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index a517101..bc22a9a 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -34,8 +34,6 @@
 // @param private_dirty_kb KB of this mapping that are private dirty  RSS.
 // @param swap_kb KB of this mapping that are in swap.
 // @param file_name
-// @param file_name_iid
-// @param path_iid
 // @param start_address
 // @param module_timestamp
 // @param module_debugid
@@ -159,9 +157,7 @@
 PERFETTO_TP_TABLE(PERFETTO_TP_STACK_SAMPLE_DEF);
 
 // Samples from the Chromium stack sampler.
-// @param ts timestamp this sample was taken at.
 // @param utid thread that was active when the sample was taken.
-// @param callsite_id callstack in active thread at time of sample.
 // @tablegroup Callstack profilers
 #define PERFETTO_TP_CPU_PROFILE_STACK_SAMPLE_DEF(NAME, PARENT, C) \
   NAME(CpuProfileStackSampleTable, "cpu_profile_stack_sample")    \
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
index ed24ef2..60c515a 100644
--- a/src/trace_processor/tables/track_tables.h
+++ b/src/trace_processor/tables/track_tables.h
@@ -18,23 +18,19 @@
 #define SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
 
 #include "src/trace_processor/tables/macros.h"
+#include "src/trace_processor/tables/track_tables_py.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace tables {
 
-// @tablegroup Tracks
-// @param source_arg_set_id {@joinable args.arg_set_id}
-// @param parent_id id of a parent track {@joinable track.id}
+// TODO(lalitm): delete this once none of the child classes depends on this.
 #define PERFETTO_TP_TRACK_TABLE_DEF(NAME, PARENT, C) \
-  NAME(TrackTable, "track")                          \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                  \
+  NAME(TrackTable, "unused")                         \
   C(StringPool::Id, name)                            \
   C(base::Optional<TrackTable::Id>, parent_id)       \
   C(base::Optional<uint32_t>, source_arg_set_id)
 
-PERFETTO_TP_TABLE(PERFETTO_TP_TRACK_TABLE_DEF);
-
 // @tablegroup Tracks
 #define PERFETTO_TP_PROCESS_TRACK_TABLE_DEF(NAME, PARENT, C) \
   NAME(ProcessTrackTable, "process_track")                   \
diff --git a/src/trace_processor/tables/track_tables.py b/src/trace_processor/tables/track_tables.py
new file mode 100644
index 0000000..38555d1
--- /dev/null
+++ b/src/trace_processor/tables/track_tables.py
@@ -0,0 +1,67 @@
+# Copyright (C) 2022 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.
+"""Contains tables for tracks."""
+
+from python.generators.trace_processor_table.public import Column as C
+from python.generators.trace_processor_table.public import CppInt64
+from python.generators.trace_processor_table.public import CppOptional
+from python.generators.trace_processor_table.public import CppString
+from python.generators.trace_processor_table.public import Table
+from python.generators.trace_processor_table.public import TableDoc
+from python.generators.trace_processor_table.public import ColumnDoc
+from python.generators.trace_processor_table.public import CppSelfTableId
+from python.generators.trace_processor_table.public import CppUint32
+from src.trace_processor.tables.metadata_tables import THREAD_TABLE
+
+TRACK_TABLE = Table(
+    class_name="TrackTable",
+    sql_name="track",
+    columns=[
+        C("name", CppString()),
+        C("parent_id", CppOptional(CppSelfTableId())),
+        C("source_arg_set_id", CppOptional(CppUint32())),
+    ],
+    tabledoc=TableDoc(
+        doc='''
+          Tracks are a fundamental concept in trace processor and represent a
+          "timeline" for events of the same type and with the same context. See
+          https://perfetto.dev/docs/analysis/trace-processor#tracks for a more
+          detailed explanation, with examples.
+        ''',
+        group='Tracks',
+        columns={
+            'name':
+                '''
+                  Name of the track; can be null for some types of tracks (e.g.
+                  thread tracks).
+                ''',
+            'parent_id':
+                '''
+                  The track which is the "parent" of this track. Only non-null
+                  for tracks created using Perfetto's track_event API.
+                ''',
+            'source_arg_set_id':
+                ColumnDoc(
+                    doc='''
+                      Args for this track which store information about "source"
+                      of this track in the trace. For example: whether this
+                      track orginated from atrace, Chrome tracepoints etc.
+                    ''',
+                    joinable='args.arg_set_id'),
+        }))
+
+# Keep this list sorted.
+ALL_TABLES = [
+    TRACK_TABLE,
+]