12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci#include "log_compress.h"
162498b56bSopenharmony_ci
172498b56bSopenharmony_ci#include <iostream>
182498b56bSopenharmony_ci#include <cstring>
192498b56bSopenharmony_ci#include <cstdlib>
202498b56bSopenharmony_ci#include <vector>
212498b56bSopenharmony_ci
222498b56bSopenharmony_ci#include <securec.h>
232498b56bSopenharmony_ci
242498b56bSopenharmony_cinamespace OHOS {
252498b56bSopenharmony_cinamespace HiviewDFX {
262498b56bSopenharmony_ciStringMap LogCompress::g_CompressTypes = StringMap({
272498b56bSopenharmony_ci        {COMPRESS_TYPE_NONE, "none"}, {COMPRESS_TYPE_ZLIB, "zlib"}, {COMPRESS_TYPE_ZSTD, "zstd"}
282498b56bSopenharmony_ci    }, COMPRESS_TYPE_ZLIB, "unknown");
292498b56bSopenharmony_ci
302498b56bSopenharmony_cistd::string LogCompress::CompressType2Str(uint16_t compressType)
312498b56bSopenharmony_ci{
322498b56bSopenharmony_ci    return g_CompressTypes.GetValue(compressType);
332498b56bSopenharmony_ci}
342498b56bSopenharmony_ci
352498b56bSopenharmony_ciuint16_t LogCompress::Str2CompressType(const std::string& str)
362498b56bSopenharmony_ci{
372498b56bSopenharmony_ci    return g_CompressTypes.GetKey(str);
382498b56bSopenharmony_ci}
392498b56bSopenharmony_ci
402498b56bSopenharmony_ciint NoneCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
412498b56bSopenharmony_ci{
422498b56bSopenharmony_ci    void *dest = compressedBuffer.content + compressedBuffer.offset;
432498b56bSopenharmony_ci    size_t destSize = MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset;
442498b56bSopenharmony_ci    if (memcpy_s(dest, destSize, inBuffer.content, inBuffer.offset) != 0) {
452498b56bSopenharmony_ci        return -1;
462498b56bSopenharmony_ci    }
472498b56bSopenharmony_ci    compressedBuffer.offset += inBuffer.offset;
482498b56bSopenharmony_ci    return 0;
492498b56bSopenharmony_ci}
502498b56bSopenharmony_ci
512498b56bSopenharmony_ciint ZlibCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
522498b56bSopenharmony_ci{
532498b56bSopenharmony_ci    cStream.zalloc = Z_NULL;
542498b56bSopenharmony_ci    cStream.zfree = Z_NULL;
552498b56bSopenharmony_ci    cStream.opaque = Z_NULL;
562498b56bSopenharmony_ci    if (deflateInit2(&cStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
572498b56bSopenharmony_ci        return -1;
582498b56bSopenharmony_ci    }
592498b56bSopenharmony_ci    uint32_t zdlen = deflateBound(&cStream, inBuffer.offset);
602498b56bSopenharmony_ci    std::vector<char> zdataBuf(zdlen, 0);
612498b56bSopenharmony_ci    char* zdata = zdataBuf.data();
622498b56bSopenharmony_ci    if (zdata == nullptr) {
632498b56bSopenharmony_ci        std::cerr << "no enough memory!\n";
642498b56bSopenharmony_ci        return -1;
652498b56bSopenharmony_ci    }
662498b56bSopenharmony_ci    size_t const toRead = CHUNK;
672498b56bSopenharmony_ci    size_t src_pos = 0;
682498b56bSopenharmony_ci    size_t dst_pos = 0;
692498b56bSopenharmony_ci    size_t read = inBuffer.offset;
702498b56bSopenharmony_ci    int flush = 0;
712498b56bSopenharmony_ci    do {
722498b56bSopenharmony_ci        bool flag = read - src_pos < toRead;
732498b56bSopenharmony_ci        if (flag) {
742498b56bSopenharmony_ci            (void)memset_s(buffIn, CHUNK, 0, CHUNK);
752498b56bSopenharmony_ci            if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) {
762498b56bSopenharmony_ci                return -1;
772498b56bSopenharmony_ci            }
782498b56bSopenharmony_ci            cStream.avail_in = read - src_pos;
792498b56bSopenharmony_ci            src_pos += read - src_pos;
802498b56bSopenharmony_ci        } else {
812498b56bSopenharmony_ci            (void)memset_s(buffIn, CHUNK, 0, CHUNK);
822498b56bSopenharmony_ci            if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) {
832498b56bSopenharmony_ci                return -1;
842498b56bSopenharmony_ci            }
852498b56bSopenharmony_ci            src_pos += toRead;
862498b56bSopenharmony_ci            cStream.avail_in = toRead;
872498b56bSopenharmony_ci        }
882498b56bSopenharmony_ci        flush = flag ? Z_FINISH : Z_NO_FLUSH;
892498b56bSopenharmony_ci        cStream.next_in = reinterpret_cast<Bytef*>(buffIn);
902498b56bSopenharmony_ci        /* run deflate() on input until output buffer not full, finish
912498b56bSopenharmony_ci           compression if all of source has been read in */
922498b56bSopenharmony_ci        do {
932498b56bSopenharmony_ci            cStream.avail_out = CHUNK;
942498b56bSopenharmony_ci            cStream.next_out = reinterpret_cast<Bytef*>(buffOut);
952498b56bSopenharmony_ci            if (deflate(&cStream, flush) == Z_STREAM_ERROR) {
962498b56bSopenharmony_ci                return -1;
972498b56bSopenharmony_ci            }
982498b56bSopenharmony_ci            unsigned have = CHUNK - cStream.avail_out;
992498b56bSopenharmony_ci            if (memmove_s(zdata + dst_pos, zdlen - dst_pos, buffOut, have) != 0) {
1002498b56bSopenharmony_ci                return -1;
1012498b56bSopenharmony_ci            }
1022498b56bSopenharmony_ci            dst_pos += have;
1032498b56bSopenharmony_ci            if (unlikely(zdlen < dst_pos)) { // zdataBuf is not long enough, shoudn't happen
1042498b56bSopenharmony_ci                return -1;
1052498b56bSopenharmony_ci            }
1062498b56bSopenharmony_ci        } while (cStream.avail_out == 0);
1072498b56bSopenharmony_ci    } while (flush != Z_FINISH);
1082498b56bSopenharmony_ci    /* clean up and return */
1092498b56bSopenharmony_ci    (void)deflateEnd(&cStream);
1102498b56bSopenharmony_ci    if (memcpy_s(compressedBuffer.content + compressedBuffer.offset,
1112498b56bSopenharmony_ci        MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) {
1122498b56bSopenharmony_ci        return -1;
1132498b56bSopenharmony_ci    }
1142498b56bSopenharmony_ci    compressedBuffer.offset += dst_pos;
1152498b56bSopenharmony_ci    return 0;
1162498b56bSopenharmony_ci}
1172498b56bSopenharmony_ci
1182498b56bSopenharmony_ciint ZstdCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
1192498b56bSopenharmony_ci{
1202498b56bSopenharmony_ci#ifdef USING_ZSTD_COMPRESS
1212498b56bSopenharmony_ci    uint32_t zdlen = ZSTD_CStreamOutSize();
1222498b56bSopenharmony_ci    std::vector<char> zdataBuf(zdlen, 0);
1232498b56bSopenharmony_ci    char* zdata = zdataBuf.data();
1242498b56bSopenharmony_ci    if (zdata == nullptr) {
1252498b56bSopenharmony_ci        std::cerr << "no enough memory!\n";
1262498b56bSopenharmony_ci        return -1;
1272498b56bSopenharmony_ci    }
1282498b56bSopenharmony_ci    ZSTD_EndDirective mode;
1292498b56bSopenharmony_ci    int compressionlevel = 1;
1302498b56bSopenharmony_ci    cctx = ZSTD_createCCtx();
1312498b56bSopenharmony_ci    if (cctx == nullptr) {
1322498b56bSopenharmony_ci        std::cerr << "ZSTD_createCCtx() failed!\n";
1332498b56bSopenharmony_ci        return -1;
1342498b56bSopenharmony_ci    }
1352498b56bSopenharmony_ci    ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionlevel);
1362498b56bSopenharmony_ci    size_t const toRead = CHUNK;
1372498b56bSopenharmony_ci    auto src_pos = 0;
1382498b56bSopenharmony_ci    auto dst_pos = 0;
1392498b56bSopenharmony_ci    size_t read = inBuffer.offset;
1402498b56bSopenharmony_ci    ZSTD_inBuffer input;
1412498b56bSopenharmony_ci    do {
1422498b56bSopenharmony_ci        bool flag = read - src_pos < toRead;
1432498b56bSopenharmony_ci        if (flag) {
1442498b56bSopenharmony_ci            (void)memset_s(buffIn, CHUNK, 0, CHUNK);
1452498b56bSopenharmony_ci            if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) {
1462498b56bSopenharmony_ci                return -1;
1472498b56bSopenharmony_ci            }
1482498b56bSopenharmony_ci            input = {buffIn, read - src_pos, 0};
1492498b56bSopenharmony_ci            src_pos += read - src_pos;
1502498b56bSopenharmony_ci        } else {
1512498b56bSopenharmony_ci            (void)memset_s(buffIn, CHUNK, 0, CHUNK);
1522498b56bSopenharmony_ci            if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) {
1532498b56bSopenharmony_ci                return -1;
1542498b56bSopenharmony_ci            }
1552498b56bSopenharmony_ci            input = {buffIn, toRead, 0};
1562498b56bSopenharmony_ci            src_pos += toRead;
1572498b56bSopenharmony_ci        }
1582498b56bSopenharmony_ci        mode = flag ? ZSTD_e_end : ZSTD_e_continue;
1592498b56bSopenharmony_ci        int finished;
1602498b56bSopenharmony_ci        do {
1612498b56bSopenharmony_ci            ZSTD_outBuffer output = {buffOut, CHUNK, 0};
1622498b56bSopenharmony_ci            size_t const remaining = ZSTD_compressStream2(cctx, &output, &input, mode);
1632498b56bSopenharmony_ci            if (memmove_s(zdata + dst_pos, zdlen, reinterpret_cast<Bytef*>(buffOut), output.pos) != 0) {
1642498b56bSopenharmony_ci                return -1;
1652498b56bSopenharmony_ci            }
1662498b56bSopenharmony_ci            dst_pos += output.pos;
1672498b56bSopenharmony_ci            finished = flag ? (remaining == 0) : (input.pos == input.size);
1682498b56bSopenharmony_ci        } while (!finished);
1692498b56bSopenharmony_ci    } while (mode != ZSTD_e_end);
1702498b56bSopenharmony_ci    ZSTD_freeCCtx(cctx);
1712498b56bSopenharmony_ci    if (memcpy_s(compressedBuffer.content + compressedBuffer.offset,
1722498b56bSopenharmony_ci        MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) {
1732498b56bSopenharmony_ci        return -1;
1742498b56bSopenharmony_ci    }
1752498b56bSopenharmony_ci    compressedBuffer.offset += dst_pos;
1762498b56bSopenharmony_ci#endif // #ifdef USING_ZSTD_COMPRESS
1772498b56bSopenharmony_ci    return 0;
1782498b56bSopenharmony_ci}
1792498b56bSopenharmony_ci} // namespace HiviewDFX
1802498b56bSopenharmony_ci} // namespace OHOS
181