blob: 235a49c6a5afb39780e754225aec0d8017a22f72 [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"
Brian Silvermanf51499a2020-09-21 12:49:08 -07005#include "aos/events/logging/logger_generated.h"
Tyler Chatow2015bc62021-08-04 21:15:09 -07006#include "flatbuffers/flatbuffers.h"
Brian Silvermanf51499a2020-09-21 12:49:08 -07007
8namespace aos::logger {
9
10// Interface to encode DetachedBuffers as they are written to a file.
11//
12// The interface to a file is represented as a series of buffers, appropriate to
13// pass to writev(2). The backing storage for these is managed internally so
14// subclasses can handle resizing/moving as desired. Implementations must
15// enqueue as many of these backing buffers as demanded, leaving it up to the
16// caller to write them to a file when desired.
17class DetachedBufferEncoder {
18 public:
19 virtual ~DetachedBufferEncoder() = default;
20
21 // Encodes and enqueues the given DetachedBuffer.
22 //
23 // Note that in may be moved-from, or it may be left unchanged, depending on
24 // what makes the most sense for a given implementation.
25 virtual void Encode(flatbuffers::DetachedBuffer &&in) = 0;
26
27 // If this returns true, the encoder may be bypassed by writing directly to
28 // the file.
29 virtual bool may_bypass() const { return false; }
30
31 // Finalizes the encoding process. After this, queue_size() represents the
32 // full extent of data which will be written to this file.
33 //
34 // Encode may not be called after this method.
35 virtual void Finish() = 0;
36
37 // Clears the first n encoded buffers from the queue.
38 virtual void Clear(int n) = 0;
39
40 // Returns a view of the queue of encoded buffers.
41 virtual std::vector<absl::Span<const uint8_t>> queue() const = 0;
42
43 // Returns the total number of of bytes currently queued up.
44 virtual size_t queued_bytes() const = 0;
45
46 // Returns the cumulative number of bytes which have been queued. This
47 // includes data which has been removed via Clear.
48 virtual size_t total_bytes() const = 0;
49
50 // Returns the number of elements in the queue.
51 virtual size_t queue_size() const = 0;
52};
53
54// This class does not encode the data. It just claims ownership of the raw data
55// and queues it up as is.
56class DummyEncoder final : public DetachedBufferEncoder {
57 public:
Austin Schuhc41603c2020-10-11 16:17:37 -070058 DummyEncoder() {}
59 DummyEncoder(const DummyEncoder &) = delete;
60 DummyEncoder(DummyEncoder &&other) = delete;
61 DummyEncoder &operator=(const DummyEncoder &) = delete;
62 DummyEncoder &operator=(DummyEncoder &&other) = delete;
Brian Silvermanf51499a2020-09-21 12:49:08 -070063 ~DummyEncoder() override = default;
64
65 // No encoding happens, the raw data is queued up as is.
66 void Encode(flatbuffers::DetachedBuffer &&in) final;
67 bool may_bypass() const final { return true; }
68 void Finish() final {}
69 void Clear(int n) final;
70 std::vector<absl::Span<const uint8_t>> queue() const final;
71 size_t queued_bytes() const final;
72 size_t total_bytes() const final { return total_bytes_; }
73 size_t queue_size() const final { return queue_.size(); }
74
75 private:
76 std::vector<flatbuffers::DetachedBuffer> queue_;
77 size_t total_bytes_ = 0;
78};
79
80// Interface to decode chunks of data. Implementations of this interface will
81// manage opening, reading, and closing the file stream.
82class DataDecoder {
83 public:
84 virtual ~DataDecoder() = default;
85
86 // Reads data into the given range. Returns the number of bytes read.
87 //
88 // Returns less than end-begin if all bytes have been read. Otherwise, this
89 // will always fill the whole range.
90 virtual size_t Read(uint8_t *begin, uint8_t *end) = 0;
Tyler Chatow2015bc62021-08-04 21:15:09 -070091
92 // Returns the underlying filename, for debugging purposes.
93 virtual std::string_view filename() const = 0;
Brian Silvermanf51499a2020-09-21 12:49:08 -070094};
95
96// Simply reads the contents of the file into the target buffer.
97class DummyDecoder final : public DataDecoder {
98 public:
99 explicit DummyDecoder(std::string_view filename);
Austin Schuhc41603c2020-10-11 16:17:37 -0700100 DummyDecoder(const DummyDecoder &) = delete;
101 DummyDecoder(DummyDecoder &&other) = delete;
102 DummyDecoder &operator=(const DummyDecoder &) = delete;
103 DummyDecoder &operator=(DummyDecoder &&other) = delete;
Brian Silvermanf51499a2020-09-21 12:49:08 -0700104 ~DummyDecoder() override;
105
106 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -0700107 std::string_view filename() const final { return filename_; }
Brian Silvermanf51499a2020-09-21 12:49:08 -0700108
109 private:
Tyler Chatow2015bc62021-08-04 21:15:09 -0700110 const std::string filename_;
111
Brian Silvermanf51499a2020-09-21 12:49:08 -0700112 // File descriptor for the log file.
113 int fd_;
114
115 // Cached bit for if we have reached the end of the file. Otherwise we will
116 // hammer on the kernel asking for more data each time we send.
117 bool end_of_file_ = false;
118};
119
120} // namespace aos::logger
121
122#endif // AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_