• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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