blob: fc6fcb6f2feb933a1c489fe23984bc7fb0b48e52 [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 Chatow2015bc62021-08-04 21:15:09 -07004#include <string_view>
Tyler Chatow7df60832021-07-15 21:18:36 -07005#include <condition_variable>
6#include <mutex>
7#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:
21 // Initializes the LZMA stream and encoder.
22 explicit LzmaEncoder(uint32_t compression_preset);
Austin Schuhc41603c2020-10-11 16:17:37 -070023 LzmaEncoder(const LzmaEncoder &) = delete;
24 LzmaEncoder(LzmaEncoder &&other) = delete;
25 LzmaEncoder &operator=(const LzmaEncoder &) = delete;
26 LzmaEncoder &operator=(LzmaEncoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070027 // Gracefully shuts down the encoder.
28 ~LzmaEncoder() final;
29
30 void Encode(flatbuffers::DetachedBuffer &&in) final;
31 void Finish() final;
32 void Clear(int n) final;
33 std::vector<absl::Span<const uint8_t>> queue() const final;
34 size_t queued_bytes() const final;
35 size_t total_bytes() const final { return total_bytes_; }
36 size_t queue_size() const final { return queue_.size(); }
37
38 private:
Austin Schuhc07d4fb2020-12-13 16:40:04 -080039 static constexpr size_t kEncodedBufferSizeBytes{4096};
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070040
41 void RunLzmaCode(lzma_action action);
42
43 lzma_stream stream_;
44 uint32_t compression_preset_;
45 std::vector<ResizeableBuffer> queue_;
46 bool finished_ = false;
47 // Total bytes that resulted from encoding raw data since the last call to
48 // Reset.
49 size_t total_bytes_ = 0;
50};
51
52// Decompresses data with liblzma.
53class LzmaDecoder final : public DataDecoder {
54 public:
James Kuszmauldd0a5042021-10-28 23:38:04 -070055 static constexpr std::string_view kExtension = ".xz";
56
Tyler Chatow2015bc62021-08-04 21:15:09 -070057 explicit LzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder);
58 explicit LzmaDecoder(std::string_view filename)
59 : LzmaDecoder(std::make_unique<DummyDecoder>(filename)) {}
Austin Schuhc41603c2020-10-11 16:17:37 -070060 LzmaDecoder(const LzmaDecoder &) = delete;
61 LzmaDecoder(LzmaDecoder &&other) = delete;
62 LzmaDecoder &operator=(const LzmaDecoder &) = delete;
63 LzmaDecoder &operator=(LzmaDecoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070064 ~LzmaDecoder();
65
66 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -070067 std::string_view filename() const final {
68 return underlying_decoder_->filename();
69 }
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070070
71 private:
72 // Size of temporary buffer to use.
73 static constexpr size_t kBufSize{256 * 1024};
74
75 // Temporary buffer for storing compressed data.
76 ResizeableBuffer compressed_data_;
77 // Used for reading data from the file.
Tyler Chatow2015bc62021-08-04 21:15:09 -070078 std::unique_ptr<DataDecoder> underlying_decoder_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070079 // Stream for decompression.
80 lzma_stream stream_;
81 // The current action. This is LZMA_RUN until we've run out of data to read
82 // from the file.
83 lzma_action action_ = LZMA_RUN;
84 // Flag that represents whether or not all the data from the file has been
85 // successfully decoded.
86 bool finished_ = false;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070087};
88
Tyler Chatow7df60832021-07-15 21:18:36 -070089// Decompresses data with liblzma in a new thread, up to a maximum queue
90// size. Calls to Read() will return data from the queue if available,
91// or block until more data is queued or the stream finishes.
92class ThreadedLzmaDecoder : public DataDecoder {
93 public:
Tyler Chatow2015bc62021-08-04 21:15:09 -070094 explicit ThreadedLzmaDecoder(std::string_view filename)
95 : ThreadedLzmaDecoder(std::make_unique<DummyDecoder>(filename)) {}
96 explicit ThreadedLzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder);
Tyler Chatow7df60832021-07-15 21:18:36 -070097 ThreadedLzmaDecoder(const ThreadedLzmaDecoder &) = delete;
98 ThreadedLzmaDecoder &operator=(const ThreadedLzmaDecoder &) = delete;
99
100 ~ThreadedLzmaDecoder();
101
102 size_t Read(uint8_t *begin, uint8_t *end) final;
103
Tyler Chatow2015bc62021-08-04 21:15:09 -0700104 std::string_view filename() const final { return decoder_.filename(); }
105
Tyler Chatow7df60832021-07-15 21:18:36 -0700106 private:
107 static constexpr size_t kBufSize{256 * 1024};
108 static constexpr size_t kQueueSize{8};
109
110 LzmaDecoder decoder_;
111
112 // Queue of decompressed data to return on calls to Read
113 std::vector<ResizeableBuffer> decoded_queue_;
114
115 // Mutex to control access to decoded_queue_.
116 std::mutex decode_mutex_;
117 std::condition_variable continue_decoding_;
118 std::condition_variable queue_filled_;
119
120 bool finished_ = false;
121
122 std::thread decode_thread_;
123};
124
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700125} // namespace aos::logger
126
127#endif // AOS_EVENTS_LOGGING_LZMA_ENCODER_H_