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 namespace perfetto {
22 namespace trace_processor {
23
ArgsTracker(TraceProcessorContext * context)24 ArgsTracker::ArgsTracker(TraceProcessorContext* context) : context_(context) {}
25
~ArgsTracker()26 ArgsTracker::~ArgsTracker() {
27 Flush();
28 }
29
AddArg(Column * arg_set_id,uint32_t row,StringId flat_key,StringId key,Variadic value,UpdatePolicy update_policy)30 void ArgsTracker::AddArg(Column* arg_set_id,
31 uint32_t row,
32 StringId flat_key,
33 StringId key,
34 Variadic value,
35 UpdatePolicy update_policy) {
36 args_.emplace_back();
37
38 auto* rid_arg = &args_.back();
39 rid_arg->column = arg_set_id;
40 rid_arg->row = row;
41 rid_arg->flat_key = flat_key;
42 rid_arg->key = key;
43 rid_arg->value = value;
44 rid_arg->update_policy = update_policy;
45 }
46
Flush()47 void ArgsTracker::Flush() {
48 using Arg = GlobalArgsTracker::Arg;
49
50 if (args_.empty())
51 return;
52
53 // We sort here because a single packet may add multiple args with different
54 // rowids.
55 auto comparator = [](const Arg& f, const Arg& s) {
56 // We only care that all args for a specific arg set appear in a contiguous
57 // block and that args within one arg set are sorted by key, but not about
58 // the relative order of one block to another. The simplest way to achieve
59 // that is to sort by table column pointer & row, which identify the arg
60 // set, and then by key.
61 if (f.column == s.column && f.row == s.row)
62 return f.key < s.key;
63 if (f.column == s.column)
64 return f.row < s.row;
65 return f.column < s.column;
66 };
67 std::stable_sort(args_.begin(), args_.end(), comparator);
68
69 for (uint32_t i = 0; i < args_.size();) {
70 const auto& arg = args_[i];
71 Column* column = arg.column;
72 auto row = arg.row;
73
74 uint32_t next_rid_idx = i + 1;
75 while (next_rid_idx < args_.size() &&
76 column == args_[next_rid_idx].column &&
77 row == args_[next_rid_idx].row) {
78 next_rid_idx++;
79 }
80
81 ArgSetId set_id =
82 context_->global_args_tracker->AddArgSet(args_, i, next_rid_idx);
83 column->Set(row, SqlValue::Long(set_id));
84
85 i = next_rid_idx;
86 }
87 args_.clear();
88 }
89
BoundInserter(ArgsTracker * args_tracker,Column * arg_set_id_column,uint32_t row)90 ArgsTracker::BoundInserter::BoundInserter(ArgsTracker* args_tracker,
91 Column* arg_set_id_column,
92 uint32_t row)
93 : args_tracker_(args_tracker),
94 arg_set_id_column_(arg_set_id_column),
95 row_(row) {}
96
~BoundInserter()97 ArgsTracker::BoundInserter::~BoundInserter() {}
98
99 ArgsTracker::BoundInserter::BoundInserter(BoundInserter&&) = default;
100 ArgsTracker::BoundInserter& ArgsTracker::BoundInserter::operator=(
101 BoundInserter&&) = default;
102
103 } // namespace trace_processor
104 } // namespace perfetto
105