blob: 4edd0e88c3a6fcdfa0537272150a0b1e1f605a31 [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:
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
Austin Schuhcd368422021-11-22 21:23:29 -080057 explicit LzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
58 bool quiet = false);
59 explicit LzmaDecoder(std::string_view filename, bool quiet = false)
60 : LzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
Austin Schuhc41603c2020-10-11 16:17:37 -070061 LzmaDecoder(const LzmaDecoder &) = delete;
62 LzmaDecoder(LzmaDecoder &&other) = delete;
63 LzmaDecoder &operator=(const LzmaDecoder &) = delete;
64 LzmaDecoder &operator=(LzmaDecoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070065 ~LzmaDecoder();
66
67 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -070068 std::string_view filename() const final {
69 return underlying_decoder_->filename();
70 }
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070071
72 private:
73 // Size of temporary buffer to use.
74 static constexpr size_t kBufSize{256 * 1024};
75
76 // Temporary buffer for storing compressed data.
77 ResizeableBuffer compressed_data_;
78 // Used for reading data from the file.
Tyler Chatow2015bc62021-08-04 21:15:09 -070079 std::unique_ptr<DataDecoder> underlying_decoder_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070080 // Stream for decompression.
81 lzma_stream stream_;
82 // The current action. This is LZMA_RUN until we've run out of data to read
83 // from the file.
84 lzma_action action_ = LZMA_RUN;
85 // Flag that represents whether or not all the data from the file has been
86 // successfully decoded.
87 bool finished_ = false;
Austin Schuhcd368422021-11-22 21:23:29 -080088 // Flag to signal how quiet to be when logging potential issues around
89 // truncation.
90 const bool quiet_ = false;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070091};
92
Tyler Chatow7df60832021-07-15 21:18:36 -070093// Decompresses data with liblzma in a new thread, up to a maximum queue
94// size. Calls to Read() will return data from the queue if available,
95// or block until more data is queued or the stream finishes.
96class ThreadedLzmaDecoder : public DataDecoder {
97 public:
Austin Schuhcd368422021-11-22 21:23:29 -080098 explicit ThreadedLzmaDecoder(std::string_view filename, bool quiet = false)
99 : ThreadedLzmaDecoder(std::make_unique<DummyDecoder>(filename), quiet) {}
100 explicit ThreadedLzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder,
101 bool quiet = false);
Tyler Chatow7df60832021-07-15 21:18:36 -0700102 ThreadedLzmaDecoder(const ThreadedLzmaDecoder &) = delete;
103 ThreadedLzmaDecoder &operator=(const ThreadedLzmaDecoder &) = delete;
104
105 ~ThreadedLzmaDecoder();
106
107 size_t Read(uint8_t *begin, uint8_t *end) final;
108
Tyler Chatow2015bc62021-08-04 21:15:09 -0700109 std::string_view filename() const final { return decoder_.filename(); }
110
Tyler Chatow7df60832021-07-15 21:18:36 -0700111 private:
112 static constexpr size_t kBufSize{256 * 1024};
113 static constexpr size_t kQueueSize{8};
114
115 LzmaDecoder decoder_;
116
117 // Queue of decompressed data to return on calls to Read
118 std::vector<ResizeableBuffer> decoded_queue_;
119
120 // Mutex to control access to decoded_queue_.
121 std::mutex decode_mutex_;
122 std::condition_variable continue_decoding_;
123 std::condition_variable queue_filled_;
124
125 bool finished_ = false;
126
127 std::thread decode_thread_;
128};
129
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700130} // namespace aos::logger
131
132#endif // AOS_EVENTS_LOGGING_LZMA_ENCODER_H_