• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from typing import List
16from typing import Optional
17
18from python.generators.trace_processor_table.public import Alias
19from python.generators.trace_processor_table.public import ColumnFlag
20from python.generators.trace_processor_table.util import ParsedTable
21from python.generators.trace_processor_table.util import ParsedColumn
22from python.generators.trace_processor_table.util import parse_type
23from python.generators.trace_processor_table.util import typed_column_type
24
25
26class ColumnSerializer:
27  """Functions for serializing a single Column in a table into C++."""
28
29  def __init__(self, table: ParsedTable, column: ParsedColumn, col_index: int):
30    self.col_index = col_index
31    self.parsed_col = column
32    self.col = self.parsed_col.column
33    self.name = self.col.name
34    self.flags = self.col.flags
35    self.typed_column_type = typed_column_type(table.table, self.parsed_col)
36    self.cpp_type = parse_type(table.table,
37                               self.col.type).cpp_type_with_optionality()
38
39    self.is_implicit_id = self.parsed_col.is_implicit_id
40    self.is_implicit_type = self.parsed_col.is_implicit_type
41    self.is_ancestor = self.parsed_col.is_ancestor
42
43  def colindex(self) -> str:
44    return f'    static constexpr uint32_t {self.name} = {self.col_index};'
45
46  def coltype_enum(self) -> str:
47    return f'    using {self.name} = {self.typed_column_type};'
48
49  def row_field(self) -> Optional[str]:
50    if self.is_implicit_id or self.is_implicit_type:
51      return None
52    if self.is_ancestor:
53      return None
54    return f'    {self.cpp_type} {self.name};'
55
56  def row_param(self) -> Optional[str]:
57    if self.is_implicit_id or self.is_implicit_type:
58      return None
59    return f'{self.cpp_type} in_{self.name} = {{}}'
60
61  def parent_row_initializer(self) -> Optional[str]:
62    if self.is_implicit_id or self.is_implicit_type:
63      return None
64    if not self.is_ancestor:
65      return None
66    return f'std::move(in_{self.name})'
67
68  def row_initializer(self) -> Optional[str]:
69    if self.is_implicit_id or self.is_implicit_type:
70      return None
71    if self.is_ancestor:
72      return None
73    return f'{self.name}(std::move(in_{self.name}))'
74
75  def const_row_ref_getter(self) -> Optional[str]:
76    return f'''ColumnType::{self.name}::type {self.name}() const {{
77      return table_->{self.name}()[row_number_];
78    }}'''
79
80  def row_ref_getter(self) -> Optional[str]:
81    if self.is_implicit_id or self.is_implicit_type:
82      return None
83    return f'''void set_{self.name}(
84        ColumnType::{self.name}::non_optional_type v) {{
85      return mutable_table()->mutable_{self.name}()->Set(row_number_, v);
86    }}'''
87
88  def flag(self) -> Optional[str]:
89    if self.is_implicit_id or self.is_implicit_type:
90      return None
91    if self.is_ancestor:
92      return None
93    default = f'ColumnType::{self.name}::default_flags()'
94    if self.flags == ColumnFlag.NONE:
95      flags = default
96    else:
97      flags = f'static_cast<uint32_t>({to_cpp_flags(self.flags)}) | {default}'
98    return f'''
99    static constexpr uint32_t {self.name} = {flags};
100    '''
101
102  def storage_init(self) -> Optional[str]:
103    if self.is_implicit_id or self.is_implicit_type:
104      return None
105    if self.is_ancestor:
106      return None
107
108    storage = f'ColumnStorage<ColumnType::{self.name}::stored_type>'
109    dense = str(ColumnFlag.DENSE in self.flags).lower()
110    return f'''{self.name}_({storage}::Create<{dense}>())'''
111
112  def column_init(self) -> Optional[str]:
113    if self.is_implicit_id or self.is_implicit_type:
114      return None
115    if self.is_ancestor:
116      return None
117    return f'''
118    columns_.emplace_back("{self.name}", &{self.name}_, ColumnFlag::{self.name},
119                          this, static_cast<uint32_t>(columns_.size()),
120                          olay_idx);
121    '''
122
123  def shrink_to_fit(self) -> Optional[str]:
124    if self.is_implicit_id:
125      return None
126    if self.is_ancestor:
127      return None
128    return f'    {self.name}_.ShrinkToFit();'
129
130  def append(self) -> Optional[str]:
131    if self.is_implicit_id or self.is_implicit_type:
132      return None
133    if self.is_ancestor:
134      return None
135    return f'    mutable_{self.name}()->Append(std::move(row.{self.name}));'
136
137  def accessor(self) -> Optional[str]:
138    inner = f'columns_[ColumnIndex::{self.name}]'
139    return f'''
140  const {self.typed_column_type}& {self.name}() const {{
141    return static_cast<const ColumnType::{self.name}&>({inner});
142  }}
143  '''
144
145  def mutable_accessor(self) -> Optional[str]:
146    if self.is_implicit_id or self.is_implicit_type:
147      return None
148    return f'''
149  {self.typed_column_type}* mutable_{self.name}() {{
150    return static_cast<ColumnType::{self.name}*>(
151        &columns_[ColumnIndex::{self.name}]);
152  }}
153  '''
154
155  def storage(self) -> Optional[str]:
156    if self.is_implicit_id or self.is_implicit_type:
157      return None
158    if self.is_ancestor:
159      return None
160    name = self.name
161    return f'  ColumnStorage<ColumnType::{name}::stored_type> {name}_;'
162
163  def iterator_getter(self) -> Optional[str]:
164    name = self.name
165    return f'''
166    ColumnType::{self.name}::type {name}() const {{
167      const auto& col = table_->{name}();
168      return col.GetAtIdx(its_[col.overlay_index()].index());
169    }}
170    '''
171
172  def iterator_setter(self) -> Optional[str]:
173    if self.is_implicit_id or self.is_implicit_type:
174      return None
175    return f'''
176      void set_{self.name}(ColumnType::{self.name}::non_optional_type v) {{
177        auto* col = mutable_table_->mutable_{self.name}();
178        col->SetAtIdx(its_[col->overlay_index()].index(), v);
179      }}
180    '''
181
182  def static_schema(self) -> Optional[str]:
183    if self.is_implicit_id or self.is_implicit_type:
184      return None
185    return f'''
186    schema.columns.emplace_back(Table::Schema::Column{{
187        "{self.name}", ColumnType::{self.name}::SqlValueType(), false,
188        {str(ColumnFlag.SORTED in self.flags).lower()},
189        {str(ColumnFlag.HIDDEN in self.flags).lower()},
190        {str(ColumnFlag.SET_ID in self.flags).lower()}}});
191    '''
192
193  def row_eq(self) -> Optional[str]:
194    if self.is_implicit_id or self.is_implicit_type:
195      return None
196    return f'ColumnType::{self.name}::Equals({self.name}, other.{self.name})'
197
198  def extend_parent_param(self) -> Optional[str]:
199    if self.is_implicit_id or self.is_implicit_type:
200      return None
201    if self.is_ancestor:
202      return None
203    return f'ColumnStorage<ColumnType::{self.name}::stored_type> {self.name}'
204
205  def extend_parent_param_arg(self) -> Optional[str]:
206    if self.is_implicit_id or self.is_implicit_type:
207      return None
208    if self.is_ancestor:
209      return None
210    return f'std::move({self.name})'
211
212  def static_assert_flags(self) -> Optional[str]:
213    if self.is_implicit_id or self.is_implicit_type:
214      return None
215    if self.is_ancestor:
216      return None
217    return f'''
218      static_assert(
219        Column::IsFlagsAndTypeValid<ColumnType::{self.name}::stored_type>(
220          ColumnFlag::{self.name}),
221        "Column type and flag combination is not valid");
222    '''
223
224  def extend_nullable_vector(self) -> Optional[str]:
225    if self.is_implicit_id or self.is_implicit_type:
226      return None
227    if self.is_ancestor:
228      return None
229    return f'''
230    PERFETTO_DCHECK({self.name}.size() == parent_overlay.size());
231    {self.name}_ = std::move({self.name});
232    '''
233
234
235class TableSerializer(object):
236  """Functions for seralizing a single Table into C++."""
237
238  def __init__(self, parsed: ParsedTable):
239    self.table = parsed.table
240    self.table_name = parsed.table.class_name
241    self.column_serializers = []
242
243    if parsed.table.parent:
244      self.parent_class_name = parsed.table.parent.class_name
245    else:
246      self.parent_class_name = 'macros_internal::RootParentTable'
247
248    self.column_serializers = []
249    for c in parsed.columns:
250      # Aliases should be ignored as they are handled in SQL currently.
251      if isinstance(c.column.type, Alias):
252        continue
253      self.column_serializers.append(
254          ColumnSerializer(parsed, c, len(self.column_serializers)))
255
256  def foreach_col(self, serialize_fn, delimiter='\n') -> str:
257    lines = []
258    for c in self.column_serializers:
259      serialized = serialize_fn(c)
260      if serialized:
261        lines.append(serialized.lstrip('\n').rstrip())
262    return delimiter.join(lines).strip()
263
264  def id_defn(self) -> str:
265    if self.table.parent:
266      return f'''
267  using Id = {self.table.parent.class_name}::Id;
268    '''
269    return '''
270  struct Id : public BaseId {
271    Id() = default;
272    explicit constexpr Id(uint32_t v) : BaseId(v) {}
273  };
274  static_assert(std::is_trivially_destructible<Id>::value,
275                "Inheritance used without trivial destruction");
276    '''
277
278  def row_struct(self) -> str:
279    param = self.foreach_col(
280        ColumnSerializer.row_param, delimiter=',\n        ')
281    parent_row_init = self.foreach_col(
282        ColumnSerializer.parent_row_initializer, delimiter=', ')
283    row_init = self.foreach_col(
284        ColumnSerializer.row_initializer, delimiter=',\n          ')
285    parent_separator = ',' if row_init else ''
286    row_eq = self.foreach_col(ColumnSerializer.row_eq, delimiter=' &&\n       ')
287    return f'''
288  struct Row : public {self.parent_class_name}::Row {{
289    Row({param},
290        std::nullptr_t = nullptr)
291        : {self.parent_class_name}::Row({parent_row_init}){parent_separator}
292          {row_init} {{
293      type_ = "{self.table.sql_name}";
294    }}
295    {self.foreach_col(ColumnSerializer.row_field)}
296
297    bool operator==(const {self.table_name}::Row& other) const {{
298      return type() == other.type() && {row_eq};
299    }}
300  }};
301    '''
302
303  def const_row_reference_struct(self) -> str:
304    row_ref_getters = self.foreach_col(
305        ColumnSerializer.const_row_ref_getter, delimiter='\n    ')
306    return f'''
307  class ConstRowReference : public macros_internal::AbstractConstRowReference<
308    {self.table_name}, RowNumber> {{
309   public:
310    ConstRowReference(const {self.table_name}* table, uint32_t row_number)
311        : AbstractConstRowReference(table, row_number) {{}}
312
313    {row_ref_getters}
314  }};
315  static_assert(std::is_trivially_destructible<ConstRowReference>::value,
316                "Inheritance used without trivial destruction");
317    '''
318
319  def row_reference_struct(self) -> str:
320    row_ref_getters = self.foreach_col(
321        ColumnSerializer.row_ref_getter, delimiter='\n    ')
322    return f'''
323  class RowReference : public ConstRowReference {{
324   public:
325    RowReference(const {self.table_name}* table, uint32_t row_number)
326        : ConstRowReference(table, row_number) {{}}
327
328    {row_ref_getters}
329
330   private:
331    {self.table_name}* mutable_table() const {{
332      return const_cast<{self.table_name}*>(table_);
333    }}
334  }};
335  static_assert(std::is_trivially_destructible<RowReference>::value,
336                "Inheritance used without trivial destruction");
337    '''
338
339  def constructor(self) -> str:
340    storage_init = self.foreach_col(
341        ColumnSerializer.storage_init, delimiter=',\n        ')
342    if self.table.parent:
343      parent_param = f', {self.parent_class_name}* parent'
344      parent_arg = 'parent'
345      parent_init = 'parent_(parent)' + (', ' if storage_init else '')
346    else:
347      parent_param = ''
348      parent_arg = 'nullptr'
349      parent_init = ''
350    col_init = self.foreach_col(ColumnSerializer.column_init)
351    if col_init:
352      olay = 'uint32_t olay_idx = static_cast<uint32_t>(overlays_.size()) - 1;'
353    else:
354      olay = ''
355    return f'''
356  explicit {self.table_name}(StringPool* pool{parent_param})
357      : macros_internal::MacroTable(pool, {parent_arg}),
358        {parent_init}{storage_init} {{
359    {self.foreach_col(ColumnSerializer.static_assert_flags)}
360    {olay}
361    {col_init}
362  }}
363    '''
364
365  def parent_field(self) -> str:
366    if self.table.parent:
367      return f'''
368  {self.parent_class_name}* parent_ = nullptr;
369      '''
370    return ''
371
372  def insert_common(self) -> str:
373    if self.table.parent:
374      return '''
375    Id id = Id{parent_->Insert(row).id};
376    UpdateOverlaysAfterParentInsert();
377      '''
378    return '''
379    Id id = Id{row_number};
380    type_.Append(string_pool_->InternString(row.type()));
381      '''
382
383  def const_iterator(self) -> str:
384    iterator_getters = self.foreach_col(
385        ColumnSerializer.iterator_getter, delimiter='\n')
386    return f'''
387  class ConstIterator;
388  class ConstIterator : public macros_internal::AbstractConstIterator<
389    ConstIterator, {self.table_name}, RowNumber, ConstRowReference> {{
390   public:
391    {iterator_getters}
392
393   protected:
394    explicit ConstIterator(const {self.table_name}* table,
395                           std::vector<ColumnStorageOverlay> overlays)
396        : AbstractConstIterator(table, std::move(overlays)) {{}}
397
398    uint32_t CurrentRowNumber() const {{
399      return its_.back().index();
400    }}
401
402   private:
403    friend class {self.table_name};
404    friend class AbstractConstIterator;
405  }};
406      '''
407
408  def iterator(self) -> str:
409    iterator_setters = self.foreach_col(
410        ColumnSerializer.iterator_setter, delimiter='\n')
411    return f'''
412  class Iterator : public ConstIterator {{
413    public:
414    {iterator_setters}
415
416    RowReference row_reference() const {{
417      return RowReference(mutable_table_, CurrentRowNumber());
418    }}
419
420    private:
421    friend class {self.table_name};
422
423    explicit Iterator({self.table_name}* table,
424                      std::vector<ColumnStorageOverlay> overlays)
425        : ConstIterator(table, std::move(overlays)),
426          mutable_table_(table) {{}}
427
428    {self.table_name}* mutable_table_ = nullptr;
429  }};
430      '''
431
432  def extend(self) -> str:
433    if not self.table.parent:
434      return ''
435    params = self.foreach_col(
436        ColumnSerializer.extend_parent_param, delimiter='\n, ')
437    args = self.foreach_col(
438        ColumnSerializer.extend_parent_param_arg, delimiter=', ')
439    delim = ',' if params else ''
440    return f'''
441  static std::unique_ptr<Table> ExtendParent(
442      const {self.parent_class_name}& parent{delim}
443      {params}) {{
444    return std::unique_ptr<Table>(new {self.table_name}(
445        parent.string_pool(), parent, RowMap(0, parent.row_count()){delim}
446        {args}));
447  }}
448
449  static std::unique_ptr<Table> SelectAndExtendParent(
450      const {self.parent_class_name}& parent,
451      std::vector<{self.parent_class_name}::RowNumber> parent_overlay{delim}
452      {params}) {{
453    std::vector<uint32_t> prs_untyped(parent_overlay.size());
454    for (uint32_t i = 0; i < parent_overlay.size(); ++i) {{
455      prs_untyped[i] = parent_overlay[i].row_number();
456    }}
457    return std::unique_ptr<Table>(new {self.table_name}(
458        parent.string_pool(), parent, RowMap(std::move(prs_untyped)){delim}
459        {args}));
460  }}
461    '''
462
463  def extend_constructor(self) -> str:
464    if not self.table.parent:
465      return ''
466    params = self.foreach_col(
467        ColumnSerializer.extend_parent_param, delimiter='\n, ')
468    if params:
469      olay = 'uint32_t olay_idx = static_cast<uint32_t>(overlays_.size()) - 1;'
470    else:
471      olay = ''
472    return f'''
473  {self.table_name}(StringPool* pool,
474            const {self.parent_class_name}& parent,
475            const RowMap& parent_overlay{',' if params else ''}
476            {params})
477      : macros_internal::MacroTable(pool, parent, parent_overlay) {{
478    {self.foreach_col(ColumnSerializer.static_assert_flags)}
479    {self.foreach_col(ColumnSerializer.extend_nullable_vector)}
480
481    {olay}
482    {self.foreach_col(ColumnSerializer.column_init)}
483  }}
484    '''
485
486  def serialize(self) -> str:
487    return f'''
488class {self.table_name} : public macros_internal::MacroTable {{
489 public:
490  {self.id_defn().lstrip()}
491  struct ColumnIndex {{
492    {self.foreach_col(ColumnSerializer.colindex)}
493  }};
494  struct ColumnType {{
495    {self.foreach_col(ColumnSerializer.coltype_enum)}
496  }};
497  {self.row_struct().strip()}
498  struct ColumnFlag {{
499    {self.foreach_col(ColumnSerializer.flag)}
500  }};
501
502  class RowNumber;
503  class ConstRowReference;
504  class RowReference;
505
506  class RowNumber : public macros_internal::AbstractRowNumber<
507      {self.table_name}, ConstRowReference, RowReference> {{
508   public:
509    explicit RowNumber(uint32_t row_number)
510        : AbstractRowNumber(row_number) {{}}
511  }};
512  static_assert(std::is_trivially_destructible<RowNumber>::value,
513                "Inheritance used without trivial destruction");
514
515  {self.const_row_reference_struct().strip()}
516  {self.row_reference_struct().strip()}
517
518  {self.const_iterator().strip()}
519  {self.iterator().strip()}
520
521  struct IdAndRow {{
522    Id id;
523    uint32_t row;
524    RowReference row_reference;
525    RowNumber row_number;
526  }};
527
528  {self.constructor().strip()}
529  ~{self.table_name}() override;
530
531  static const char* Name() {{ return "{self.table.sql_name}"; }}
532
533  static Table::Schema ComputeStaticSchema() {{
534    Table::Schema schema;
535    schema.columns.emplace_back(Table::Schema::Column{{
536        "id", SqlValue::Type::kLong, true, true, false, false}});
537    schema.columns.emplace_back(Table::Schema::Column{{
538        "type", SqlValue::Type::kString, false, false, false, false}});
539    {self.foreach_col(ColumnSerializer.static_schema)}
540    return schema;
541  }}
542
543  ConstIterator IterateRows() const {{
544    return ConstIterator(this, CopyOverlays());
545  }}
546
547  Iterator IterateRows() {{ return Iterator(this, CopyOverlays()); }}
548
549  ConstIterator FilterToIterator(
550      const std::vector<Constraint>& cs,
551      RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) const {{
552    return ConstIterator(this, FilterAndApplyToOverlays(cs, opt));
553  }}
554
555  Iterator FilterToIterator(
556      const std::vector<Constraint>& cs,
557      RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) {{
558    return Iterator(this, FilterAndApplyToOverlays(cs, opt));
559  }}
560
561  void ShrinkToFit() {{
562    {self.foreach_col(ColumnSerializer.shrink_to_fit)}
563  }}
564
565  std::optional<ConstRowReference> FindById(Id find_id) const {{
566    std::optional<uint32_t> row = id().IndexOf(find_id);
567    return row ? std::make_optional(ConstRowReference(this, *row))
568               : std::nullopt;
569  }}
570
571  std::optional<RowReference> FindById(Id find_id) {{
572    std::optional<uint32_t> row = id().IndexOf(find_id);
573    return row ? std::make_optional(RowReference(this, *row)) : std::nullopt;
574  }}
575
576  IdAndRow Insert(const Row& row) {{
577    uint32_t row_number = row_count();
578    {self.insert_common().strip()}
579    {self.foreach_col(ColumnSerializer.append)}
580    UpdateSelfOverlayAfterInsert();
581    return IdAndRow{{std::move(id), row_number, RowReference(this, row_number),
582                     RowNumber(row_number)}};
583  }}
584
585  {self.extend().strip()}
586
587  {self.foreach_col(ColumnSerializer.accessor)}
588
589  {self.foreach_col(ColumnSerializer.mutable_accessor)}
590
591 private:
592  {self.extend_constructor().strip()}
593  {self.parent_field().strip()}
594  {self.foreach_col(ColumnSerializer.storage)}
595}};
596  '''.strip('\n')
597
598
599def serialize_header(ifdef_guard: str, tables: List[ParsedTable],
600                     include_paths: List[str]) -> str:
601  """Serializes a table header file containing the given set of tables."""
602  include_paths_str = '\n'.join([f'#include "{i}"' for i in include_paths])
603  tables_str = '\n\n'.join([TableSerializer(t).serialize() for t in tables])
604  return f'''
605#ifndef {ifdef_guard}
606#define {ifdef_guard}
607
608#include "src/trace_processor/tables/macros_internal.h"
609
610{include_paths_str}
611
612namespace perfetto {{
613namespace trace_processor {{
614namespace tables {{
615
616{tables_str.strip()}
617
618}}  // namespace tables
619}}  // namespace trace_processor
620}}  // namespace perfetto
621
622#endif  // {ifdef_guard}
623  '''.strip()
624
625
626def to_cpp_flags(raw_flag: ColumnFlag) -> str:
627  """Converts a ColumnFlag to the C++ flags which it represents
628
629  It is not valid to call this function with ColumnFlag.NONE as in this case
630  defaults for that column should be implicitly used."""
631
632  assert raw_flag != ColumnFlag.NONE
633  flags = []
634  if ColumnFlag.SORTED in raw_flag:
635    flags.append('Column::Flag::kSorted')
636  if ColumnFlag.HIDDEN in raw_flag:
637    flags.append('Column::Flag::kHidden')
638  if ColumnFlag.DENSE in raw_flag:
639    flags.append('Column::Flag::kDense')
640  if ColumnFlag.SET_ID in raw_flag:
641    flags.append('Column::Flag::kSetId')
642  return ' | '.join(flags)
643