1 /* 2 * Copyright (C) 2024 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_UTIL_FILE_BUFFER_H_ 18 #define SRC_TRACE_PROCESSOR_UTIL_FILE_BUFFER_H_ 19 20 #include <cstddef> 21 #include <optional> 22 23 #include "perfetto/ext/base/circular_queue.h" 24 #include "perfetto/trace_processor/trace_blob_view.h" 25 26 namespace perfetto::trace_processor::util { 27 28 // Helper class that exposes a window into the contents of a file. Data can be 29 // appended to the end of the buffer (increasing the size of the window) or 30 // removed from the front (decreasing the size of the window). 31 // 32 // TraceProcessor reads trace files in chunks and streams those to the 33 // `ChunkedTraceReader` instance. But sometimes the reader needs to look into 34 // the future (i.e. some data that has not yet arrived) before being able to 35 // process the current data. In such a case the reader would have to buffer data 36 // until the "future" data arrives. This class encapsulates that functionality. 37 class FileBuffer { 38 public: 39 // Trivial empty ctor. 40 FileBuffer() = default; 41 empty()42 bool empty() const { return data_.empty(); } 43 44 // Returns the offset to the start of the buffered window of data. file_offset()45 size_t file_offset() const { 46 return data_.empty() ? end_offset_ : data_.front().file_offset; 47 } 48 49 // Adds a `TraceBlobView` at the back. 50 void PushBack(TraceBlobView view); 51 52 // Shrinks the buffer by dropping data from the front of the buffer until the 53 // given offset is reached. If not enough data is present as much data as 54 // possible will be dropped and `false` will be returned. 55 // ATTENTION: If `offset` < 'file_offset()' (i.e. you try to access data 56 // previously popped) this method will CHECK fail. 57 bool PopFrontUntil(size_t offset); 58 59 // Shrinks the buffer by dropping `bytes` from the front of the buffer. If not 60 // enough data is present as much data as possible will be dropped and `false` 61 // will be returned. PopFrontBytes(size_t bytes)62 bool PopFrontBytes(size_t bytes) { 63 return PopFrontUntil(file_offset() + bytes); 64 } 65 66 // Similar to `TraceBlobView::slice_off`, creates a slice with data starting 67 // at `offset` and of the given `length`. This method might need to allocate a 68 // new buffer and copy data into it (if the requested data spans multiple 69 // TraceBlobView instances). If not enough data is present `std::nullopt` is 70 // returned. 71 // 72 // ATTENTION: If `offset` < 'file_offset()' (i.e. you try to access data 73 // previously popped) this method will CHECK fail. 74 std::optional<TraceBlobView> SliceOff(size_t offset, size_t length) const; 75 76 private: 77 struct Entry { 78 // File offset of the first byte in `data`. 79 size_t file_offset; 80 TraceBlobView data; 81 }; 82 using Iterator = base::CircularQueue<Entry>::Iterator; 83 // Finds the `TraceBlobView` at `offset` and returns a slice starting at that 84 // offset and spanning the rest of the `TraceBlobView`. It also returns an 85 // iterator to the next `TraceBlobView` instance (which might be `end()`). 86 Iterator FindEntryWithOffset(size_t offset) const; 87 end()88 Iterator end() const { return data_.end(); } 89 90 // CircularQueue has no const_iterator, so mutable is needed to access it from 91 // const methods. 92 // CircularQueue has no const_iterator, so mutable is needed to access it from 93 // const methods. 94 mutable base::CircularQueue<Entry> data_; 95 size_t end_offset_ = 0; 96 }; 97 98 } // namespace perfetto::trace_processor::util 99 100 #endif // SRC_TRACE_PROCESSOR_UTIL_FILE_BUFFER_H_ 101