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