• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "log_compress.h"
16 
17 #include <iostream>
18 #include <cstring>
19 #include <cstdlib>
20 #include <vector>
21 
22 #include <securec.h>
23 
24 namespace OHOS {
25 namespace HiviewDFX {
26 StringMap LogCompress::g_CompressTypes = StringMap({
27         {COMPRESS_TYPE_NONE, "none"}, {COMPRESS_TYPE_ZLIB, "zlib"}, {COMPRESS_TYPE_ZSTD, "zstd"}
28     }, COMPRESS_TYPE_ZLIB, "unknown");
29 
CompressType2Str(uint16_t compressType)30 std::string LogCompress::CompressType2Str(uint16_t compressType)
31 {
32     return g_CompressTypes.GetValue(compressType);
33 }
34 
Str2CompressType(const std::string & str)35 uint16_t LogCompress::Str2CompressType(const std::string& str)
36 {
37     return g_CompressTypes.GetKey(str);
38 }
39 
Compress(const LogPersisterBuffer & inBuffer,LogPersisterBuffer & compressedBuffer)40 int NoneCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
41 {
42     void *dest = compressedBuffer.content + compressedBuffer.offset;
43     size_t destSize = MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset;
44     if (memcpy_s(dest, destSize, inBuffer.content, inBuffer.offset) != 0) {
45         return -1;
46     }
47     compressedBuffer.offset += inBuffer.offset;
48     return 0;
49 }
50 
Compress(const LogPersisterBuffer & inBuffer,LogPersisterBuffer & compressedBuffer)51 int ZlibCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
52 {
53     cStream.zalloc = Z_NULL;
54     cStream.zfree = Z_NULL;
55     cStream.opaque = Z_NULL;
56     if (deflateInit2(&cStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
57         return -1;
58     }
59     uint32_t zdlen = deflateBound(&cStream, inBuffer.offset);
60     std::vector<char> zdataBuf(zdlen, 0);
61     char* zdata = zdataBuf.data();
62     if (zdata == nullptr) {
63         std::cerr << "no enough memory!\n";
64         return -1;
65     }
66     size_t const toRead = CHUNK;
67     size_t src_pos = 0;
68     size_t dst_pos = 0;
69     size_t read = inBuffer.offset;
70     int flush = 0;
71     do {
72         bool flag = read - src_pos < toRead;
73         if (flag) {
74             (void)memset_s(buffIn, CHUNK, 0, CHUNK);
75             if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) {
76                 return -1;
77             }
78             cStream.avail_in = read - src_pos;
79             src_pos += read - src_pos;
80         } else {
81             (void)memset_s(buffIn, CHUNK, 0, CHUNK);
82             if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) {
83                 return -1;
84             }
85             src_pos += toRead;
86             cStream.avail_in = toRead;
87         }
88         flush = flag ? Z_FINISH : Z_NO_FLUSH;
89         cStream.next_in = reinterpret_cast<Bytef*>(buffIn);
90         /* run deflate() on input until output buffer not full, finish
91            compression if all of source has been read in */
92         do {
93             cStream.avail_out = CHUNK;
94             cStream.next_out = reinterpret_cast<Bytef*>(buffOut);
95             if (deflate(&cStream, flush) == Z_STREAM_ERROR) {
96                 return -1;
97             }
98             unsigned have = CHUNK - cStream.avail_out;
99             if (memmove_s(zdata + dst_pos, zdlen - dst_pos, buffOut, have) != 0) {
100                 return -1;
101             }
102             dst_pos += have;
103             if (unlikely(zdlen < dst_pos)) { // zdataBuf is not long enough, shoudn't happen
104                 return -1;
105             }
106         } while (cStream.avail_out == 0);
107     } while (flush != Z_FINISH);
108     /* clean up and return */
109     (void)deflateEnd(&cStream);
110     if (memcpy_s(compressedBuffer.content + compressedBuffer.offset,
111         MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) {
112         return -1;
113     }
114     compressedBuffer.offset += dst_pos;
115     return 0;
116 }
117 
Compress(const LogPersisterBuffer & inBuffer,LogPersisterBuffer & compressedBuffer)118 int ZstdCompress::Compress(const LogPersisterBuffer &inBuffer, LogPersisterBuffer &compressedBuffer)
119 {
120 #ifdef USING_ZSTD_COMPRESS
121     uint32_t zdlen = ZSTD_CStreamOutSize();
122     std::vector<char> zdataBuf(zdlen, 0);
123     char* zdata = zdataBuf.data();
124     if (zdata == nullptr) {
125         std::cerr << "no enough memory!\n";
126         return -1;
127     }
128     ZSTD_EndDirective mode;
129     int compressionlevel = 1;
130     cctx = ZSTD_createCCtx();
131     if (cctx == nullptr) {
132         std::cerr << "ZSTD_createCCtx() failed!\n";
133         return -1;
134     }
135     ZSTD_CCtx_setParameter(cctx, ZSTD_c_compressionLevel, compressionlevel);
136     size_t const toRead = CHUNK;
137     auto src_pos = 0;
138     auto dst_pos = 0;
139     size_t read = inBuffer.offset;
140     ZSTD_inBuffer input;
141     do {
142         bool flag = read - src_pos < toRead;
143         if (flag) {
144             (void)memset_s(buffIn, CHUNK, 0, CHUNK);
145             if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, read - src_pos) != 0) {
146                 return -1;
147             }
148             input = {buffIn, read - src_pos, 0};
149             src_pos += read - src_pos;
150         } else {
151             (void)memset_s(buffIn, CHUNK, 0, CHUNK);
152             if (memmove_s(buffIn, CHUNK, inBuffer.content + src_pos, toRead) != 0) {
153                 return -1;
154             }
155             input = {buffIn, toRead, 0};
156             src_pos += toRead;
157         }
158         mode = flag ? ZSTD_e_end : ZSTD_e_continue;
159         int finished;
160         do {
161             ZSTD_outBuffer output = {buffOut, CHUNK, 0};
162             size_t const remaining = ZSTD_compressStream2(cctx, &output, &input, mode);
163             if (memmove_s(zdata + dst_pos, zdlen, reinterpret_cast<Bytef*>(buffOut), output.pos) != 0) {
164                 return -1;
165             }
166             dst_pos += output.pos;
167             finished = flag ? (remaining == 0) : (input.pos == input.size);
168         } while (!finished);
169     } while (mode != ZSTD_e_end);
170     ZSTD_freeCCtx(cctx);
171     if (memcpy_s(compressedBuffer.content + compressedBuffer.offset,
172         MAX_PERSISTER_BUFFER_SIZE - compressedBuffer.offset, zdata, dst_pos) != 0) {
173         return -1;
174     }
175     compressedBuffer.offset += dst_pos;
176 #endif // #ifdef USING_ZSTD_COMPRESS
177     return 0;
178 }
179 } // namespace HiviewDFX
180 } // namespace OHOS
181