1 /* 2 * Copyright (C) 2019 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_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_ 19 20 #include "perfetto/ext/base/optional.h" 21 #include "perfetto/trace_processor/status.h" 22 #include "src/trace_processor/importers/common/trace_blob_view.h" 23 24 namespace perfetto { 25 26 namespace protos { 27 namespace pbzero { 28 class TraceConfig_Decoder; 29 class TracePacket_Decoder; 30 } // namespace pbzero 31 } // namespace protos 32 33 namespace trace_processor { 34 35 class PacketSequenceState; 36 struct TimestampedTracePiece; 37 class TraceProcessorContext; 38 39 // This file contains a base class for ProtoTraceReader/Parser modules. 40 // A module implements support for a subset of features of the TracePacket 41 // proto format. 42 // To add and integrate a new module: 43 // (1) Add MyModule as a subclass of ProtoImporterModule, 44 // overriding the TokenizePacket(), ParsePacket() and/or ParseTraceConfig() 45 // methods. 46 // (2) In the constructor call the RegisterForField method for every field 47 // that the module knows how to handle. 48 // (3) Create a module instance and add it to TraceProcessorContext's |modules| 49 // vector in either default_modules.cc or additional_modules.cc. 50 // See GraphicsEventModule for an example. 51 52 class ModuleResult { 53 public: 54 // Allow auto conversion from util::Status to Handled / Error result. ModuleResult(util::Status status)55 ModuleResult(util::Status status) 56 : ignored_(false), 57 error_(status.ok() ? base::nullopt 58 : base::make_optional(status.message())) {} 59 60 // Constructs a result that indicates the module ignored the packet and is 61 // deferring the handling of the packet to other modules. Ignored()62 static ModuleResult Ignored() { return ModuleResult(true); } 63 64 // Constructs a result that indicates the module handled the packet. Other 65 // modules will not be notified about the packet. Handled()66 static ModuleResult Handled() { return ModuleResult(false); } 67 68 // Constructs a result that indicates an error condition while handling the 69 // packet. Other modules will not be notified about the packet. Error(const std::string & message)70 static ModuleResult Error(const std::string& message) { 71 return ModuleResult(message); 72 } 73 ignored()74 bool ignored() const { return ignored_; } ok()75 bool ok() const { return !error_.has_value(); } message()76 const std::string& message() const { return *error_; } 77 ToStatus()78 util::Status ToStatus() const { 79 PERFETTO_DCHECK(!ignored_); 80 if (error_) 81 return util::Status(*error_); 82 return util::OkStatus(); 83 } 84 85 private: ModuleResult(bool ignored)86 explicit ModuleResult(bool ignored) : ignored_(ignored) {} ModuleResult(const std::string & error)87 explicit ModuleResult(const std::string& error) 88 : ignored_(false), error_(error) {} 89 90 bool ignored_; 91 base::Optional<std::string> error_; 92 }; 93 94 // Base class for modules. 95 class ProtoImporterModule { 96 public: 97 ProtoImporterModule(); 98 99 virtual ~ProtoImporterModule(); 100 101 // Called by ProtoTraceReader during the tokenization stage, i.e. before 102 // sorting. It's called for each TracePacket that contains fields for which 103 // the module was registered. If this returns a result other than 104 // ModuleResult::Ignored(), tokenization of the packet will be aborted after 105 // the module. 106 virtual ModuleResult TokenizePacket( 107 const protos::pbzero::TracePacket_Decoder&, 108 TraceBlobView* packet, 109 int64_t packet_timestamp, 110 PacketSequenceState*, 111 uint32_t field_id); 112 113 // Called by ProtoTraceReader during the tokenization stage i.e. before 114 // sorting. Indicates that sequence with id |packet_sequence_id| has cleared 115 // its incremental state. This should be used to clear any cached state the 116 // tokenizer has built up while reading packets until this point for this 117 // packet sequence. OnIncrementalStateCleared(uint32_t)118 virtual void OnIncrementalStateCleared(uint32_t /* packet_sequence_id */) {} 119 120 // Called by ProtoTraceParser after the sorting stage for each non-ftrace 121 // TracePacket that contains fields for which the module was registered. 122 virtual void ParsePacket(const protos::pbzero::TracePacket_Decoder&, 123 const TimestampedTracePiece&, 124 uint32_t field_id); 125 126 // Called by ProtoTraceParser for trace config packets after the sorting 127 // stage, on all existing modules. 128 virtual void ParseTraceConfig(const protos::pbzero::TraceConfig_Decoder&); 129 NotifyEndOfFile()130 virtual void NotifyEndOfFile() {} 131 132 protected: 133 void RegisterForField(uint32_t field_id, TraceProcessorContext*); 134 }; 135 136 } // namespace trace_processor 137 } // namespace perfetto 138 139 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_ 140