• 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 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRACKER_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRACKER_H_
19 
20 #include "perfetto/ext/base/small_vector.h"
21 #include "src/trace_processor/importers/common/global_args_tracker.h"
22 #include "src/trace_processor/storage/trace_storage.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24 #include "src/trace_processor/types/variadic.h"
25 
26 namespace perfetto {
27 namespace trace_processor {
28 
29 // Tracks and stores args for rows until the end of the packet. This allows
30 // allows args to pushed as a group into storage.
31 class ArgsTracker {
32  public:
33   using UpdatePolicy = GlobalArgsTracker::UpdatePolicy;
34   using CompactArg = GlobalArgsTracker::CompactArg;
35   using CompactArgSet = base::SmallVector<CompactArg, 16>;
36 
37   // Stores the table and row at creation time which args are associated with.
38   // This allows callers to directly add args without repeating the row the
39   // args should be associated with.
40   class BoundInserter {
41    public:
42     virtual ~BoundInserter();
43 
44     BoundInserter(BoundInserter&&) noexcept = default;
45     BoundInserter& operator=(BoundInserter&&) noexcept = default;
46 
47     BoundInserter(const BoundInserter&) = delete;
48     BoundInserter& operator=(const BoundInserter&) = delete;
49 
50     // Adds an arg with the same key and flat_key.
51     BoundInserter& AddArg(
52         StringId key,
53         Variadic v,
54         UpdatePolicy update_policy = UpdatePolicy::kAddOrUpdate) {
55       return AddArg(key, key, v, update_policy);
56     }
57 
58     virtual BoundInserter& AddArg(
59         StringId flat_key,
60         StringId key,
61         Variadic v,
62         UpdatePolicy update_policy = UpdatePolicy::kAddOrUpdate) {
63       args_tracker_->AddArg(arg_set_id_column_, row_, flat_key, key, v,
64                             update_policy);
65       return *this;
66     }
67 
68     // IncrementArrayEntryIndex() and GetNextArrayEntryIndex() provide a way to
69     // track the next array index for an array under a specific key.
GetNextArrayEntryIndex(StringId key)70     size_t GetNextArrayEntryIndex(StringId key) {
71       // Zero-initializes |key| in the map if it doesn't exist yet.
72       return args_tracker_
73           ->array_indexes_[std::make_tuple(arg_set_id_column_, row_, key)];
74     }
75 
76     // Returns the next available array index after increment.
IncrementArrayEntryIndex(StringId key)77     size_t IncrementArrayEntryIndex(StringId key) {
78       // Zero-initializes |key| in the map if it doesn't exist yet.
79       return ++args_tracker_->array_indexes_[std::make_tuple(arg_set_id_column_,
80                                                              row_, key)];
81     }
82 
83    protected:
84     BoundInserter(ArgsTracker* args_tracker,
85                   Column* arg_set_id_column,
86                   uint32_t row);
87 
88    private:
89     friend class ArgsTracker;
90 
91     ArgsTracker* args_tracker_ = nullptr;
92     Column* arg_set_id_column_ = nullptr;
93     uint32_t row_ = 0;
94   };
95 
96   explicit ArgsTracker(TraceProcessorContext*);
97 
98   ArgsTracker(const ArgsTracker&) = delete;
99   ArgsTracker& operator=(const ArgsTracker&) = delete;
100 
101   ArgsTracker(ArgsTracker&&) = default;
102   ArgsTracker& operator=(ArgsTracker&&) = default;
103 
104   virtual ~ArgsTracker();
105 
AddArgsTo(RawId id)106   BoundInserter AddArgsTo(RawId id) {
107     return AddArgsTo(context_->storage->mutable_raw_table(), id);
108   }
109 
AddArgsTo(CounterId id)110   BoundInserter AddArgsTo(CounterId id) {
111     return AddArgsTo(context_->storage->mutable_counter_table(), id);
112   }
113 
AddArgsTo(SliceId id)114   BoundInserter AddArgsTo(SliceId id) {
115     return AddArgsTo(context_->storage->mutable_slice_table(), id);
116   }
117 
AddArgsTo(tables::FlowTable::Id id)118   BoundInserter AddArgsTo(tables::FlowTable::Id id) {
119     return AddArgsTo(context_->storage->mutable_flow_table(), id);
120   }
121 
AddArgsTo(tables::MemorySnapshotNodeTable::Id id)122   BoundInserter AddArgsTo(tables::MemorySnapshotNodeTable::Id id) {
123     return AddArgsTo(context_->storage->mutable_memory_snapshot_node_table(),
124                      id);
125   }
126 
AddArgsTo(MetadataId id)127   BoundInserter AddArgsTo(MetadataId id) {
128     auto* table = context_->storage->mutable_metadata_table();
129     uint32_t row = *table->id().IndexOf(id);
130     return BoundInserter(this, table->mutable_int_value(), row);
131   }
132 
AddArgsTo(TrackId id)133   BoundInserter AddArgsTo(TrackId id) {
134     auto* table = context_->storage->mutable_track_table();
135     uint32_t row = *table->id().IndexOf(id);
136     return BoundInserter(this, table->mutable_source_arg_set_id(), row);
137   }
138 
AddArgsTo(VulkanAllocId id)139   BoundInserter AddArgsTo(VulkanAllocId id) {
140     return AddArgsTo(
141         context_->storage->mutable_vulkan_memory_allocations_table(), id);
142   }
143 
AddArgsTo(UniquePid id)144   BoundInserter AddArgsTo(UniquePid id) {
145     return BoundInserter(
146         this, context_->storage->mutable_process_table()->mutable_arg_set_id(),
147         id);
148   }
149 
AddArgsTo(tables::ExperimentalProtoPathTable::Id id)150   BoundInserter AddArgsTo(tables::ExperimentalProtoPathTable::Id id) {
151     return AddArgsTo(context_->storage->mutable_experimental_proto_path_table(),
152                      id);
153   }
154 
155   // Returns a CompactArgSet which contains the args inserted into this
156   // ArgsTracker. Requires that every arg in this tracker was inserted for the
157   // "arg_set_id" column given by |column| at the given |row_number|.
158   //
159   // Note that this means the args stored in this tracker will *not* be flushed
160   // into the tables: it is the callers responsibility to ensure this happens if
161   // necessary.
162   CompactArgSet ToCompactArgSet(const Column& column, uint32_t row_number) &&;
163 
164   // Returns whether this ArgsTracker contains any arg which require translation
165   // according to the provided |table|.
166   bool NeedsTranslation(const ArgsTranslationTable& table) const;
167 
168   // Commits the added args to storage.
169   // Virtual for testing.
170   virtual void Flush();
171 
172  private:
173   template <typename Table>
AddArgsTo(Table * table,typename Table::Id id)174   BoundInserter AddArgsTo(Table* table, typename Table::Id id) {
175     uint32_t row = *table->id().IndexOf(id);
176     return BoundInserter(this, table->mutable_arg_set_id(), row);
177   }
178 
179   void AddArg(Column* arg_set_id,
180               uint32_t row,
181               StringId flat_key,
182               StringId key,
183               Variadic,
184               UpdatePolicy);
185 
186   base::SmallVector<GlobalArgsTracker::Arg, 16> args_;
187   TraceProcessorContext* context_ = nullptr;
188 
189   using ArrayKeyTuple =
190       std::tuple<Column* /*arg_set_id*/, uint32_t /*row*/, StringId /*key*/>;
191   std::map<ArrayKeyTuple, size_t /*next_index*/> array_indexes_;
192 };
193 
194 }  // namespace trace_processor
195 }  // namespace perfetto
196 
197 #endif  // SRC_TRACE_PROCESSOR_IMPORTERS_COMMON_ARGS_TRACKER_H_
198