1 /*
2 * Copyright (C) 2020 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/proto/packet_sequence_state_generation.h"
18 #include <cstddef>
19
20 #include "src/trace_processor/importers/proto/track_event_sequence_state.h"
21 #include "src/trace_processor/storage/stats.h"
22 #include "src/trace_processor/storage/trace_storage.h"
23 #include "src/trace_processor/types/trace_processor_context.h"
24
25 namespace perfetto::trace_processor {
26
27 PacketSequenceStateGeneration::CustomState::~CustomState() = default;
28
29 // static
30 RefPtr<PacketSequenceStateGeneration>
CreateFirst(TraceProcessorContext * context)31 PacketSequenceStateGeneration::CreateFirst(TraceProcessorContext* context) {
32 return RefPtr<PacketSequenceStateGeneration>(
33 new PacketSequenceStateGeneration(
34 context, TrackEventSequenceState::CreateFirst(), false));
35 }
36
PacketSequenceStateGeneration(TraceProcessorContext * context,InternedFieldMap interned_data,TrackEventSequenceState track_event_sequence_state,CustomStateArray custom_state,TraceBlobView trace_packet_defaults,bool is_incremental_state_valid)37 PacketSequenceStateGeneration::PacketSequenceStateGeneration(
38 TraceProcessorContext* context,
39 InternedFieldMap interned_data,
40 TrackEventSequenceState track_event_sequence_state,
41 CustomStateArray custom_state,
42 TraceBlobView trace_packet_defaults,
43 bool is_incremental_state_valid)
44 : context_(context),
45 interned_data_(std::move(interned_data)),
46 track_event_sequence_state_(std::move(track_event_sequence_state)),
47 custom_state_(std::move(custom_state)),
48 trace_packet_defaults_(std::move(trace_packet_defaults)),
49 is_incremental_state_valid_(is_incremental_state_valid) {
50 for (auto& s : custom_state_) {
51 if (s.get() != nullptr) {
52 s->set_generation(this);
53 }
54 }
55 }
56
57 RefPtr<PacketSequenceStateGeneration>
OnPacketLoss()58 PacketSequenceStateGeneration::OnPacketLoss() {
59 // No need to increment the generation. If any future packet depends on
60 // previous messages to update the incremental state its packet (if the
61 // DataSource is behaving correctly) would have the
62 // SEQ_NEEDS_INCREMENTAL_STATE bit set and such a packet will be dropped by
63 // the ProtoTraceReader and never make it far enough to update any incremental
64 // state.
65 track_event_sequence_state_.OnPacketLoss();
66 is_incremental_state_valid_ = false;
67 return RefPtr<PacketSequenceStateGeneration>(this);
68 }
69
70 RefPtr<PacketSequenceStateGeneration>
OnIncrementalStateCleared()71 PacketSequenceStateGeneration::OnIncrementalStateCleared() {
72 return RefPtr<PacketSequenceStateGeneration>(
73 new PacketSequenceStateGeneration(
74 context_, track_event_sequence_state_.OnIncrementalStateCleared(),
75 true));
76 }
77
78 RefPtr<PacketSequenceStateGeneration>
OnNewTracePacketDefaults(TraceBlobView trace_packet_defaults)79 PacketSequenceStateGeneration::OnNewTracePacketDefaults(
80 TraceBlobView trace_packet_defaults) {
81 return RefPtr<PacketSequenceStateGeneration>(
82 new PacketSequenceStateGeneration(
83 context_, interned_data_,
84 track_event_sequence_state_.OnIncrementalStateCleared(),
85 custom_state_, std::move(trace_packet_defaults),
86 is_incremental_state_valid_));
87 }
88
GetInternedMessageView(uint32_t field_id,uint64_t iid)89 InternedMessageView* PacketSequenceStateGeneration::GetInternedMessageView(
90 uint32_t field_id,
91 uint64_t iid) {
92 auto field_it = interned_data_.find(field_id);
93 if (field_it != interned_data_.end()) {
94 auto* message_map = &field_it->second;
95 auto it = message_map->find(iid);
96 if (it != message_map->end()) {
97 return &it->second;
98 }
99 }
100
101 context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
102 return nullptr;
103 }
104
InternMessage(uint32_t field_id,TraceBlobView message)105 void PacketSequenceStateGeneration::InternMessage(uint32_t field_id,
106 TraceBlobView message) {
107 constexpr auto kIidFieldNumber = 1;
108
109 uint64_t iid = 0;
110 auto message_start = message.data();
111 auto message_size = message.length();
112 protozero::ProtoDecoder decoder(message_start, message_size);
113
114 auto field = decoder.FindField(kIidFieldNumber);
115 if (PERFETTO_UNLIKELY(!field)) {
116 PERFETTO_DLOG("Interned message without interning_id");
117 context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
118 return;
119 }
120 iid = field.as_uint64();
121
122 auto res = interned_data_[field_id].emplace(
123 iid, InternedMessageView(std::move(message)));
124
125 // If a message with this ID is already interned in the same generation,
126 // its data should not have changed (this is forbidden by the InternedData
127 // proto).
128 // TODO(eseckler): This DCHECK assumes that the message is encoded the
129 // same way if it is re-emitted.
130 PERFETTO_DCHECK(res.second ||
131 (res.first->second.message().length() == message_size &&
132 memcmp(res.first->second.message().data(), message_start,
133 message_size) == 0));
134 }
135
136 } // namespace perfetto::trace_processor
137