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