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/protozero/field.h" 31 #include "perfetto/trace_processor/basic_types.h" 32 33 namespace perfetto { 34 35 namespace protos::pbzero { 36 class ComputeMetricResult; 37 class DisableAndReadMetatraceResult; 38 } // namespace protos::pbzero 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 = 87 std::function<void(const void* /*data*/, uint32_t /*len*/)>; SetRpcResponseFunction(RpcResponseFunction f)88 void SetRpcResponseFunction(RpcResponseFunction f) { 89 rpc_response_fn_ = std::move(f); 90 } 91 92 // 2. TraceProcessor legacy RPC endpoints. 93 // The methods below are exposed for the old RPC interfaces, where each RPC 94 // implementation deals with the method demuxing: (i) wasm_bridge.cc has one 95 // exported C function per method (going away soon); (ii) httpd.cc has one 96 // REST endpoint per method. Over time this turned out to have too much 97 // duplicated boilerplate and we moved to the byte-pipe model above. 98 // We still keep these endpoints around, because httpd.cc still exposes the 99 // individual REST endpoints to legacy clients (TP's Python API). The 100 // mainteinance cost of those is very low. Both the new byte-pipe and the 101 // old endpoints run exactly the same code. The {de,}serialization format is 102 // the same, the only difference is only who does the method demuxing. 103 // The methods of this class are mirrors (modulo {un,}marshalling of args) of 104 // the corresponding names in trace_processor.h . See that header for docs. 105 106 base::Status Parse(const uint8_t*, size_t); 107 base::Status NotifyEndOfFile(); 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 ResetTraceProcessor(const uint8_t*, size_t); 134 base::Status RegisterSqlPackage(protozero::ConstBytes); 135 void ResetTraceProcessorInternal(const Config&); 136 void MaybePrintProgress(); 137 Iterator QueryInternal(const uint8_t*, size_t); 138 void ComputeMetricInternal(const uint8_t*, 139 size_t, 140 protos::pbzero::ComputeMetricResult*); 141 void DisableAndReadMetatraceInternal( 142 protos::pbzero::DisableAndReadMetatraceResult*); 143 144 Config trace_processor_config_; 145 std::unique_ptr<TraceProcessor> trace_processor_; 146 RpcResponseFunction rpc_response_fn_; 147 protozero::ProtoRingBuffer rxbuf_; 148 int64_t tx_seq_id_ = 0; 149 int64_t rx_seq_id_ = 0; 150 bool eof_ = false; 151 int64_t t_parse_started_ = 0; 152 size_t bytes_last_progress_ = 0; 153 size_t bytes_parsed_ = 0; 154 }; 155 156 } // namespace trace_processor 157 } // namespace perfetto 158 159 #endif // SRC_TRACE_PROCESSOR_RPC_RPC_H_ 160