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_RPC_RPC_H_ 18 #define SRC_TRACE_PROCESSOR_RPC_RPC_H_ 19 20 #include <cstddef> 21 #include <cstdint> 22 #include <functional> 23 #include <memory> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 28 #include "perfetto/base/status.h" 29 #include "perfetto/ext/protozero/proto_ring_buffer.h" 30 #include "perfetto/trace_processor/basic_types.h" 31 32 namespace perfetto { 33 34 namespace protos::pbzero { 35 class ComputeMetricResult; 36 class DisableAndReadMetatraceResult; 37 } // namespace protos::pbzero 38 39 namespace trace_processor { 40 41 class Iterator; 42 class TraceProcessor; 43 44 // This class handles the binary {,un}marshalling for the Trace Processor RPC 45 // API (see protos/perfetto/trace_processor/trace_processor.proto). 46 // This is to deal with cases where the client of the trace processor is not 47 // some in-process C++ code but a remote process: 48 // There are two use cases of this: 49 // 1. The JS<>WASM interop for the web-based UI. 50 // 2. The HTTP RPC mode of trace_processor_shell that allows the UI to talk 51 // to a native trace processor instead of the bundled WASM one. 52 // This class has (a subset of) the same methods of the public TraceProcessor 53 // interface, but the methods just take and return proto-encoded binary buffers. 54 // This class does NOT define how the transport works (e.g. HTTP vs WASM interop 55 // calls), it just deals with {,un}marshalling. 56 // This class internally creates and owns a TraceProcessor instance, which 57 // lifetime is tied to the lifetime of the Rpc instance. 58 class Rpc { 59 public: 60 // The unique_ptr argument is optional. If non-null it will adopt the passed 61 // instance and allow to directly query that. If null, a new instanace will be 62 // created internally by calling Parse(). 63 explicit Rpc(std::unique_ptr<TraceProcessor>); 64 Rpc(); 65 ~Rpc(); 66 67 // 1. TraceProcessor byte-pipe RPC interface. 68 // This is a bidirectional channel with a remote TraceProcessor instance. All 69 // it needs is a byte-oriented pipe (e.g., a TCP socket, a pipe(2) between two 70 // processes or a postmessage channel in the JS+Wasm case). The messages 71 // exchanged on these pipes are TraceProcessorRpc protos (defined in 72 // trace_processor.proto). This has been introduced in Perfetto v15. 73 74 // Pushes data received by the RPC channel into the parser. Inbound messages 75 // are tokenized and turned into TraceProcessor method invocations. |data| 76 // does not need to be a whole TraceProcessorRpc message. It can be a portion 77 // of it or a union of >1 messages. 78 // Responses are sent throught the RpcResponseFunction (below). 79 void OnRpcRequest(const void* data, size_t len); 80 81 // The size argument is a uint32_t and not size_t to avoid ABI mismatches 82 // with Wasm, where size_t = uint32_t. 83 // (nullptr, 0) has the semantic of "close the channel" and is issued when an 84 // unrecoverable wire-protocol framing error is detected. 85 using RpcResponseFunction = 86 std::function<void(const void* /*data*/, uint32_t /*len*/)>; SetRpcResponseFunction(RpcResponseFunction f)87 void SetRpcResponseFunction(RpcResponseFunction f) { 88 rpc_response_fn_ = std::move(f); 89 } 90 91 // 2. TraceProcessor legacy RPC endpoints. 92 // The methods below are exposed for the old RPC interfaces, where each RPC 93 // implementation deals with the method demuxing: (i) wasm_bridge.cc has one 94 // exported C function per method (going away soon); (ii) httpd.cc has one 95 // REST endpoint per method. Over time this turned out to have too much 96 // duplicated boilerplate and we moved to the byte-pipe model above. 97 // We still keep these endpoints around, because httpd.cc still exposes the 98 // individual REST endpoints to legacy clients (TP's Python API). The 99 // mainteinance cost of those is very low. Both the new byte-pipe and the 100 // old endpoints run exactly the same code. The {de,}serialization format is 101 // the same, the only difference is only who does the method demuxing. 102 // The methods of this class are mirrors (modulo {un,}marshalling of args) of 103 // the corresponding names in trace_processor.h . See that header for docs. 104 105 base::Status Parse(const uint8_t*, size_t); 106 void NotifyEndOfFile(); 107 void ResetTraceProcessor(const uint8_t*, size_t); 108 std::string GetCurrentTraceName(); 109 std::vector<uint8_t> ComputeMetric(const uint8_t*, size_t); 110 void EnableMetatrace(const uint8_t*, size_t); 111 std::vector<uint8_t> DisableAndReadMetatrace(); 112 std::vector<uint8_t> GetStatus(); 113 114 // Creates a new RPC session by deleting all tables and views that have been 115 // created (by the UI or user) after the trace was loaded; built-in 116 // tables/view created by the ingestion process are preserved. 117 void RestoreInitialTables(); 118 119 // Runs a query and returns results in batch. Each batch is a proto-encoded 120 // TraceProcessor.QueryResult message and contains a variable number of rows. 121 // The callbacks are called inline, so the whole callstack looks as follows: 122 // Query(..., callback) 123 // callback(..., has_more=true) 124 // ... 125 // callback(..., has_more=false) 126 // (Query() returns at this point). 127 using QueryResultBatchCallback = std::function< 128 void(const uint8_t* /*buf*/, size_t /*len*/, bool /*has_more*/)>; 129 void Query(const uint8_t*, size_t, const QueryResultBatchCallback&); 130 131 private: 132 void ParseRpcRequest(const uint8_t*, size_t); 133 void ResetTraceProcessorInternal(const Config&); 134 void MaybePrintProgress(); 135 Iterator QueryInternal(const uint8_t*, size_t); 136 void ComputeMetricInternal(const uint8_t*, 137 size_t, 138 protos::pbzero::ComputeMetricResult*); 139 void DisableAndReadMetatraceInternal( 140 protos::pbzero::DisableAndReadMetatraceResult*); 141 142 Config trace_processor_config_; 143 std::unique_ptr<TraceProcessor> trace_processor_; 144 RpcResponseFunction rpc_response_fn_; 145 protozero::ProtoRingBuffer rxbuf_; 146 int64_t tx_seq_id_ = 0; 147 int64_t rx_seq_id_ = 0; 148 bool eof_ = false; 149 int64_t t_parse_started_ = 0; 150 size_t bytes_last_progress_ = 0; 151 size_t bytes_parsed_ = 0; 152 }; 153 154 } // namespace trace_processor 155 } // namespace perfetto 156 157 #endif // SRC_TRACE_PROCESSOR_RPC_RPC_H_ 158