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