blob: bbd739a98f124bf864e3cf467455e1d06ca592e8 [file] [log] [blame]
Brian Silvermanf59fe3f2020-09-22 21:04:09 -07001#ifndef AOS_EVENTS_LOGGING_LZMA_ENCODER_H_
2#define AOS_EVENTS_LOGGING_LZMA_ENCODER_H_
3
Tyler Chatow7df60832021-07-15 21:18:36 -07004#include <condition_variable>
5#include <mutex>
Austin Schuh60e77942022-05-16 17:48:24 -07006#include <string_view>
Tyler Chatow7df60832021-07-15 21:18:36 -07007#include <thread>
Brian Silvermanf59fe3f2020-09-22 21:04:09 -07008
Tyler Chatow7df60832021-07-15 21:18:36 -07009#include "absl/types/span.h"
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070010#include "aos/containers/resizeable_buffer.h"
11#include "aos/events/logging/buffer_encoder.h"
12#include "aos/events/logging/logger_generated.h"
Tyler Chatow7df60832021-07-15 21:18:36 -070013#include "flatbuffers/flatbuffers.h"
14#include "lzma.h"
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070015
16namespace aos::logger {
17
18// Encodes buffers using liblzma.
Austin Schuh48d10d62022-10-16 22:19:23 -070019class LzmaEncoder final : public DataEncoder {
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070020 public:
Austin Schuh48d10d62022-10-16 22:19:23 -070021 static constexpr std::string_view kExtension = ".xz";
22
Austin Schuhbe91b342022-06-27 00:53:45 -070023 // Initializes the LZMA stream and encoder. The block size is the block size
24 // used by the multithreaded encoder for batching. A block size of 0 tells
25 // lzma to pick it's favorite block size.
Austin Schuh48d10d62022-10-16 22:19:23 -070026 explicit LzmaEncoder(size_t max_message_size, uint32_t compression_preset,
27 size_t block_size = 0);
Austin Schuhc41603c2020-10-11 16:17:37 -070028 LzmaEncoder(const LzmaEncoder &) = delete;
29 LzmaEncoder(LzmaEncoder &&other) = delete;
30 LzmaEncoder &operator=(const LzmaEncoder &) = delete;
31 LzmaEncoder &operator=(LzmaEncoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070032 // Gracefully shuts down the encoder.
33 ~LzmaEncoder() final;
34
Austin Schuh48d10d62022-10-16 22:19:23 -070035 bool HasSpace(size_t /*request*/) const override {
36 // Since the underlying lzma encoder handles buffering, we always have
37 // space.
38 return true;
39 }
40 void Encode(Copier *copy) final;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070041 void Finish() final;
42 void Clear(int n) final;
Austin Schuh48d10d62022-10-16 22:19:23 -070043 absl::Span<const absl::Span<const uint8_t>> queue() final;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070044 size_t queued_bytes() const final;
45 size_t total_bytes() const final { return total_bytes_; }
46 size_t queue_size() const final { return queue_.size(); }
47
48 private:
Austin Schuh48d10d62022-10-16 22:19:23 -070049 static constexpr size_t kEncodedBufferSizeBytes{1024 * 128};
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070050
51 void RunLzmaCode(lzma_action action);
52
53 lzma_stream stream_;
54 uint32_t compression_preset_;
55 std::vector<ResizeableBuffer> queue_;
56 bool finished_ = false;
57 // Total bytes that resulted from encoding raw data since the last call to
58 // Reset.
59 size_t total_bytes_ = 0;
Austin Schuh48d10d62022-10-16 22:19:23 -070060
61 // Buffer that messages get coppied into for encoding.
62 ResizeableBuffer input_buffer_;
63
64 std::vector<absl::Span<const uint8_t>> return_queue_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070065};
66
67// Decompresses data with liblzma.
68class LzmaDecoder final : public DataDecoder {
69 public:
James Kuszmauldd0a5042021-10-28 23:38:04 -070070 static constexpr std::string_view kExtension = ".xz";
71
Austin Schuhcd368422021-11-22 21:23:29 -080072 explicit LzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
73 bool quiet = false);
74 explicit LzmaDecoder(std::string_view filename, bool quiet = false)
75 : LzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
Austin Schuhc41603c2020-10-11 16:17:37 -070076 LzmaDecoder(const LzmaDecoder &) = delete;
77 LzmaDecoder(LzmaDecoder &&other) = delete;
78 LzmaDecoder &operator=(const LzmaDecoder &) = delete;
79 LzmaDecoder &operator=(LzmaDecoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070080 ~LzmaDecoder();
81
82 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -070083 std::string_view filename() const final {
84 return underlying_decoder_->filename();
85 }
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070086
87 private:
88 // Size of temporary buffer to use.
89 static constexpr size_t kBufSize{256 * 1024};
90
91 // Temporary buffer for storing compressed data.
92 ResizeableBuffer compressed_data_;
93 // Used for reading data from the file.
Tyler Chatow2015bc62021-08-04 21:15:09 -070094 std::unique_ptr<DataDecoder> underlying_decoder_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070095 // Stream for decompression.
96 lzma_stream stream_;
97 // The current action. This is LZMA_RUN until we've run out of data to read
98 // from the file.
99 lzma_action action_ = LZMA_RUN;
100 // Flag that represents whether or not all the data from the file has been
101 // successfully decoded.
102 bool finished_ = false;
Austin Schuhcd368422021-11-22 21:23:29 -0800103 // Flag to signal how quiet to be when logging potential issues around
104 // truncation.
105 const bool quiet_ = false;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700106};
107
Tyler Chatow7df60832021-07-15 21:18:36 -0700108// Decompresses data with liblzma in a new thread, up to a maximum queue
109// size. Calls to Read() will return data from the queue if available,
110// or block until more data is queued or the stream finishes.
111class ThreadedLzmaDecoder : public DataDecoder {
112 public:
Austin Schuhcd368422021-11-22 21:23:29 -0800113 explicit ThreadedLzmaDecoder(std::string_view filename, bool quiet = false)
114 : ThreadedLzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
115 explicit ThreadedLzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
116 bool quiet = false);
Tyler Chatow7df60832021-07-15 21:18:36 -0700117 ThreadedLzmaDecoder(const ThreadedLzmaDecoder &) = delete;
118 ThreadedLzmaDecoder &operator=(const ThreadedLzmaDecoder &) = delete;
119
120 ~ThreadedLzmaDecoder();
121
122 size_t Read(uint8_t *begin, uint8_t *end) final;
123
Tyler Chatow2015bc62021-08-04 21:15:09 -0700124 std::string_view filename() const final { return decoder_.filename(); }
125
Tyler Chatow7df60832021-07-15 21:18:36 -0700126 private:
127 static constexpr size_t kBufSize{256 * 1024};
128 static constexpr size_t kQueueSize{8};
129
130 LzmaDecoder decoder_;
131
132 // Queue of decompressed data to return on calls to Read
133 std::vector<ResizeableBuffer> decoded_queue_;
134
135 // Mutex to control access to decoded_queue_.
136 std::mutex decode_mutex_;
137 std::condition_variable continue_decoding_;
138 std::condition_variable queue_filled_;
139
140 bool finished_ = false;
141
142 std::thread decode_thread_;
143};
144
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700145} // namespace aos::logger
146
147#endif // AOS_EVENTS_LOGGING_LZMA_ENCODER_H_