• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/args_tracker.h"
18 
19 #include <algorithm>
20 
21 #include "src/trace_processor/importers/common/args_translation_table.h"
22 
23 namespace perfetto {
24 namespace trace_processor {
25 
ArgsTracker(TraceProcessorContext * context)26 ArgsTracker::ArgsTracker(TraceProcessorContext* context) : context_(context) {}
27 
~ArgsTracker()28 ArgsTracker::~ArgsTracker() {
29   Flush();
30 }
31 
AddArg(Column * arg_set_id,uint32_t row,StringId flat_key,StringId key,Variadic value,UpdatePolicy update_policy)32 void ArgsTracker::AddArg(Column* arg_set_id,
33                          uint32_t row,
34                          StringId flat_key,
35                          StringId key,
36                          Variadic value,
37                          UpdatePolicy update_policy) {
38   args_.emplace_back();
39 
40   auto* rid_arg = &args_.back();
41   rid_arg->column = arg_set_id;
42   rid_arg->row = row;
43   rid_arg->flat_key = flat_key;
44   rid_arg->key = key;
45   rid_arg->value = value;
46   rid_arg->update_policy = update_policy;
47 }
48 
Flush()49 void ArgsTracker::Flush() {
50   using Arg = GlobalArgsTracker::Arg;
51 
52   if (args_.empty())
53     return;
54 
55   // We sort here because a single packet may add multiple args with different
56   // rowids.
57   auto comparator = [](const Arg& f, const Arg& s) {
58     // We only care that all args for a specific arg set appear in a contiguous
59     // block and that args within one arg set are sorted by key, but not about
60     // the relative order of one block to another. The simplest way to achieve
61     // that is to sort by table column pointer & row, which identify the arg
62     // set, and then by key.
63     if (f.column == s.column && f.row == s.row)
64       return f.key < s.key;
65     if (f.column == s.column)
66       return f.row < s.row;
67     return f.column < s.column;
68   };
69   std::stable_sort(args_.begin(), args_.end(), comparator);
70 
71   for (uint32_t i = 0; i < args_.size();) {
72     const GlobalArgsTracker::Arg& arg = args_[i];
73     auto* col = arg.column;
74     uint32_t row = arg.row;
75 
76     uint32_t next_rid_idx = i + 1;
77     while (next_rid_idx < args_.size() && col == args_[next_rid_idx].column &&
78            row == args_[next_rid_idx].row) {
79       next_rid_idx++;
80     }
81 
82     ArgSetId set_id =
83         context_->global_args_tracker->AddArgSet(&args_[0], i, next_rid_idx);
84     if (col->IsNullable()) {
85       TypedColumn<std::optional<uint32_t>>::FromColumn(col)->Set(row, set_id);
86     } else {
87       TypedColumn<uint32_t>::FromColumn(col)->Set(row, set_id);
88     }
89 
90     i = next_rid_idx;
91   }
92   args_.clear();
93 }
94 
ToCompactArgSet(const Column & column,uint32_t row_number)95 ArgsTracker::CompactArgSet ArgsTracker::ToCompactArgSet(
96     const Column& column,
97     uint32_t row_number) && {
98   CompactArgSet compact_args;
99   for (const auto& arg : args_) {
100     PERFETTO_DCHECK(arg.column == &column);
101     PERFETTO_DCHECK(arg.row == row_number);
102     compact_args.emplace_back(arg.ToCompactArg());
103   }
104   args_.clear();
105   return compact_args;
106 }
107 
NeedsTranslation(const ArgsTranslationTable & table) const108 bool ArgsTracker::NeedsTranslation(const ArgsTranslationTable& table) const {
109   return std::any_of(
110       args_.begin(), args_.end(), [&table](const GlobalArgsTracker::Arg& arg) {
111         return table.NeedsTranslation(arg.flat_key, arg.key, arg.value.type);
112       });
113 }
114 
BoundInserter(ArgsTracker * args_tracker,Column * arg_set_id_column,uint32_t row)115 ArgsTracker::BoundInserter::BoundInserter(ArgsTracker* args_tracker,
116                                           Column* arg_set_id_column,
117                                           uint32_t row)
118     : args_tracker_(args_tracker),
119       arg_set_id_column_(arg_set_id_column),
120       row_(row) {}
121 
122 ArgsTracker::BoundInserter::~BoundInserter() = default;
123 
124 }  // namespace trace_processor
125 }  // namespace perfetto
126