blob: 394992cab84ef0c0859503b413de79fb52e3f41e [file] [log] [blame]
Brian Silvermanf51499a2020-09-21 12:49:08 -07001#ifndef AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_
2#define AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_
3
4#include "absl/types/span.h"
Tyler Chatow2015bc62021-08-04 21:15:09 -07005#include "flatbuffers/flatbuffers.h"
Austin Schuh48d10d62022-10-16 22:19:23 -07006#include "glog/logging.h"
Brian Silvermanf51499a2020-09-21 12:49:08 -07007
Philipp Schrader790cb542023-07-05 21:06:52 -07008#include "aos/containers/resizeable_buffer.h"
9#include "aos/events/logging/logger_generated.h"
10
Brian Silvermanf51499a2020-09-21 12:49:08 -070011namespace aos::logger {
12
Austin Schuh48d10d62022-10-16 22:19:23 -070013// Interface to encode data as it is written to a file.
14class DataEncoder {
Brian Silvermanf51499a2020-09-21 12:49:08 -070015 public:
Austin Schuh48d10d62022-10-16 22:19:23 -070016 virtual ~DataEncoder() = default;
Brian Silvermanf51499a2020-09-21 12:49:08 -070017
Austin Schuh48d10d62022-10-16 22:19:23 -070018 // Interface to copy data into a buffer.
19 class Copier {
20 public:
21 Copier(size_t size) : size_(size) {}
22
23 // Returns the data this will write.
24 size_t size() const { return size_; }
25
26 // Writes size() bytes to data, and returns the data written.
Austin Schuh71a40d42023-02-04 21:22:22 -080027 [[nodiscard]] virtual size_t Copy(uint8_t *data, size_t start_byte,
28 size_t end_byte) = 0;
Austin Schuh48d10d62022-10-16 22:19:23 -070029
30 private:
31 size_t size_;
32 };
33
Austin Schuh8bdfc492023-02-11 12:53:13 -080034 // Copies a span. The span must have a longer lifetime than the coppier is
Austin Schuh48d10d62022-10-16 22:19:23 -070035 // being used.
36 class SpanCopier : public Copier {
37 public:
38 SpanCopier(absl::Span<const uint8_t> data)
39 : Copier(data.size()), data_(data) {
Austin Schuh71a40d42023-02-04 21:22:22 -080040 CHECK(data_.data() != nullptr);
Austin Schuh48d10d62022-10-16 22:19:23 -070041 }
42
Austin Schuh71a40d42023-02-04 21:22:22 -080043 size_t Copy(uint8_t *data, size_t start_byte, size_t end_byte) final {
44 DCHECK_LE(start_byte, end_byte);
45 DCHECK_LE(end_byte, data_.size());
46
47 std::memcpy(data, data_.data() + start_byte, end_byte - start_byte);
48 return end_byte - start_byte;
Austin Schuh48d10d62022-10-16 22:19:23 -070049 }
50
51 private:
52 const absl::Span<const uint8_t> data_;
53 };
54
55 // Returns true if there is space in the buffer for the next request, or if
56 // the output needs to be flushed.
57 virtual bool HasSpace(size_t request) const = 0;
58
Austin Schuh8bdfc492023-02-11 12:53:13 -080059 // Returns the space available.
60 virtual size_t space() const = 0;
Brian Silvermanf51499a2020-09-21 12:49:08 -070061
Austin Schuh8bdfc492023-02-11 12:53:13 -080062 // Encodes and enqueues the given data encoder. Starts at the start byte
63 // (which must be a multiple of 8 bytes), and goes as far as it can. Returns
64 // the amount encoded.
65 virtual size_t Encode(Copier *copy, size_t start_byte) = 0;
Brian Silvermanf51499a2020-09-21 12:49:08 -070066
67 // Finalizes the encoding process. After this, queue_size() represents the
68 // full extent of data which will be written to this file.
69 //
70 // Encode may not be called after this method.
71 virtual void Finish() = 0;
72
73 // Clears the first n encoded buffers from the queue.
74 virtual void Clear(int n) = 0;
75
Austin Schuh48d10d62022-10-16 22:19:23 -070076 // Returns a view of the queue of encoded buffers. Valid until any other
77 // method on this class is called.
78 virtual absl::Span<const absl::Span<const uint8_t>> queue() = 0;
Brian Silvermanf51499a2020-09-21 12:49:08 -070079
80 // Returns the total number of of bytes currently queued up.
81 virtual size_t queued_bytes() const = 0;
82
83 // Returns the cumulative number of bytes which have been queued. This
84 // includes data which has been removed via Clear.
85 virtual size_t total_bytes() const = 0;
86
87 // Returns the number of elements in the queue.
88 virtual size_t queue_size() const = 0;
89};
90
91// This class does not encode the data. It just claims ownership of the raw data
92// and queues it up as is.
Austin Schuh48d10d62022-10-16 22:19:23 -070093class DummyEncoder final : public DataEncoder {
Brian Silvermanf51499a2020-09-21 12:49:08 -070094 public:
Austin Schuh8bdfc492023-02-11 12:53:13 -080095 DummyEncoder(size_t max_message_size, size_t buffer_size = 128 * 1024);
Austin Schuhc41603c2020-10-11 16:17:37 -070096 DummyEncoder(const DummyEncoder &) = delete;
97 DummyEncoder(DummyEncoder &&other) = delete;
98 DummyEncoder &operator=(const DummyEncoder &) = delete;
99 DummyEncoder &operator=(DummyEncoder &&other) = delete;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700100 ~DummyEncoder() override = default;
101
Austin Schuh48d10d62022-10-16 22:19:23 -0700102 bool HasSpace(size_t request) const final;
Austin Schuh8bdfc492023-02-11 12:53:13 -0800103 size_t space() const final;
104 size_t Encode(Copier *copy, size_t start_byte) final;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700105 void Finish() final {}
106 void Clear(int n) final;
Austin Schuh48d10d62022-10-16 22:19:23 -0700107 absl::Span<const absl::Span<const uint8_t>> queue() final;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700108 size_t queued_bytes() const final;
109 size_t total_bytes() const final { return total_bytes_; }
Austin Schuh48d10d62022-10-16 22:19:23 -0700110 size_t queue_size() const final {
111 return input_buffer_.size() != 0 ? 1u : 0u;
112 }
Brian Silvermanf51499a2020-09-21 12:49:08 -0700113
114 private:
Brian Silvermanf51499a2020-09-21 12:49:08 -0700115 size_t total_bytes_ = 0;
Austin Schuh48d10d62022-10-16 22:19:23 -0700116
Austin Schuhbed6eeb2023-02-04 11:42:03 -0800117 // A class which uses aligned_alloc to allocate sector aligned blocks of
118 // memory.
119 class AlignedReallocator {
120 public:
121 static void *Realloc(void *old, size_t old_size, size_t new_capacity) {
122 void *new_memory = std::aligned_alloc(512, new_capacity);
123 if (old) {
124 memcpy(new_memory, old, old_size);
125 free(old);
126 }
127 return new_memory;
128 }
129 };
130
131 AllocatorResizeableBuffer<AlignedReallocator> input_buffer_;
Austin Schuh48d10d62022-10-16 22:19:23 -0700132 std::vector<absl::Span<const uint8_t>> return_queue_;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700133};
134
135// Interface to decode chunks of data. Implementations of this interface will
136// manage opening, reading, and closing the file stream.
137class DataDecoder {
138 public:
139 virtual ~DataDecoder() = default;
140
141 // Reads data into the given range. Returns the number of bytes read.
142 //
143 // Returns less than end-begin if all bytes have been read. Otherwise, this
144 // will always fill the whole range.
145 virtual size_t Read(uint8_t *begin, uint8_t *end) = 0;
Tyler Chatow2015bc62021-08-04 21:15:09 -0700146
147 // Returns the underlying filename, for debugging purposes.
148 virtual std::string_view filename() const = 0;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700149};
150
151// Simply reads the contents of the file into the target buffer.
152class DummyDecoder final : public DataDecoder {
153 public:
154 explicit DummyDecoder(std::string_view filename);
Austin Schuhc41603c2020-10-11 16:17:37 -0700155 DummyDecoder(const DummyDecoder &) = delete;
156 DummyDecoder(DummyDecoder &&other) = delete;
157 DummyDecoder &operator=(const DummyDecoder &) = delete;
158 DummyDecoder &operator=(DummyDecoder &&other) = delete;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700159 ~DummyDecoder() override;
160
161 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -0700162 std::string_view filename() const final { return filename_; }
Brian Silvermanf51499a2020-09-21 12:49:08 -0700163
164 private:
Tyler Chatow2015bc62021-08-04 21:15:09 -0700165 const std::string filename_;
166
Brian Silvermanf51499a2020-09-21 12:49:08 -0700167 // File descriptor for the log file.
168 int fd_;
169
170 // Cached bit for if we have reached the end of the file. Otherwise we will
171 // hammer on the kernel asking for more data each time we send.
172 bool end_of_file_ = false;
173};
174
175} // namespace aos::logger
176
177#endif // AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_