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