|  | /* | 
|  | * Copyright (C) 2020 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_QUERY_RESULT_SERIALIZER_H_ | 
|  | #define SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <vector> | 
|  |  | 
|  | #include <limits.h> | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | namespace perfetto { | 
|  |  | 
|  | namespace protos { | 
|  | namespace pbzero { | 
|  | class QueryResult; | 
|  | }  // namespace pbzero | 
|  | }  // namespace protos | 
|  |  | 
|  | namespace trace_processor { | 
|  |  | 
|  | class Iterator; | 
|  | class IteratorImpl; | 
|  |  | 
|  | // This class serializes a TraceProcessor query result (i.e. an Iterator) | 
|  | // into batches of QueryResult (trace_processor.proto). This class | 
|  | // returns results in batches, allowing to deal with O(M) results without | 
|  | // full memory buffering. It works as follows: | 
|  | // - The iterator is passed in the constructor. | 
|  | // - The client is expected to call Serialize(out_buf) until EOF is reached. | 
|  | // - For each Serialize() call, this class will serialize a batch of cells, | 
|  | //   stopping when either when a number of cells (|cells_per_batch_|) is reached | 
|  | //   or when the batch size exceeds (batch_split_threshold_). | 
|  | //   A batch is guaranteed to contain a number of cells that is an integer | 
|  | //   multiple of the column count (i.e. a batch is not truncated in the middle | 
|  | //   of a row). | 
|  | // The intended use case is streaaming these batches onto through a | 
|  | // chunked-encoded HTTP response, or through a repetition of Wasm calls. | 
|  | class QueryResultSerializer { | 
|  | public: | 
|  | static constexpr uint32_t kDefaultBatchSplitThreshold = 128 * 1024; | 
|  | explicit QueryResultSerializer(Iterator); | 
|  | ~QueryResultSerializer(); | 
|  |  | 
|  | // No copy or move. | 
|  | QueryResultSerializer(const QueryResultSerializer&) = delete; | 
|  | QueryResultSerializer& operator=(const QueryResultSerializer&) = delete; | 
|  |  | 
|  | // Appends the data to the passed protozero message. It returns true if more | 
|  | // chunks are available (i.e. it returns NOT(|eof_reached_||)). The caller is | 
|  | // supposed to keep calling this function until it returns false. | 
|  | bool Serialize(protos::pbzero::QueryResult*); | 
|  |  | 
|  | // Like the above but stitches everything together in a vector. Incurs in | 
|  | // extra copies. | 
|  | bool Serialize(std::vector<uint8_t>*); | 
|  |  | 
|  | void set_batch_size_for_testing(uint32_t cells_per_batch, uint32_t thres) { | 
|  | cells_per_batch_ = cells_per_batch; | 
|  | batch_split_threshold_ = thres; | 
|  | } | 
|  |  | 
|  | private: | 
|  | void SerializeMetadata(protos::pbzero::QueryResult*); | 
|  | void SerializeBatch(protos::pbzero::QueryResult*); | 
|  | void MaybeSerializeError(protos::pbzero::QueryResult*); | 
|  |  | 
|  | std::unique_ptr<IteratorImpl> iter_; | 
|  | const uint32_t num_cols_; | 
|  | bool did_write_metadata_ = false; | 
|  | bool eof_reached_ = false; | 
|  | uint32_t col_ = UINT32_MAX; | 
|  |  | 
|  | // These params specify the thresholds for splitting the results in batches, | 
|  | // in terms of: (1) max cells (row x cols); (2) serialized batch size in | 
|  | // bytes, whichever is reached first. Note also that the byte limit is not | 
|  | // 100% accurate and can occasionally yield to batches slighly larger than | 
|  | // the limit (it splits on the next row *after* the limit is hit). | 
|  | // Overridable for testing only. | 
|  | uint32_t cells_per_batch_ = 50000; | 
|  | uint32_t batch_split_threshold_ = kDefaultBatchSplitThreshold; | 
|  | }; | 
|  |  | 
|  | }  // namespace trace_processor | 
|  | }  // namespace perfetto | 
|  |  | 
|  | #endif  // SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_ |