blob: b70f1ab1d899843baa2edeb666b41a3e0295a4dc [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/developer/forensics/feedback_data/system_log_recorder/encoding/lz4_encoder.h"
#include <lib/syslog/cpp/macros.h>
#include <iterator>
#include "src/developer/forensics/feedback_data/system_log_recorder/encoding/lz4_utils.h"
namespace forensics {
namespace feedback_data {
namespace system_log_recorder {
const std::string kDroppedError = "!!! DROPPED MESSAGE NOT ENCODABLE !!!\n";
Lz4Encoder::Lz4Encoder() : ring_(kEncoderRingBufferSize) { stream_ = LZ4_createStream(); }
Lz4Encoder::~Lz4Encoder() { LZ4_freeStream(stream_); }
std::string Lz4Encoder::Encode(const std::string& msg) {
if (msg.size() == 0) {
return "";
}
const size_t msg_size = std::min(msg.size(), kMaxEncodeSize);
// lz4 forces us to output separately (1) the size of the encoded message and (2) the encoded
// message itself.
const size_t max_encoded_size = LZ4_compressBound((int)msg_size);
std::vector<char> encoded(max_encoded_size);
// Make a copy that will stay in memory for LZ4 to use
char* chunk_copy_ptr = ring_.Write(msg.data(), msg_size);
// Encode message.
const int encoded_size = LZ4_compress_fast_continue(stream_, chunk_copy_ptr, encoded.data(),
(int)msg_size, (int)max_encoded_size, 0);
FX_CHECK((size_t)encoded_size <= kMaxChunkSize);
if (encoded_size <= 0) {
// We reset the encoder stream as its state has become undefined. Sending a special size
// kEncodeSizeError is a proxy to reset the decoder to keep it in sync.
Reset();
return EncodeSize(kEncodeSizeError) + Encode(kDroppedError);
}
return EncodeSize((uint16_t)encoded_size) +
std::string(encoded.begin(), encoded.begin() + encoded_size);
}
void Lz4Encoder::Reset() {
LZ4_freeStream(stream_);
stream_ = LZ4_createStream();
}
} // namespace system_log_recorder
} // namespace feedback_data
} // namespace forensics