| /* | 
 |  * Copyright (C) 2019 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef SRC_TRACE_PROCESSOR_RPC_RPC_H_ | 
 | #define SRC_TRACE_PROCESSOR_RPC_RPC_H_ | 
 |  | 
 | #include <functional> | 
 | #include <memory> | 
 | #include <vector> | 
 |  | 
 | #include <stddef.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include "perfetto/trace_processor/basic_types.h" | 
 | #include "perfetto/trace_processor/status.h" | 
 | #include "src/protozero/proto_ring_buffer.h" | 
 |  | 
 | namespace perfetto { | 
 |  | 
 | namespace protos { | 
 | namespace pbzero { | 
 | class ComputeMetricResult; | 
 | class DisableAndReadMetatraceResult; | 
 | }  // namespace pbzero | 
 | }  // namespace protos | 
 |  | 
 | namespace trace_processor { | 
 |  | 
 | class Iterator; | 
 | class TraceProcessor; | 
 |  | 
 | // This class handles the binary {,un}marshalling for the Trace Processor RPC | 
 | // API (see protos/perfetto/trace_processor/trace_processor.proto). | 
 | // This is to deal with cases where the client of the trace processor is not | 
 | // some in-process C++ code but a remote process: | 
 | // There are two use cases of this: | 
 | //   1. The JS<>WASM interop for the web-based UI. | 
 | //   2. The HTTP RPC mode of trace_processor_shell that allows the UI to talk | 
 | //      to a native trace processor instead of the bundled WASM one. | 
 | // This class has (a subset of) the same methods of the public TraceProcessor | 
 | // interface, but the methods just take and return proto-encoded binary buffers. | 
 | // This class does NOT define how the transport works (e.g. HTTP vs WASM interop | 
 | // calls), it just deals with {,un}marshalling. | 
 | // This class internally creates and owns a TraceProcessor instance, which | 
 | // lifetime is tied to the lifetime of the Rpc instance. | 
 | class Rpc { | 
 |  public: | 
 |   // The unique_ptr argument is optional. If non-null it will adopt the passed | 
 |   // instance and allow to directly query that. If null, a new instanace will be | 
 |   // created internally by calling Parse(). | 
 |   explicit Rpc(std::unique_ptr<TraceProcessor>); | 
 |   Rpc(); | 
 |   ~Rpc(); | 
 |  | 
 |   // 1. TraceProcessor byte-pipe RPC interface. | 
 |   // This is a bidirectional channel with a remote TraceProcessor instance. All | 
 |   // it needs is a byte-oriented pipe (e.g., a TCP socket, a pipe(2) between two | 
 |   // processes or a postmessage channel in the JS+Wasm case). The messages | 
 |   // exchanged on these pipes are TraceProcessorRpc protos (defined in | 
 |   // trace_processor.proto). This has been introduced in Perfetto v15. | 
 |  | 
 |   // Pushes data received by the RPC channel into the parser. Inbound messages | 
 |   // are tokenized and turned into TraceProcessor method invocations. |data| | 
 |   // does not need to be a whole TraceProcessorRpc message. It can be a portion | 
 |   // of it or a union of >1 messages. | 
 |   // Responses are sent throught the RpcResponseFunction (below). | 
 |   void OnRpcRequest(const void* data, size_t len); | 
 |  | 
 |   // The size argument is a uint32_t and not size_t to avoid ABI mismatches | 
 |   // with Wasm, where size_t = uint32_t. | 
 |   // (nullptr, 0) has the semantic of "close the channel" and is issued when an | 
 |   // unrecoverable wire-protocol framing error is detected. | 
 |   using RpcResponseFunction = void (*)(const void* /*data*/, uint32_t /*len*/); | 
 |   void SetRpcResponseFunction(RpcResponseFunction f) { rpc_response_fn_ = f; } | 
 |  | 
 |   // 2. TraceProcessor legacy RPC endpoints. | 
 |   // The methods below are exposed for the old RPC interfaces, where each RPC | 
 |   // implementation deals with the method demuxing: (i) wasm_bridge.cc has one | 
 |   // exported C function per method (going away soon); (ii) httpd.cc has one | 
 |   // REST endpoint per method. Over time this turned out to have too much | 
 |   // duplicated boilerplate and we moved to the byte-pipe model above. | 
 |   // We still keep these endpoints around, because httpd.cc still  exposes the | 
 |   // individual REST endpoints to legacy clients (TP's Python API). The | 
 |   // mainteinance cost of those is very low. Both the new byte-pipe and the | 
 |   // old endpoints run exactly the same code. The {de,}serialization format is | 
 |   // the same, the only difference is only who does the method demuxing. | 
 |   // The methods of this class are mirrors (modulo {un,}marshalling of args) of | 
 |   // the corresponding names in trace_processor.h . See that header for docs. | 
 |  | 
 |   util::Status Parse(const uint8_t* data, size_t len); | 
 |   void NotifyEndOfFile(); | 
 |   void ResetTraceProcessor(const uint8_t* args, size_t len); | 
 |   std::string GetCurrentTraceName(); | 
 |   std::vector<uint8_t> ComputeMetric(const uint8_t* data, size_t len); | 
 |   void EnableMetatrace(const uint8_t* data, size_t len);  // EnableMetatraceArgs | 
 |   std::vector<uint8_t> DisableAndReadMetatrace(); | 
 |   std::vector<uint8_t> GetStatus(); | 
 |  | 
 |   // Creates a new RPC session by deleting all tables and views that have been | 
 |   // created (by the UI or user) after the trace was loaded; built-in | 
 |   // tables/view created by the ingestion process are preserved. | 
 |   void RestoreInitialTables(); | 
 |  | 
 |   // Runs a query and returns results in batch. Each batch is a proto-encoded | 
 |   // TraceProcessor.QueryResult message and contains a variable number of rows. | 
 |   // The callbacks are called inline, so the whole callstack looks as follows: | 
 |   // Query(..., callback) | 
 |   //   callback(..., has_more=true) | 
 |   //   ... | 
 |   //   callback(..., has_more=false) | 
 |   //   (Query() returns at this point). | 
 |   // TODO(primiano): long-term this API should change and be turned into a | 
 |   // bidirectional streaming api (see go/imperative-metrics). The problem with | 
 |   // the current design is that it holds the callstack until the query is done | 
 |   // and makes nested query hard as they cause re-entrancy. It's okay for now | 
 |   // but will change soon. | 
 |   using QueryResultBatchCallback = std::function< | 
 |       void(const uint8_t* /*buf*/, size_t /*len*/, bool /*has_more*/)>; | 
 |   void Query(const uint8_t* args, size_t len, QueryResultBatchCallback); | 
 |  | 
 |  private: | 
 |   void ParseRpcRequest(const uint8_t* data, size_t len); | 
 |   void ResetTraceProcessorInternal(const Config& config); | 
 |   void MaybePrintProgress(); | 
 |   Iterator QueryInternal(const uint8_t* args, size_t len); | 
 |   void ComputeMetricInternal(const uint8_t* args, | 
 |                              size_t len, | 
 |                              protos::pbzero::ComputeMetricResult*); | 
 |   void DisableAndReadMetatraceInternal( | 
 |       protos::pbzero::DisableAndReadMetatraceResult*); | 
 |  | 
 |   Config trace_processor_config_; | 
 |   std::unique_ptr<TraceProcessor> trace_processor_; | 
 |   RpcResponseFunction rpc_response_fn_; | 
 |   protozero::ProtoRingBuffer rxbuf_; | 
 |   int64_t tx_seq_id_ = 0; | 
 |   int64_t rx_seq_id_ = 0; | 
 |   bool eof_ = false; | 
 |   int64_t t_parse_started_ = 0; | 
 |   size_t bytes_last_progress_ = 0; | 
 |   size_t bytes_parsed_ = 0; | 
 | }; | 
 |  | 
 | }  // namespace trace_processor | 
 | }  // namespace perfetto | 
 |  | 
 | #endif  // SRC_TRACE_PROCESSOR_RPC_RPC_H_ |