blob: b75ccf4780460963ee085b4c52285f9992b4102d [file] [log] [blame]
Primiano Tuccid933d912018-09-04 09:15:07 +01001/*
2 * Copyright (C) 2018 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
Eric Seckler137a4672019-10-24 08:51:14 +010017#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
Primiano Tuccid933d912018-09-04 09:15:07 +010018
19#include <string>
20
Hector Dearman33610d22019-08-07 13:00:20 +010021#include <zlib.h>
22
Primiano Tuccid933d912018-09-04 09:15:07 +010023#include "perfetto/base/logging.h"
Hector Dearman33610d22019-08-07 13:00:20 +010024#include "perfetto/ext/base/optional.h"
ssid1ffe2252019-10-02 13:27:21 -070025#include "perfetto/ext/base/string_view.h"
Primiano Tucci2c5488f2019-06-01 03:27:28 +010026#include "perfetto/ext/base/utils.h"
Primiano Tuccid933d912018-09-04 09:15:07 +010027#include "perfetto/protozero/proto_decoder.h"
28#include "perfetto/protozero/proto_utils.h"
ssid1ffe2252019-10-02 13:27:21 -070029#include "perfetto/trace_processor/status.h"
Primiano Tucci6756fb02019-08-14 15:49:18 +020030#include "src/trace_processor/clock_tracker.h"
Isabelle Taylora97c5f52018-10-23 17:36:12 +010031#include "src/trace_processor/event_tracker.h"
Eric Seckleracfe35b2019-10-18 15:50:17 +010032#include "src/trace_processor/importers/ftrace/ftrace_module.h"
Eric Seckler771960c2019-10-22 15:37:12 +010033#include "src/trace_processor/importers/proto/packet_sequence_state.h"
34#include "src/trace_processor/importers/proto/proto_incremental_state.h"
Eric Secklerde589952019-10-17 12:46:07 +010035#include "src/trace_processor/importers/proto/track_event_module.h"
Primiano Tucci0e38a142019-01-07 20:51:09 +000036#include "src/trace_processor/stats.h"
Primiano Tuccid933d912018-09-04 09:15:07 +010037#include "src/trace_processor/trace_sorter.h"
Primiano Tucci0e38a142019-01-07 20:51:09 +000038#include "src/trace_processor/trace_storage.h"
Primiano Tuccid933d912018-09-04 09:15:07 +010039
Primiano Tucci355b8c82019-08-29 08:37:51 +020040#include "protos/perfetto/config/trace_config.pbzero.h"
41#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
Primiano Tucci355b8c82019-08-29 08:37:51 +020042#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
43#include "protos/perfetto/trace/trace.pbzero.h"
Eric Secklerd2af9892019-11-01 10:10:53 +000044#include "protos/perfetto/trace/trace_packet.pbzero.h"
Primiano Tuccid933d912018-09-04 09:15:07 +010045
46namespace perfetto {
47namespace trace_processor {
48
Primiano Tuccid933d912018-09-04 09:15:07 +010049using protozero::proto_utils::MakeTagLengthDelimited;
Primiano Tuccid933d912018-09-04 09:15:07 +010050using protozero::proto_utils::ParseVarInt;
51
Eric Seckler684a4f72019-04-26 14:34:07 +010052namespace {
53
Hector Dearman33610d22019-08-07 13:00:20 +010054constexpr uint8_t kTracePacketTag =
55 MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
56
Hector Dearman33610d22019-08-07 13:00:20 +010057TraceBlobView Decompress(TraceBlobView input) {
58 uint8_t out[4096];
59 std::string s;
60
61 z_stream stream{};
62 stream.next_in = const_cast<uint8_t*>(input.data());
63 stream.avail_in = static_cast<unsigned int>(input.length());
64
65 if (inflateInit(&stream) != Z_OK)
66 return TraceBlobView(nullptr, 0, 0);
67
68 int ret;
69 do {
70 stream.next_out = out;
71 stream.avail_out = sizeof(out);
72 ret = inflate(&stream, Z_NO_FLUSH);
Hector Dearman10055b72019-11-04 18:57:26 +000073 if (ret != Z_STREAM_END && ret != Z_OK) {
74 inflateEnd(&stream);
Hector Dearman33610d22019-08-07 13:00:20 +010075 return TraceBlobView(nullptr, 0, 0);
Hector Dearman10055b72019-11-04 18:57:26 +000076 }
Hector Dearman33610d22019-08-07 13:00:20 +010077 s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
78 } while (ret != Z_STREAM_END);
79 inflateEnd(&stream);
80
81 std::unique_ptr<uint8_t[]> output(new uint8_t[s.size()]);
82 memcpy(output.get(), s.data(), s.size());
83 return TraceBlobView(std::move(output), 0, s.size());
84}
85
Eric Seckler684a4f72019-04-26 14:34:07 +010086} // namespace
87
Primiano Tuccid933d912018-09-04 09:15:07 +010088ProtoTraceTokenizer::ProtoTraceTokenizer(TraceProcessorContext* ctx)
Deepanjan Roy01994ca2019-04-02 11:05:34 -070089 : context_(ctx) {}
Primiano Tuccid933d912018-09-04 09:15:07 +010090ProtoTraceTokenizer::~ProtoTraceTokenizer() = default;
91
Lalit Magantid71a9452019-05-09 15:13:24 +010092util::Status ProtoTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> owned_buf,
93 size_t size) {
Primiano Tuccid933d912018-09-04 09:15:07 +010094 uint8_t* data = &owned_buf[0];
95 if (!partial_buf_.empty()) {
96 // It takes ~5 bytes for a proto preamble + the varint size.
97 const size_t kHeaderBytes = 5;
98 if (PERFETTO_UNLIKELY(partial_buf_.size() < kHeaderBytes)) {
99 size_t missing_len = std::min(kHeaderBytes - partial_buf_.size(), size);
100 partial_buf_.insert(partial_buf_.end(), &data[0], &data[missing_len]);
101 if (partial_buf_.size() < kHeaderBytes)
Lalit Magantid71a9452019-05-09 15:13:24 +0100102 return util::OkStatus();
Primiano Tuccid933d912018-09-04 09:15:07 +0100103 data += missing_len;
104 size -= missing_len;
105 }
106
Primiano Tuccic1678872019-03-20 11:30:54 +0000107 // At this point we have enough data in |partial_buf_| to read at least the
Primiano Tuccid933d912018-09-04 09:15:07 +0100108 // field header and know the size of the next TracePacket.
Primiano Tuccid933d912018-09-04 09:15:07 +0100109 const uint8_t* pos = &partial_buf_[0];
110 uint8_t proto_field_tag = *pos;
111 uint64_t field_size = 0;
112 const uint8_t* next = ParseVarInt(++pos, &*partial_buf_.end(), &field_size);
113 bool parse_failed = next == pos;
114 pos = next;
115 if (proto_field_tag != kTracePacketTag || field_size == 0 || parse_failed) {
Lalit Magantid71a9452019-05-09 15:13:24 +0100116 return util::ErrStatus(
117 "Failed parsing a TracePacket from the partial buffer");
Primiano Tuccid933d912018-09-04 09:15:07 +0100118 }
119
120 // At this point we know how big the TracePacket is.
121 size_t hdr_size = static_cast<size_t>(pos - &partial_buf_[0]);
122 size_t size_incl_header = static_cast<size_t>(field_size + hdr_size);
123 PERFETTO_DCHECK(size_incl_header > partial_buf_.size());
124
125 // There is a good chance that between the |partial_buf_| and the new |data|
126 // of the current call we have enough bytes to parse a TracePacket.
127 if (partial_buf_.size() + size >= size_incl_header) {
128 // Create a new buffer for the whole TracePacket and copy into that:
129 // 1) The beginning of the TracePacket (including the proto header) from
130 // the partial buffer.
131 // 2) The rest of the TracePacket from the current |data| buffer (note
132 // that we might have consumed already a few bytes form |data| earlier
133 // in this function, hence we need to keep |off| into account).
134 std::unique_ptr<uint8_t[]> buf(new uint8_t[size_incl_header]);
135 memcpy(&buf[0], partial_buf_.data(), partial_buf_.size());
136 // |size_missing| is the number of bytes for the rest of the TracePacket
137 // in |data|.
138 size_t size_missing = size_incl_header - partial_buf_.size();
139 memcpy(&buf[partial_buf_.size()], &data[0], size_missing);
140 data += size_missing;
141 size -= size_missing;
142 partial_buf_.clear();
143 uint8_t* buf_start = &buf[0]; // Note that buf is std::moved below.
Lalit Magantid71a9452019-05-09 15:13:24 +0100144 util::Status status =
145 ParseInternal(std::move(buf), buf_start, size_incl_header);
146 if (PERFETTO_UNLIKELY(!status.ok()))
147 return status;
Primiano Tuccid933d912018-09-04 09:15:07 +0100148 } else {
149 partial_buf_.insert(partial_buf_.end(), data, &data[size]);
Lalit Magantid71a9452019-05-09 15:13:24 +0100150 return util::OkStatus();
Primiano Tuccid933d912018-09-04 09:15:07 +0100151 }
152 }
Lalit Magantid71a9452019-05-09 15:13:24 +0100153 return ParseInternal(std::move(owned_buf), data, size);
Primiano Tuccid933d912018-09-04 09:15:07 +0100154}
155
Lalit Magantid71a9452019-05-09 15:13:24 +0100156util::Status ProtoTraceTokenizer::ParseInternal(
157 std::unique_ptr<uint8_t[]> owned_buf,
158 uint8_t* data,
159 size_t size) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100160 PERFETTO_DCHECK(data >= &owned_buf[0]);
161 const uint8_t* start = &owned_buf[0];
162 const size_t data_off = static_cast<size_t>(data - start);
163 TraceBlobView whole_buf(std::move(owned_buf), data_off, size);
Primiano Tuccic1678872019-03-20 11:30:54 +0000164
165 protos::pbzero::Trace::Decoder decoder(data, size);
166 for (auto it = decoder.packet(); it; ++it) {
Primiano Tucci8f7359c2019-10-17 12:59:33 +0100167 protozero::ConstBytes packet = *it;
168 size_t field_offset = whole_buf.offset_of(packet.data);
Lalit Magantid71a9452019-05-09 15:13:24 +0100169 util::Status status =
Primiano Tucci8f7359c2019-10-17 12:59:33 +0100170 ParsePacket(whole_buf.slice(field_offset, packet.size));
Lalit Magantid71a9452019-05-09 15:13:24 +0100171 if (PERFETTO_UNLIKELY(!status.ok()))
172 return status;
Primiano Tuccid933d912018-09-04 09:15:07 +0100173 }
174
Primiano Tuccic1678872019-03-20 11:30:54 +0000175 const size_t bytes_left = decoder.bytes_left();
176 if (bytes_left > 0) {
Primiano Tuccid933d912018-09-04 09:15:07 +0100177 PERFETTO_DCHECK(partial_buf_.empty());
Primiano Tuccic1678872019-03-20 11:30:54 +0000178 partial_buf_.insert(partial_buf_.end(), &data[decoder.read_offset()],
179 &data[decoder.read_offset() + bytes_left]);
Primiano Tuccid933d912018-09-04 09:15:07 +0100180 }
Lalit Magantid71a9452019-05-09 15:13:24 +0100181 return util::OkStatus();
Primiano Tuccid933d912018-09-04 09:15:07 +0100182}
183
Lalit Magantid71a9452019-05-09 15:13:24 +0100184util::Status ProtoTraceTokenizer::ParsePacket(TraceBlobView packet) {
Primiano Tuccic1678872019-03-20 11:30:54 +0000185 protos::pbzero::TracePacket::Decoder decoder(packet.data(), packet.length());
Lalit Maganti4b2b2532019-05-09 11:03:23 +0100186 if (PERFETTO_UNLIKELY(decoder.bytes_left()))
Lalit Magantid71a9452019-05-09 15:13:24 +0100187 return util::ErrStatus(
188 "Failed to parse proto packet fully; the trace is probably corrupt.");
Primiano Tuccid933d912018-09-04 09:15:07 +0100189
Eric Seckler5c7866e2019-10-18 08:38:16 +0100190 auto timestamp =
191 decoder.has_timestamp()
192 ? static_cast<int64_t>(decoder.timestamp())
193 : std::max(latest_timestamp_, context_->sorter->max_timestamp());
Primiano Tucci6756fb02019-08-14 15:49:18 +0200194
Eric Secklerb32cacf2019-09-27 16:51:19 +0100195 const uint32_t seq_id = decoder.trusted_packet_sequence_id();
196
Eric Seckler6f263fd2019-10-24 16:48:24 +0100197 if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
198 (!decoder.timestamp_clock_id() ||
199 decoder.timestamp_clock_id() ==
200 protos::pbzero::ClockSnapshot::Clock::MONOTONIC)) {
201 // Chrome event timestamps are in MONOTONIC domain, but may occur in traces
202 // where (a) no clock snapshots exist or (b) no clock_id is specified for
203 // their timestamps. Adjust to trace time if we have a clock snapshot.
204 // TODO(eseckler): Set timestamp_clock_id and emit ClockSnapshots in chrome
205 // and then remove this.
206 auto trace_ts = context_->clock_tracker->ToTraceTime(
207 protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
208 if (trace_ts.has_value())
209 timestamp = trace_ts.value();
210 } else if (decoder.timestamp_clock_id()) {
211 // If the TracePacket specifies a non-zero clock-id, translate the timestamp
212 // into the trace-time clock domain.
Primiano Tucci6756fb02019-08-14 15:49:18 +0200213 PERFETTO_DCHECK(decoder.has_timestamp());
214 ClockTracker::ClockId clock_id = decoder.timestamp_clock_id();
Primiano Tucci6756fb02019-08-14 15:49:18 +0200215 bool is_seq_scoped = ClockTracker::IsReservedSeqScopedClockId(clock_id);
216 if (is_seq_scoped) {
217 if (!seq_id) {
218 return util::ErrStatus(
219 "TracePacket specified a sequence-local clock id (%" PRIu32
220 ") but the TraceWriter's sequence_id is zero (the service is "
221 "probably too old)",
Eric Secklerb32cacf2019-09-27 16:51:19 +0100222 decoder.timestamp_clock_id());
Primiano Tucci6756fb02019-08-14 15:49:18 +0200223 }
224 clock_id = ClockTracker::SeqScopedClockIdToGlobal(
225 seq_id, decoder.timestamp_clock_id());
226 }
227 auto trace_ts = context_->clock_tracker->ToTraceTime(clock_id, timestamp);
228 if (!trace_ts.has_value()) {
229 // ToTraceTime() will increase the |clock_sync_failure| stat on failure.
230 static const char seq_extra_err[] =
231 " Because the clock id is sequence-scoped, the ClockSnapshot must be "
232 "emitted on the same TraceWriter sequence of the packet that refers "
233 "to that clock id.";
234 return util::ErrStatus(
235 "Failed to convert TracePacket's timestamp from clock_id=%" PRIu32
236 " seq_id=%" PRIu32
237 ". This is usually due to the lack of a prior ClockSnapshot proto.%s",
238 decoder.timestamp_clock_id(), seq_id,
239 is_seq_scoped ? seq_extra_err : "");
240 }
241 timestamp = trace_ts.value();
242 }
Lalit Magantifa21a282019-01-17 19:03:04 +0000243 latest_timestamp_ = std::max(timestamp, latest_timestamp_);
Primiano Tuccid933d912018-09-04 09:15:07 +0100244
Eric Secklerb32cacf2019-09-27 16:51:19 +0100245 auto* state = GetIncrementalStateForPacketSequence(
246 decoder.trusted_packet_sequence_id());
247
248 uint32_t sequence_flags = decoder.sequence_flags();
249
250 if (decoder.incremental_state_cleared() ||
251 sequence_flags &
252 protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
Eric Seckler684a4f72019-04-26 14:34:07 +0100253 HandleIncrementalStateCleared(decoder);
254 } else if (decoder.previous_packet_dropped()) {
255 HandlePreviousPacketDropped(decoder);
256 }
257
Eric Secklerb32cacf2019-09-27 16:51:19 +0100258 if (decoder.sequence_flags() &
259 protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE) {
260 if (!seq_id) {
261 return util::ErrStatus(
262 "TracePacket specified SEQ_NEEDS_INCREMENTAL_STATE but the "
263 "TraceWriter's sequence_id is zero (the service is "
264 "probably too old)");
265 }
266
267 if (!state->IsIncrementalStateValid()) {
268 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
269 return util::OkStatus();
270 }
271 }
272
Primiano Tucci6756fb02019-08-14 15:49:18 +0200273 if (decoder.has_clock_snapshot()) {
274 return ParseClockSnapshot(decoder.clock_snapshot(),
275 decoder.trusted_packet_sequence_id());
276 }
277
Eric Secklerb32cacf2019-09-27 16:51:19 +0100278 // TODO(eseckler): Parse TracePacketDefaults.
279
Eric Seckler684a4f72019-04-26 14:34:07 +0100280 if (decoder.has_interned_data()) {
281 auto field = decoder.interned_data();
282 const size_t offset = packet.offset_of(field.data);
283 ParseInternedData(decoder, packet.slice(offset, field.size));
284 }
285
Eric Secklerde589952019-10-17 12:46:07 +0100286 ModuleResult res = ModuleResult::Ignored();
Eric Seckler771960c2019-10-22 15:37:12 +0100287 res = context_->ftrace_module->TokenizePacket(decoder, &packet, timestamp,
288 state);
Eric Secklerde589952019-10-17 12:46:07 +0100289 if (!res.ignored())
290 return res.ToStatus();
291
Eric Seckler771960c2019-10-22 15:37:12 +0100292 res = context_->track_event_module->TokenizePacket(decoder, &packet,
293 timestamp, state);
Eric Secklerde589952019-10-17 12:46:07 +0100294 if (!res.ignored())
295 return res.ToStatus();
296
Mikhail Khokhlov785af542019-12-06 13:45:10 +0000297 auto& modules = context_->modules_by_field;
298 for (uint32_t field_id = 1; field_id < modules.size(); ++field_id) {
299 if (modules[field_id] && decoder.Get(field_id).valid()) {
300 modules[field_id]->TokenizePacket(decoder, &packet, timestamp, state,
301 field_id);
302 if (!res.ignored())
303 return res.ToStatus();
304 }
305 }
306
Hector Dearman33610d22019-08-07 13:00:20 +0100307 if (decoder.has_compressed_packets()) {
308 protozero::ConstBytes field = decoder.compressed_packets();
309 const size_t field_off = packet.offset_of(field.data);
310 TraceBlobView compressed_packets = packet.slice(field_off, field.size);
311 TraceBlobView packets = Decompress(std::move(compressed_packets));
312
313 const uint8_t* start = packets.data();
314 const uint8_t* end = packets.data() + packets.length();
315 const uint8_t* ptr = start;
316 while ((end - ptr) > 2) {
317 const uint8_t* packet_start = ptr;
318 if (PERFETTO_UNLIKELY(*ptr != kTracePacketTag))
319 return util::ErrStatus("Expected TracePacket tag");
320 uint64_t packet_size = 0;
321 ptr = ParseVarInt(++ptr, end, &packet_size);
322 size_t packet_offset = static_cast<size_t>(ptr - start);
323 ptr += packet_size;
324 if (PERFETTO_UNLIKELY((ptr - packet_start) < 2 || ptr > end))
325 return util::ErrStatus("Invalid packet size");
326 util::Status status = ParsePacket(
327 packets.slice(packet_offset, static_cast<size_t>(packet_size)));
328 if (PERFETTO_UNLIKELY(!status.ok()))
329 return status;
330 }
331
332 return util::OkStatus();
333 }
334
Lalit Maganti55d0bc72019-10-23 16:22:00 +0100335 // If we're not forcing a full sort and this is a write_into_file trace, then
336 // use flush_period_ms as an indiciator for how big the sliding window for the
337 // sorter should be.
338 if (!context_->config.force_full_sort && decoder.has_trace_config()) {
Lalit Maganti295a8612019-05-21 13:57:42 +0100339 auto config = decoder.trace_config();
340 protos::pbzero::TraceConfig::Decoder trace_config(config.data, config.size);
341
342 if (trace_config.write_into_file()) {
343 int64_t window_size_ns;
344 if (trace_config.has_flush_period_ms() &&
345 trace_config.flush_period_ms() > 0) {
346 // We use 2x the flush period as a margin of error to allow for any
347 // late flush responses to still be sorted correctly.
Lalit Magantib2c2f562019-05-22 18:53:46 +0100348 window_size_ns = static_cast<int64_t>(trace_config.flush_period_ms()) *
349 2 * 1000 * 1000;
Lalit Maganti295a8612019-05-21 13:57:42 +0100350 } else {
351 constexpr uint64_t kDefaultWindowNs =
352 180 * 1000 * 1000 * 1000ULL; // 3 minutes.
353 PERFETTO_ELOG(
354 "It is strongly recommended to have flush_period_ms set when "
355 "write_into_file is turned on. You will likely have many dropped "
356 "events because of inability to sort the events correctly.");
357 window_size_ns = static_cast<int64_t>(kDefaultWindowNs);
358 }
359 context_->sorter->SetWindowSizeNs(window_size_ns);
360 }
361 }
362
Primiano Tuccid933d912018-09-04 09:15:07 +0100363 // Use parent data and length because we want to parse this again
364 // later to get the exact type of the packet.
Florian Mayer5716fc12019-06-24 11:50:51 -0700365 context_->sorter->PushTracePacket(timestamp, state, std::move(packet));
Lalit Maganti4b2b2532019-05-09 11:03:23 +0100366
Lalit Magantid71a9452019-05-09 15:13:24 +0100367 return util::OkStatus();
Eric Seckler684a4f72019-04-26 14:34:07 +0100368}
369
370void ProtoTraceTokenizer::HandleIncrementalStateCleared(
371 const protos::pbzero::TracePacket::Decoder& packet_decoder) {
372 if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
373 PERFETTO_ELOG(
374 "incremental_state_cleared without trusted_packet_sequence_id");
375 context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
376 return;
377 }
378 GetIncrementalStateForPacketSequence(
379 packet_decoder.trusted_packet_sequence_id())
380 ->OnIncrementalStateCleared();
381}
382
383void ProtoTraceTokenizer::HandlePreviousPacketDropped(
384 const protos::pbzero::TracePacket::Decoder& packet_decoder) {
385 if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
386 PERFETTO_ELOG("previous_packet_dropped without trusted_packet_sequence_id");
387 context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
388 return;
389 }
390 GetIncrementalStateForPacketSequence(
391 packet_decoder.trusted_packet_sequence_id())
392 ->OnPacketLoss();
393}
394
395void ProtoTraceTokenizer::ParseInternedData(
396 const protos::pbzero::TracePacket::Decoder& packet_decoder,
397 TraceBlobView interned_data) {
398 if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
399 PERFETTO_ELOG("InternedData packet without trusted_packet_sequence_id");
400 context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
401 return;
402 }
403
404 auto* state = GetIncrementalStateForPacketSequence(
405 packet_decoder.trusted_packet_sequence_id());
406
Eric Seckler02cdcef2019-10-14 08:56:28 +0100407 // Don't parse interned data entries until incremental state is valid, because
408 // they could otherwise be associated with the wrong generation in the state.
409 if (!state->IsIncrementalStateValid()) {
410 context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
411 return;
412 }
Eric Seckler684a4f72019-04-26 14:34:07 +0100413
414 // Store references to interned data submessages into the sequence's state.
Eric Seckler02cdcef2019-10-14 08:56:28 +0100415 protozero::ProtoDecoder decoder(interned_data.data(), interned_data.length());
416 for (protozero::Field f = decoder.ReadField(); f.valid();
417 f = decoder.ReadField()) {
418 auto bytes = f.as_bytes();
419 auto offset = interned_data.offset_of(bytes.data);
420 state->InternMessage(f.id(), interned_data.slice(offset, bytes.size));
Nicolò Mazzucato8f75ede2019-08-12 17:36:36 +0100421 }
Eric Seckler684a4f72019-04-26 14:34:07 +0100422}
423
Primiano Tucci6756fb02019-08-14 15:49:18 +0200424util::Status ProtoTraceTokenizer::ParseClockSnapshot(ConstBytes blob,
425 uint32_t seq_id) {
Eric Seckler9cadb3a2019-11-14 01:38:33 +0000426 std::vector<ClockTracker::ClockValue> clocks;
Primiano Tucci6756fb02019-08-14 15:49:18 +0200427 protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
428 for (auto it = evt.clocks(); it; ++it) {
Primiano Tucci8f7359c2019-10-17 12:59:33 +0100429 protos::pbzero::ClockSnapshot::Clock::Decoder clk(*it);
Primiano Tucci6756fb02019-08-14 15:49:18 +0200430 ClockTracker::ClockId clock_id = clk.clock_id();
431 if (ClockTracker::IsReservedSeqScopedClockId(clk.clock_id())) {
432 if (!seq_id) {
433 return util::ErrStatus(
434 "ClockSnapshot packet is specifying a sequence-scoped clock id "
435 "(%" PRIu64 ") but the TracePacket sequence_id is zero",
436 clock_id);
437 }
438 clock_id = ClockTracker::SeqScopedClockIdToGlobal(seq_id, clk.clock_id());
439 }
Eric Seckler9cadb3a2019-11-14 01:38:33 +0000440 int64_t unit_multiplier_ns =
441 clk.unit_multiplier_ns()
442 ? static_cast<int64_t>(clk.unit_multiplier_ns())
443 : 1;
444 clocks.emplace_back(clock_id, clk.timestamp(), unit_multiplier_ns,
445 clk.is_incremental());
Primiano Tucci6756fb02019-08-14 15:49:18 +0200446 }
Eric Seckler9cadb3a2019-11-14 01:38:33 +0000447 context_->clock_tracker->AddSnapshot(clocks);
Primiano Tucci6756fb02019-08-14 15:49:18 +0200448 return util::OkStatus();
449}
450
Primiano Tuccid933d912018-09-04 09:15:07 +0100451} // namespace trace_processor
452} // namespace perfetto