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 INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
     18 #define INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
     19 
     20 #include <stddef.h>
     21 
     22 #include <memory>
     23 #include <tuple>
     24 
     25 #include "google/protobuf/io/zero_copy_stream.h"
     26 #include "perfetto/base/export.h"
     27 #include "perfetto/base/logging.h"
     28 #include "perfetto/tracing/core/slice.h"
     29 
     30 namespace perfetto {
     31 
     32 namespace protos {
     33 class TracePacket;  // From protos/trace_packet.pb.h.
     34 }  // namespace protos
     35 
     36 // A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
     37 // (see trace_packet.proto). The TracePacket is decoded only if the Consumer
     38 // requests that. This is to allow Consumer(s) to just stream the packet over
     39 // the network or save it to a file without wasting time decoding it and without
     40 // needing to depend on libprotobuf or the trace_packet.pb.h header.
     41 // If the packets are saved / streamed and not just consumed locally, consumers
     42 // should ensure to preserve the unknown fields in the proto. A consumer, in
     43 // fact, might have an older version .proto which is newer on the producer.
     44 class PERFETTO_EXPORT TracePacket {
     45  public:
     46   using const_iterator = Slices::const_iterator;
     47   using ZeroCopyInputStream = ::google::protobuf::io::ZeroCopyInputStream;
     48 
     49   // The field id of protos::Trace::packet, static_assert()-ed in the unittest.
     50   static constexpr uint32_t kPacketFieldNumber = 1;
     51 
     52   TracePacket();
     53   ~TracePacket();
     54   TracePacket(TracePacket&&) noexcept;
     55   TracePacket& operator=(TracePacket&&);
     56 
     57   // Accesses all the raw slices in the packet, for saving them to file/network.
     58   const Slices& slices() const { return slices_; }
     59 
     60   // Decodes the packet. This function requires that the caller:
     61   // 1) Does #include "perfetto/trace/trace_packet.pb.h"
     62   // 2) Links against the //protos/trace:lite target.
     63   // The core service code deliberately doesn't link against that in order to
     64   // avoid binary bloat. This is the reason why this is a templated function.
     65   // It doesn't need to be (i.e. the caller should not specify the template
     66   // argument) but doing so prevents the compiler trying to resolve the
     67   // TracePacket type until it's needed, in which case the caller needs (1).
     68   template <typename TracePacketType = protos::TracePacket>
     69   bool Decode(TracePacketType* packet) const {
     70     std::unique_ptr<ZeroCopyInputStream> istr = CreateSlicedInputStream();
     71     return packet->ParseFromZeroCopyStream(istr.get());
     72   }
     73 
     74   // Mutator, used only by the service and tests.
     75   void AddSlice(Slice);
     76 
     77   // Does not copy / take ownership of the memory of the slice. The TracePacket
     78   // will be valid only as long as the original buffer is valid.
     79   void AddSlice(const void* start, size_t size);
     80 
     81   // Total size of all slices.
     82   size_t size() const { return size_; }
     83 
     84   // Generates a protobuf preamble suitable to represent this packet as a
     85   // repeated field within a root trace.proto message.
     86   // Returns a pointer to a buffer, owned by this class, containing the preamble
     87   // and its size.
     88   std::tuple<char*, size_t> GetProtoPreamble();
     89 
     90  private:
     91   TracePacket(const TracePacket&) = delete;
     92   TracePacket& operator=(const TracePacket&) = delete;
     93 
     94   std::unique_ptr<ZeroCopyInputStream> CreateSlicedInputStream() const;
     95 
     96   Slices slices_;     // Not owned.
     97   size_t size_ = 0;   // SUM(slice.size for slice in slices_).
     98   char preamble_[8];  // Deliberately not initialized.
     99 
    100   // Remember to update the move operators and their unittest if adding new
    101   // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on
    102   // std::move(TracePacket) to clear up the moved-from instance.
    103 };
    104 
    105 }  // namespace perfetto
    106 
    107 #endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
    108