| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "perfetto/tracing/internal/interceptor_trace_writer.h" |
| |
| #include "perfetto/ext/tracing/core/trace_writer.h" |
| |
| namespace perfetto { |
| namespace internal { |
| |
| // static |
| std::atomic<uint32_t> InterceptorTraceWriter::next_sequence_id_{}; |
| |
| InterceptorTraceWriter::InterceptorTraceWriter( |
| std::unique_ptr<InterceptorBase::ThreadLocalState> tls, |
| InterceptorBase::TracePacketCallback packet_callback, |
| DataSourceStaticState* static_state, |
| uint32_t instance_index) |
| : tls_(std::move(tls)), |
| packet_callback_(std::move(packet_callback)), |
| static_state_(static_state), |
| instance_index_(instance_index), |
| sequence_id_(++next_sequence_id_) {} |
| |
| InterceptorTraceWriter::~InterceptorTraceWriter() = default; |
| |
| protozero::MessageHandle<protos::pbzero::TracePacket> |
| InterceptorTraceWriter::NewTracePacket() { |
| Flush(); |
| auto packet = TraceWriter::TracePacketHandle(cur_packet_.get()); |
| packet->set_trusted_packet_sequence_id(sequence_id_); |
| return packet; |
| } |
| |
| void InterceptorTraceWriter::Flush(std::function<void()> callback) { |
| if (!cur_packet_.empty()) { |
| InterceptorBase::TracePacketCallbackArgs args{}; |
| args.static_state = static_state_; |
| args.instance_index = instance_index_; |
| args.tls = tls_.get(); |
| |
| const auto& slices = cur_packet_.GetSlices(); |
| if (slices.size() == 1) { |
| // Fast path: the current packet fits into a single slice. |
| auto slice_range = slices.begin()->GetUsedRange(); |
| args.packet_data = protozero::ConstBytes{ |
| slice_range.begin, |
| static_cast<size_t>(slice_range.end - slice_range.begin)}; |
| bytes_written_ += static_cast<uint64_t>(args.packet_data.size); |
| packet_callback_(std::move(args)); |
| } else { |
| // Fallback: stitch together multiple slices. |
| auto stitched_data = cur_packet_.SerializeAsArray(); |
| args.packet_data = |
| protozero::ConstBytes{stitched_data.data(), stitched_data.size()}; |
| bytes_written_ += static_cast<uint64_t>(stitched_data.size()); |
| packet_callback_(std::move(args)); |
| } |
| cur_packet_.Reset(); |
| } |
| if (callback) |
| callback(); |
| } |
| |
| void InterceptorTraceWriter::FinishTracePacket() {} |
| |
| uint64_t InterceptorTraceWriter::written() const { |
| return bytes_written_; |
| } |
| |
| } // namespace internal |
| } // namespace perfetto |