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