master
c 169 lines 4.91 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "rrdengine.h"
4 #include "dbengine-compression.h"
5
6 #ifdef ENABLE_LZ4
7 #include <lz4.h>
8 #endif
9
10 #ifdef ENABLE_ZSTD
11 #include <zstd.h>
12 #define DBENGINE_ZSTD_DEFAULT_COMPRESSION_LEVEL 3
13 #endif
14
15 uint8_t dbengine_default_compression(void) {
16
17 #ifdef ENABLE_ZSTD
18 return RRDENG_COMPRESSION_ZSTD;
19 #endif
20
21 #ifdef ENABLE_LZ4
22 return RRDENG_COMPRESSION_LZ4;
23 #endif
24
25 return RRDENG_COMPRESSION_NONE;
26 }
27
28 bool dbengine_valid_compression_algorithm(uint8_t algorithm) {
29 switch(algorithm) {
30 case RRDENG_COMPRESSION_NONE:
31
32 #ifdef ENABLE_LZ4
33 case RRDENG_COMPRESSION_LZ4:
34 #endif
35
36 #ifdef ENABLE_ZSTD
37 case RRDENG_COMPRESSION_ZSTD:
38 #endif
39
40 return true;
41
42 default:
43 return false;
44 }
45 }
46
47 size_t dbengine_max_compressed_size(size_t uncompressed_size, uint8_t algorithm) {
48 switch(algorithm) {
49 #ifdef ENABLE_LZ4
50 case RRDENG_COMPRESSION_LZ4:
51 fatal_assert(uncompressed_size < LZ4_MAX_INPUT_SIZE);
52 return LZ4_compressBound((int)uncompressed_size);
53 #endif
54
55 #ifdef ENABLE_ZSTD
56 case RRDENG_COMPRESSION_ZSTD:
57 return ZSTD_compressBound(uncompressed_size);
58 #endif
59
60 case RRDENG_COMPRESSION_NONE:
61 return uncompressed_size;
62
63 default: {
64 fatal("DBENGINE: unknown compression algorithm %u", algorithm);
65 //we will never reach this point, but we have warnings from compiler
66 return 0;
67 }
68 }
69 }
70
71 size_t dbengine_compress(void *payload, size_t uncompressed_size, uint8_t algorithm) {
72 // the result should be stored in the payload
73 // the caller must have called dbengine_max_compressed_size() to make sure the
74 // payload is big enough to fit the max size needed.
75
76 switch(algorithm) {
77 #ifdef ENABLE_LZ4
78 case RRDENG_COMPRESSION_LZ4: {
79 size_t max_compressed_size = dbengine_max_compressed_size(uncompressed_size, algorithm);
80 struct extent_buffer *eb = extent_buffer_get(max_compressed_size);
81 void *compressed_buf = eb->data;
82
83 size_t compressed_size =
84 LZ4_compress_default(payload, compressed_buf, (int)uncompressed_size, (int)max_compressed_size);
85
86 if(compressed_size > 0 && compressed_size < uncompressed_size)
87 memcpy(payload, compressed_buf, compressed_size);
88 else
89 compressed_size = 0;
90
91 extent_buffer_release(eb);
92 return compressed_size;
93 }
94 #endif
95
96 #ifdef ENABLE_ZSTD
97 case RRDENG_COMPRESSION_ZSTD: {
98 size_t max_compressed_size = dbengine_max_compressed_size(uncompressed_size, algorithm);
99 struct extent_buffer *eb = extent_buffer_get(max_compressed_size);
100 void *compressed_buf = eb->data;
101
102 size_t compressed_size = ZSTD_compress(compressed_buf, max_compressed_size, payload, uncompressed_size,
103 DBENGINE_ZSTD_DEFAULT_COMPRESSION_LEVEL);
104
105 if (ZSTD_isError(compressed_size)) {
106 internal_fatal(true, "DBENGINE: ZSTD compression error %s", ZSTD_getErrorName(compressed_size));
107 compressed_size = 0;
108 }
109
110 if(compressed_size > 0 && compressed_size < uncompressed_size)
111 memcpy(payload, compressed_buf, compressed_size);
112 else
113 compressed_size = 0;
114
115 extent_buffer_release(eb);
116 return compressed_size;
117 }
118 #endif
119
120 case RRDENG_COMPRESSION_NONE:
121 return 0;
122
123 default: {
124 fatal("DBENGINE: unknown compression algorithm %u", algorithm);
125 //we will never reach this point, but we have warnings from compiler
126 return 0;
127 }
128 }
129 }
130
131 size_t dbengine_decompress(void *dst, void *src, size_t dst_size, size_t src_size, uint8_t algorithm) {
132 switch(algorithm) {
133
134 #ifdef ENABLE_LZ4
135 case RRDENG_COMPRESSION_LZ4: {
136 int rc = LZ4_decompress_safe(src, dst, (int)src_size, (int)dst_size);
137 if(rc < 0) {
138 nd_log(NDLS_DAEMON, NDLP_ERR, "DBENGINE: ZSTD decompression error %d", rc);
139 rc = 0;
140 }
141
142 return rc;
143 }
144 #endif
145
146 #ifdef ENABLE_ZSTD
147 case RRDENG_COMPRESSION_ZSTD: {
148 size_t decompressed_size = ZSTD_decompress(dst, dst_size, src, src_size);
149
150 if (ZSTD_isError(decompressed_size)) {
151 nd_log(NDLS_DAEMON, NDLP_ERR, "DBENGINE: ZSTD decompression error %s",
152 ZSTD_getErrorName(decompressed_size));
153
154 decompressed_size = 0;
155 }
156
157 return decompressed_size;
158 }
159 #endif
160
161 case RRDENG_COMPRESSION_NONE:
162 internal_fatal(true, "DBENGINE: %s() should not be called for uncompressed pages", __FUNCTION__ );
163 return 0;
164
165 default:
166 internal_fatal(true, "DBENGINE: unknown compression algorithm %u", algorithm);
167 return 0;
168 }
169 }