blob: 14c00eb304753af8ef0f6dbb2080a22764c26791 [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.
19class LzmaEncoder final : public DetachedBufferEncoder {
20 public:
Austin Schuhbe91b342022-06-27 00:53:45 -070021 // Initializes the LZMA stream and encoder. The block size is the block size
22 // used by the multithreaded encoder for batching. A block size of 0 tells
23 // lzma to pick it's favorite block size.
24 explicit LzmaEncoder(uint32_t compression_preset, size_t block_size = 0);
Austin Schuhc41603c2020-10-11 16:17:37 -070025 LzmaEncoder(const LzmaEncoder &) = delete;
26 LzmaEncoder(LzmaEncoder &&other) = delete;
27 LzmaEncoder &operator=(const LzmaEncoder &) = delete;
28 LzmaEncoder &operator=(LzmaEncoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070029 // Gracefully shuts down the encoder.
30 ~LzmaEncoder() final;
31
32 void Encode(flatbuffers::DetachedBuffer &&in) final;
33 void Finish() final;
34 void Clear(int n) final;
35 std::vector<absl::Span<const uint8_t>> queue() const final;
36 size_t queued_bytes() const final;
37 size_t total_bytes() const final { return total_bytes_; }
38 size_t queue_size() const final { return queue_.size(); }
39
40 private:
Austin Schuhbe91b342022-06-27 00:53:45 -070041 static constexpr size_t kEncodedBufferSizeBytes{4096 * 10};
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070042
43 void RunLzmaCode(lzma_action action);
44
45 lzma_stream stream_;
46 uint32_t compression_preset_;
47 std::vector<ResizeableBuffer> queue_;
48 bool finished_ = false;
49 // Total bytes that resulted from encoding raw data since the last call to
50 // Reset.
51 size_t total_bytes_ = 0;
52};
53
54// Decompresses data with liblzma.
55class LzmaDecoder final : public DataDecoder {
56 public:
James Kuszmauldd0a5042021-10-28 23:38:04 -070057 static constexpr std::string_view kExtension = ".xz";
58
Austin Schuhcd368422021-11-22 21:23:29 -080059 explicit LzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
60 bool quiet = false);
61 explicit LzmaDecoder(std::string_view filename, bool quiet = false)
62 : LzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
Austin Schuhc41603c2020-10-11 16:17:37 -070063 LzmaDecoder(const LzmaDecoder &) = delete;
64 LzmaDecoder(LzmaDecoder &&other) = delete;
65 LzmaDecoder &operator=(const LzmaDecoder &) = delete;
66 LzmaDecoder &operator=(LzmaDecoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070067 ~LzmaDecoder();
68
69 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -070070 std::string_view filename() const final {
71 return underlying_decoder_->filename();
72 }
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070073
74 private:
75 // Size of temporary buffer to use.
76 static constexpr size_t kBufSize{256 * 1024};
77
78 // Temporary buffer for storing compressed data.
79 ResizeableBuffer compressed_data_;
80 // Used for reading data from the file.
Tyler Chatow2015bc62021-08-04 21:15:09 -070081 std::unique_ptr<DataDecoder> underlying_decoder_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070082 // Stream for decompression.
83 lzma_stream stream_;
84 // The current action. This is LZMA_RUN until we've run out of data to read
85 // from the file.
86 lzma_action action_ = LZMA_RUN;
87 // Flag that represents whether or not all the data from the file has been
88 // successfully decoded.
89 bool finished_ = false;
Austin Schuhcd368422021-11-22 21:23:29 -080090 // Flag to signal how quiet to be when logging potential issues around
91 // truncation.
92 const bool quiet_ = false;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070093};
94
Tyler Chatow7df60832021-07-15 21:18:36 -070095// Decompresses data with liblzma in a new thread, up to a maximum queue
96// size. Calls to Read() will return data from the queue if available,
97// or block until more data is queued or the stream finishes.
98class ThreadedLzmaDecoder : public DataDecoder {
99 public:
Austin Schuhcd368422021-11-22 21:23:29 -0800100 explicit ThreadedLzmaDecoder(std::string_view filename, bool quiet = false)
101 : ThreadedLzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
102 explicit ThreadedLzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
103 bool quiet = false);
Tyler Chatow7df60832021-07-15 21:18:36 -0700104 ThreadedLzmaDecoder(const ThreadedLzmaDecoder &) = delete;
105 ThreadedLzmaDecoder &operator=(const ThreadedLzmaDecoder &) = delete;
106
107 ~ThreadedLzmaDecoder();
108
109 size_t Read(uint8_t *begin, uint8_t *end) final;
110
Tyler Chatow2015bc62021-08-04 21:15:09 -0700111 std::string_view filename() const final { return decoder_.filename(); }
112
Tyler Chatow7df60832021-07-15 21:18:36 -0700113 private:
114 static constexpr size_t kBufSize{256 * 1024};
115 static constexpr size_t kQueueSize{8};
116
117 LzmaDecoder decoder_;
118
119 // Queue of decompressed data to return on calls to Read
120 std::vector<ResizeableBuffer> decoded_queue_;
121
122 // Mutex to control access to decoded_queue_.
123 std::mutex decode_mutex_;
124 std::condition_variable continue_decoding_;
125 std::condition_variable queue_filled_;
126
127 bool finished_ = false;
128
129 std::thread decode_thread_;
130};
131
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700132} // namespace aos::logger
133
134#endif // AOS_EVENTS_LOGGING_LZMA_ENCODER_H_