1 /* 2 * Copyright (C) 2020 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_QUERY_RESULT_SERIALIZER_H_ 18 #define SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_ 19 20 #include <memory> 21 #include <vector> 22 23 #include <limits.h> 24 #include <stddef.h> 25 #include <stdint.h> 26 27 namespace perfetto { 28 29 namespace protos { 30 namespace pbzero { 31 class QueryResult; 32 } // namespace pbzero 33 } // namespace protos 34 35 namespace trace_processor { 36 37 class Iterator; 38 class IteratorImpl; 39 40 // This class serializes a TraceProcessor query result (i.e. an Iterator) 41 // into batches of QueryResult (trace_processor.proto). This class 42 // returns results in batches, allowing to deal with O(M) results without 43 // full memory buffering. It works as follows: 44 // - The iterator is passed in the constructor. 45 // - The client is expected to call Serialize(out_buf) until EOF is reached. 46 // - For each Serialize() call, this class will serialize a batch of cells, 47 // stopping when either when a number of cells (|cells_per_batch_|) is reached 48 // or when the batch size exceeds (batch_split_threshold_). 49 // A batch is guaranteed to contain a number of cells that is an integer 50 // multiple of the column count (i.e. a batch is not truncated in the middle 51 // of a row). 52 // The intended use case is streaaming these batches onto through a 53 // chunked-encoded HTTP response, or through a repetition of Wasm calls. 54 class QueryResultSerializer { 55 public: 56 static constexpr uint32_t kDefaultBatchSplitThreshold = 128 * 1024; 57 explicit QueryResultSerializer(Iterator); 58 ~QueryResultSerializer(); 59 60 // No copy or move. 61 QueryResultSerializer(const QueryResultSerializer&) = delete; 62 QueryResultSerializer& operator=(const QueryResultSerializer&) = delete; 63 64 // Appends the data to the passed protozero message. It returns true if more 65 // chunks are available (i.e. it returns NOT(|eof_reached_||)). The caller is 66 // supposed to keep calling this function until it returns false. 67 bool Serialize(protos::pbzero::QueryResult*); 68 69 // Like the above but stitches everything together in a vector. Incurs in 70 // extra copies. 71 bool Serialize(std::vector<uint8_t>*); 72 set_batch_size_for_testing(uint32_t cells_per_batch,uint32_t thres)73 void set_batch_size_for_testing(uint32_t cells_per_batch, uint32_t thres) { 74 cells_per_batch_ = cells_per_batch; 75 batch_split_threshold_ = thres; 76 } 77 78 private: 79 void SerializeMetadata(protos::pbzero::QueryResult*); 80 void SerializeBatch(protos::pbzero::QueryResult*); 81 void MaybeSerializeError(protos::pbzero::QueryResult*); 82 83 std::unique_ptr<IteratorImpl> iter_; 84 const uint32_t num_cols_; 85 bool did_write_metadata_ = false; 86 bool eof_reached_ = false; 87 uint32_t col_ = UINT32_MAX; 88 89 // These params specify the thresholds for splitting the results in batches, 90 // in terms of: (1) max cells (row x cols); (2) serialized batch size in 91 // bytes, whichever is reached first. Note also that the byte limit is not 92 // 100% accurate and can occasionally yield to batches slighly larger than 93 // the limit (it splits on the next row *after* the limit is hit). 94 // Overridable for testing only. 95 uint32_t cells_per_batch_ = 50000; 96 uint32_t batch_split_threshold_ = kDefaultBatchSplitThreshold; 97 }; 98 99 } // namespace trace_processor 100 } // namespace perfetto 101 102 #endif // SRC_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_ 103