Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2017 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_TRACING_CORE_TRACE_WRITER_IMPL_H_
     18 #define SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
     19 
     20 #include "perfetto/protozero/message_handle.h"
     21 #include "perfetto/protozero/scattered_stream_writer.h"
     22 #include "perfetto/tracing/core/basic_types.h"
     23 #include "perfetto/tracing/core/shared_memory_abi.h"
     24 #include "perfetto/tracing/core/trace_writer.h"
     25 #include "src/tracing/core/patch_list.h"
     26 
     27 namespace perfetto {
     28 
     29 class SharedMemoryArbiterImpl;
     30 
     31 // See //include/perfetto/tracing/core/trace_writer.h for docs.
     32 class TraceWriterImpl : public TraceWriter,
     33                         public protozero::ScatteredStreamWriter::Delegate {
     34  public:
     35   // TracePacketHandle is defined in trace_writer.h
     36   TraceWriterImpl(SharedMemoryArbiterImpl*, WriterID, BufferID);
     37   ~TraceWriterImpl() override;
     38 
     39   // TraceWriter implementation. See documentation in trace_writer.h.
     40   TracePacketHandle NewTracePacket() override;
     41   void Flush(std::function<void()> callback = {}) override;
     42   WriterID writer_id() const override;
     43   bool SetFirstChunkId(ChunkID) override;
     44   uint64_t written() const override {
     45     return protobuf_stream_writer_.written();
     46   }
     47 
     48   void ResetChunkForTesting() { cur_chunk_ = SharedMemoryABI::Chunk(); }
     49 
     50  private:
     51   TraceWriterImpl(const TraceWriterImpl&) = delete;
     52   TraceWriterImpl& operator=(const TraceWriterImpl&) = delete;
     53 
     54   // ScatteredStreamWriter::Delegate implementation.
     55   protozero::ContiguousMemoryRange GetNewBuffer() override;
     56 
     57   // The per-producer arbiter that coordinates access to the shared memory
     58   // buffer from several threads.
     59   SharedMemoryArbiterImpl* const shmem_arbiter_;
     60 
     61   // ID of the current writer.
     62   const WriterID id_;
     63 
     64   // This is just copied back into the chunk header.
     65   // See comments in data_source_config.proto for |target_buffer|.
     66   const BufferID target_buffer_;
     67 
     68   // Monotonic (% wrapping) sequence id of the chunk. Together with the WriterID
     69   // this allows the Service to reconstruct the linear sequence of packets.
     70   ChunkID next_chunk_id_ = 0;
     71 
     72   // The chunk we are holding onto (if any).
     73   SharedMemoryABI::Chunk cur_chunk_;
     74 
     75   // Passed to protozero message to write directly into |cur_chunk_|. It
     76   // keeps track of the write pointer. It calls us back (GetNewBuffer()) when
     77   // |cur_chunk_| is filled.
     78   protozero::ScatteredStreamWriter protobuf_stream_writer_;
     79 
     80   // The packet returned via NewTracePacket(). Its owned by this class,
     81   // TracePacketHandle has just a pointer to it.
     82   std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
     83 
     84   // The start address of |cur_packet_| within |cur_chunk_|. Used to figure out
     85   // fragments sizes when a TracePacket write is interrupted by GetNewBuffer().
     86   uint8_t* cur_fragment_start_ = nullptr;
     87 
     88   // true if we received a call to GetNewBuffer() after NewTracePacket(),
     89   // false if GetNewBuffer() happened during NewTracePacket() prologue, while
     90   // starting the TracePacket header.
     91   bool fragmenting_packet_ = false;
     92 
     93   // Set to |true| when the current chunk contains the maximum number of packets
     94   // a chunk can contain. When this is |true|, the next packet requires starting
     95   // a new chunk.
     96   bool reached_max_packets_per_chunk_ = false;
     97 
     98   // When a packet is fragmented across different chunks, the |size_field| of
     99   // the outstanding nested protobuf messages is redirected onto Patch entries
    100   // in this list at the time the Chunk is returned (because at that point we
    101   // have to release the ownership of the current Chunk). This list will be
    102   // later sent out-of-band to the tracing service, who will patch the required
    103   // chunks, if they are still around.
    104   PatchList patch_list_;
    105 };
    106 
    107 }  // namespace perfetto
    108 
    109 #endif  // SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
    110