blob: 6696200d7d21d4885cf3c0554bc9ff4824f13c21 [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:
Tyler Chatow2015bc62021-08-04 21:15:09 -070055 explicit LzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder);
56 explicit LzmaDecoder(std::string_view filename)
57 : LzmaDecoder(std::make_unique<DummyDecoder>(filename)) {}
Austin Schuhc41603c2020-10-11 16:17:37 -070058 LzmaDecoder(const LzmaDecoder &) = delete;
59 LzmaDecoder(LzmaDecoder &&other) = delete;
60 LzmaDecoder &operator=(const LzmaDecoder &) = delete;
61 LzmaDecoder &operator=(LzmaDecoder &&other) = delete;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070062 ~LzmaDecoder();
63
64 size_t Read(uint8_t *begin, uint8_t *end) final;
Tyler Chatow2015bc62021-08-04 21:15:09 -070065 std::string_view filename() const final {
66 return underlying_decoder_->filename();
67 }
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070068
69 private:
70 // Size of temporary buffer to use.
71 static constexpr size_t kBufSize{256 * 1024};
72
73 // Temporary buffer for storing compressed data.
74 ResizeableBuffer compressed_data_;
75 // Used for reading data from the file.
Tyler Chatow2015bc62021-08-04 21:15:09 -070076 std::unique_ptr<DataDecoder> underlying_decoder_;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070077 // Stream for decompression.
78 lzma_stream stream_;
79 // The current action. This is LZMA_RUN until we've run out of data to read
80 // from the file.
81 lzma_action action_ = LZMA_RUN;
82 // Flag that represents whether or not all the data from the file has been
83 // successfully decoded.
84 bool finished_ = false;
Brian Silvermanf59fe3f2020-09-22 21:04:09 -070085};
86
Tyler Chatow7df60832021-07-15 21:18:36 -070087// Decompresses data with liblzma in a new thread, up to a maximum queue
88// size. Calls to Read() will return data from the queue if available,
89// or block until more data is queued or the stream finishes.
90class ThreadedLzmaDecoder : public DataDecoder {
91 public:
Tyler Chatow2015bc62021-08-04 21:15:09 -070092 explicit ThreadedLzmaDecoder(std::string_view filename)
93 : ThreadedLzmaDecoder(std::make_unique<DummyDecoder>(filename)) {}
94 explicit ThreadedLzmaDecoder(std::unique_ptr<DataDecoder> underlying_decoder);
Tyler Chatow7df60832021-07-15 21:18:36 -070095 ThreadedLzmaDecoder(const ThreadedLzmaDecoder &) = delete;
96 ThreadedLzmaDecoder &operator=(const ThreadedLzmaDecoder &) = delete;
97
98 ~ThreadedLzmaDecoder();
99
100 size_t Read(uint8_t *begin, uint8_t *end) final;
101
Tyler Chatow2015bc62021-08-04 21:15:09 -0700102 std::string_view filename() const final { return decoder_.filename(); }
103
Tyler Chatow7df60832021-07-15 21:18:36 -0700104 private:
105 static constexpr size_t kBufSize{256 * 1024};
106 static constexpr size_t kQueueSize{8};
107
108 LzmaDecoder decoder_;
109
110 // Queue of decompressed data to return on calls to Read
111 std::vector<ResizeableBuffer> decoded_queue_;
112
113 // Mutex to control access to decoded_queue_.
114 std::mutex decode_mutex_;
115 std::condition_variable continue_decoding_;
116 std::condition_variable queue_filled_;
117
118 bool finished_ = false;
119
120 std::thread decode_thread_;
121};
122
Brian Silvermanf59fe3f2020-09-22 21:04:09 -0700123} // namespace aos::logger
124
125#endif // AOS_EVENTS_LOGGING_LZMA_ENCODER_H_