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