zstd-ruby 1.4.4.0 → 1.5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +78 -5
- data/Rakefile +8 -2
- data/ext/zstdruby/common.h +15 -0
- data/ext/zstdruby/extconf.rb +3 -2
- data/ext/zstdruby/libzstd/common/allocations.h +55 -0
- data/ext/zstdruby/libzstd/common/bits.h +200 -0
- data/ext/zstdruby/libzstd/common/bitstream.h +74 -97
- data/ext/zstdruby/libzstd/common/compiler.h +219 -20
- data/ext/zstdruby/libzstd/common/cpu.h +1 -3
- data/ext/zstdruby/libzstd/common/debug.c +11 -31
- data/ext/zstdruby/libzstd/common/debug.h +22 -49
- data/ext/zstdruby/libzstd/common/entropy_common.c +184 -80
- data/ext/zstdruby/libzstd/common/error_private.c +11 -2
- data/ext/zstdruby/libzstd/common/error_private.h +87 -4
- data/ext/zstdruby/libzstd/common/fse.h +47 -116
- data/ext/zstdruby/libzstd/common/fse_decompress.c +127 -127
- data/ext/zstdruby/libzstd/common/huf.h +112 -197
- data/ext/zstdruby/libzstd/common/mem.h +124 -142
- data/ext/zstdruby/libzstd/common/pool.c +54 -27
- data/ext/zstdruby/libzstd/common/pool.h +11 -5
- data/ext/zstdruby/libzstd/common/portability_macros.h +156 -0
- data/ext/zstdruby/libzstd/common/threading.c +78 -22
- data/ext/zstdruby/libzstd/common/threading.h +9 -13
- data/ext/zstdruby/libzstd/common/xxhash.c +15 -873
- data/ext/zstdruby/libzstd/common/xxhash.h +5572 -191
- data/ext/zstdruby/libzstd/common/zstd_common.c +2 -37
- data/ext/zstdruby/libzstd/common/zstd_deps.h +111 -0
- data/ext/zstdruby/libzstd/common/zstd_internal.h +186 -144
- data/ext/zstdruby/libzstd/common/zstd_trace.h +163 -0
- data/ext/zstdruby/libzstd/compress/clevels.h +134 -0
- data/ext/zstdruby/libzstd/compress/fse_compress.c +99 -196
- data/ext/zstdruby/libzstd/compress/hist.c +41 -63
- data/ext/zstdruby/libzstd/compress/hist.h +13 -33
- data/ext/zstdruby/libzstd/compress/huf_compress.c +968 -331
- data/ext/zstdruby/libzstd/compress/zstd_compress.c +4120 -1191
- data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +688 -159
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +121 -40
- data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +16 -6
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +62 -35
- data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +10 -3
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +577 -0
- data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
- data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +322 -115
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +394 -154
- data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_fast.c +729 -253
- data/ext/zstdruby/libzstd/compress/zstd_fast.h +4 -3
- data/ext/zstdruby/libzstd/compress/zstd_lazy.c +1289 -247
- data/ext/zstdruby/libzstd/compress/zstd_lazy.h +61 -1
- data/ext/zstdruby/libzstd/compress/zstd_ldm.c +339 -212
- data/ext/zstdruby/libzstd/compress/zstd_ldm.h +15 -3
- data/ext/zstdruby/libzstd/compress/zstd_ldm_geartab.h +106 -0
- data/ext/zstdruby/libzstd/compress/zstd_opt.c +508 -282
- data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +217 -466
- data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +35 -114
- data/ext/zstdruby/libzstd/decompress/huf_decompress.c +1220 -572
- data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +576 -0
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +23 -19
- data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +3 -3
- data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +859 -273
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +1244 -375
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +21 -7
- data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +74 -11
- data/ext/zstdruby/libzstd/dictBuilder/cover.c +75 -54
- data/ext/zstdruby/libzstd/dictBuilder/cover.h +20 -9
- data/ext/zstdruby/libzstd/dictBuilder/divsufsort.c +1 -1
- data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +55 -36
- data/ext/zstdruby/libzstd/dictBuilder/zdict.c +126 -110
- data/ext/zstdruby/libzstd/{dictBuilder/zdict.h → zdict.h} +248 -56
- data/ext/zstdruby/libzstd/zstd.h +1277 -306
- data/ext/zstdruby/libzstd/{common/zstd_errors.h → zstd_errors.h} +29 -8
- data/ext/zstdruby/main.c +20 -0
- data/ext/zstdruby/skippable_frame.c +63 -0
- data/ext/zstdruby/streaming_compress.c +177 -0
- data/ext/zstdruby/streaming_compress.h +5 -0
- data/ext/zstdruby/streaming_decompress.c +123 -0
- data/ext/zstdruby/zstdruby.c +114 -32
- data/lib/zstd-ruby/version.rb +1 -1
- data/lib/zstd-ruby.rb +0 -1
- data/zstd-ruby.gemspec +1 -1
- metadata +24 -39
- data/.travis.yml +0 -14
- data/ext/zstdruby/libzstd/.gitignore +0 -3
- data/ext/zstdruby/libzstd/BUCK +0 -234
- data/ext/zstdruby/libzstd/Makefile +0 -289
- data/ext/zstdruby/libzstd/README.md +0 -159
- data/ext/zstdruby/libzstd/deprecated/zbuff.h +0 -214
- data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +0 -26
- data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +0 -147
- data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +0 -75
- data/ext/zstdruby/libzstd/dll/example/Makefile +0 -47
- data/ext/zstdruby/libzstd/dll/example/README.md +0 -69
- data/ext/zstdruby/libzstd/dll/example/build_package.bat +0 -20
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.sln +0 -25
- data/ext/zstdruby/libzstd/dll/example/fullbench-dll.vcxproj +0 -181
- data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +0 -415
- data/ext/zstdruby/libzstd/legacy/zstd_v01.c +0 -2152
- data/ext/zstdruby/libzstd/legacy/zstd_v01.h +0 -94
- data/ext/zstdruby/libzstd/legacy/zstd_v02.c +0 -3514
- data/ext/zstdruby/libzstd/legacy/zstd_v02.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v03.c +0 -3156
- data/ext/zstdruby/libzstd/legacy/zstd_v03.h +0 -93
- data/ext/zstdruby/libzstd/legacy/zstd_v04.c +0 -3641
- data/ext/zstdruby/libzstd/legacy/zstd_v04.h +0 -142
- data/ext/zstdruby/libzstd/legacy/zstd_v05.c +0 -4046
- data/ext/zstdruby/libzstd/legacy/zstd_v05.h +0 -162
- data/ext/zstdruby/libzstd/legacy/zstd_v06.c +0 -4150
- data/ext/zstdruby/libzstd/legacy/zstd_v06.h +0 -172
- data/ext/zstdruby/libzstd/legacy/zstd_v07.c +0 -4533
- data/ext/zstdruby/libzstd/legacy/zstd_v07.h +0 -187
- data/ext/zstdruby/libzstd/libzstd.pc.in +0 -15
- data/ext/zstdruby/zstdruby.h +0 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright (c)
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
3
|
* All rights reserved.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under both the BSD-style license (found in the
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
/* ====== Dependencies ====== */
|
|
23
|
-
#include
|
|
24
|
-
#include
|
|
25
|
-
#include "mem.h" /* MEM_STATIC */
|
|
26
|
-
#include "pool.h" /* threadpool */
|
|
27
|
-
#include "threading.h" /* mutex */
|
|
23
|
+
#include "../common/allocations.h" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */
|
|
24
|
+
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */
|
|
25
|
+
#include "../common/mem.h" /* MEM_STATIC */
|
|
26
|
+
#include "../common/pool.h" /* threadpool */
|
|
27
|
+
#include "../common/threading.h" /* mutex */
|
|
28
28
|
#include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
|
29
29
|
#include "zstd_ldm.h"
|
|
30
30
|
#include "zstdmt_compress.h"
|
|
@@ -103,14 +103,13 @@ typedef struct ZSTDMT_bufferPool_s {
|
|
|
103
103
|
buffer_t bTable[1]; /* variable size */
|
|
104
104
|
} ZSTDMT_bufferPool;
|
|
105
105
|
|
|
106
|
-
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned
|
|
106
|
+
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)
|
|
107
107
|
{
|
|
108
|
-
|
|
109
|
-
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
|
|
108
|
+
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
|
|
110
109
|
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
|
|
111
110
|
if (bufPool==NULL) return NULL;
|
|
112
111
|
if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {
|
|
113
|
-
|
|
112
|
+
ZSTD_customFree(bufPool, cMem);
|
|
114
113
|
return NULL;
|
|
115
114
|
}
|
|
116
115
|
bufPool->bufferSize = 64 KB;
|
|
@@ -127,10 +126,10 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
|
|
|
127
126
|
if (!bufPool) return; /* compatibility with free on NULL */
|
|
128
127
|
for (u=0; u<bufPool->totalBuffers; u++) {
|
|
129
128
|
DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start);
|
|
130
|
-
|
|
129
|
+
ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem);
|
|
131
130
|
}
|
|
132
131
|
ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);
|
|
133
|
-
|
|
132
|
+
ZSTD_customFree(bufPool, bufPool->cMem);
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
/* only works at initialization, not during compression */
|
|
@@ -161,9 +160,8 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const
|
|
|
161
160
|
}
|
|
162
161
|
|
|
163
162
|
|
|
164
|
-
static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool,
|
|
163
|
+
static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers)
|
|
165
164
|
{
|
|
166
|
-
unsigned const maxNbBuffers = 2*nbWorkers + 3;
|
|
167
165
|
if (srcBufPool==NULL) return NULL;
|
|
168
166
|
if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */
|
|
169
167
|
return srcBufPool;
|
|
@@ -172,7 +170,7 @@ static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool,
|
|
|
172
170
|
size_t const bSize = srcBufPool->bufferSize; /* forward parameters */
|
|
173
171
|
ZSTDMT_bufferPool* newBufPool;
|
|
174
172
|
ZSTDMT_freeBufferPool(srcBufPool);
|
|
175
|
-
newBufPool = ZSTDMT_createBufferPool(
|
|
173
|
+
newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem);
|
|
176
174
|
if (newBufPool==NULL) return newBufPool;
|
|
177
175
|
ZSTDMT_setBufferSize(newBufPool, bSize);
|
|
178
176
|
return newBufPool;
|
|
@@ -201,13 +199,13 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)
|
|
|
201
199
|
}
|
|
202
200
|
/* size conditions not respected : scratch this buffer, create new one */
|
|
203
201
|
DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing");
|
|
204
|
-
|
|
202
|
+
ZSTD_customFree(buf.start, bufPool->cMem);
|
|
205
203
|
}
|
|
206
204
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
|
207
205
|
/* create new buffer */
|
|
208
206
|
DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer");
|
|
209
207
|
{ buffer_t buffer;
|
|
210
|
-
void* const start =
|
|
208
|
+
void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
|
|
211
209
|
buffer.start = start; /* note : start can be NULL if malloc fails ! */
|
|
212
210
|
buffer.capacity = (start==NULL) ? 0 : bSize;
|
|
213
211
|
if (start==NULL) {
|
|
@@ -229,13 +227,13 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer)
|
|
|
229
227
|
{
|
|
230
228
|
size_t const bSize = bufPool->bufferSize;
|
|
231
229
|
if (buffer.capacity < bSize) {
|
|
232
|
-
void* const start =
|
|
230
|
+
void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);
|
|
233
231
|
buffer_t newBuffer;
|
|
234
232
|
newBuffer.start = start;
|
|
235
233
|
newBuffer.capacity = start == NULL ? 0 : bSize;
|
|
236
234
|
if (start != NULL) {
|
|
237
235
|
assert(newBuffer.capacity >= buffer.capacity);
|
|
238
|
-
|
|
236
|
+
ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity);
|
|
239
237
|
DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize);
|
|
240
238
|
return newBuffer;
|
|
241
239
|
}
|
|
@@ -261,13 +259,21 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
|
|
|
261
259
|
ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);
|
|
262
260
|
/* Reached bufferPool capacity (should not happen) */
|
|
263
261
|
DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing ");
|
|
264
|
-
|
|
262
|
+
ZSTD_customFree(buf.start, bufPool->cMem);
|
|
265
263
|
}
|
|
266
264
|
|
|
265
|
+
/* We need 2 output buffers per worker since each dstBuff must be flushed after it is released.
|
|
266
|
+
* The 3 additional buffers are as follows:
|
|
267
|
+
* 1 buffer for input loading
|
|
268
|
+
* 1 buffer for "next input" when submitting current one
|
|
269
|
+
* 1 buffer stuck in queue */
|
|
270
|
+
#define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) (2*(nbWorkers) + 3)
|
|
267
271
|
|
|
268
|
-
/*
|
|
272
|
+
/* After a worker releases its rawSeqStore, it is immediately ready for reuse.
|
|
273
|
+
* So we only need one seq buffer per worker. */
|
|
274
|
+
#define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) (nbWorkers)
|
|
269
275
|
|
|
270
|
-
|
|
276
|
+
/* ===== Seq Pool Wrapper ====== */
|
|
271
277
|
|
|
272
278
|
typedef ZSTDMT_bufferPool ZSTDMT_seqPool;
|
|
273
279
|
|
|
@@ -278,7 +284,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)
|
|
|
278
284
|
|
|
279
285
|
static rawSeqStore_t bufferToSeq(buffer_t buffer)
|
|
280
286
|
{
|
|
281
|
-
rawSeqStore_t seq =
|
|
287
|
+
rawSeqStore_t seq = kNullRawSeqStore;
|
|
282
288
|
seq.seq = (rawSeq*)buffer.start;
|
|
283
289
|
seq.capacity = buffer.capacity / sizeof(rawSeq);
|
|
284
290
|
return seq;
|
|
@@ -319,7 +325,7 @@ static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
|
|
|
319
325
|
|
|
320
326
|
static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
|
|
321
327
|
{
|
|
322
|
-
ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
|
|
328
|
+
ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
|
|
323
329
|
if (seqPool == NULL) return NULL;
|
|
324
330
|
ZSTDMT_setNbSeq(seqPool, 0);
|
|
325
331
|
return seqPool;
|
|
@@ -332,7 +338,7 @@ static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
|
|
|
332
338
|
|
|
333
339
|
static ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)
|
|
334
340
|
{
|
|
335
|
-
return ZSTDMT_expandBufferPool(pool, nbWorkers);
|
|
341
|
+
return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers));
|
|
336
342
|
}
|
|
337
343
|
|
|
338
344
|
|
|
@@ -354,7 +360,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
|
|
354
360
|
for (cid=0; cid<pool->totalCCtx; cid++)
|
|
355
361
|
ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
|
|
356
362
|
ZSTD_pthread_mutex_destroy(&pool->poolMutex);
|
|
357
|
-
|
|
363
|
+
ZSTD_customFree(pool, pool->cMem);
|
|
358
364
|
}
|
|
359
365
|
|
|
360
366
|
/* ZSTDMT_createCCtxPool() :
|
|
@@ -362,12 +368,12 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
|
|
362
368
|
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
|
|
363
369
|
ZSTD_customMem cMem)
|
|
364
370
|
{
|
|
365
|
-
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*)
|
|
371
|
+
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc(
|
|
366
372
|
sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem);
|
|
367
373
|
assert(nbWorkers > 0);
|
|
368
374
|
if (!cctxPool) return NULL;
|
|
369
375
|
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
|
|
370
|
-
|
|
376
|
+
ZSTD_customFree(cctxPool, cMem);
|
|
371
377
|
return NULL;
|
|
372
378
|
}
|
|
373
379
|
cctxPool->cMem = cMem;
|
|
@@ -461,52 +467,72 @@ typedef struct {
|
|
|
461
467
|
ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
|
|
462
468
|
} serialState_t;
|
|
463
469
|
|
|
464
|
-
static int
|
|
470
|
+
static int
|
|
471
|
+
ZSTDMT_serialState_reset(serialState_t* serialState,
|
|
472
|
+
ZSTDMT_seqPool* seqPool,
|
|
473
|
+
ZSTD_CCtx_params params,
|
|
474
|
+
size_t jobSize,
|
|
475
|
+
const void* dict, size_t const dictSize,
|
|
476
|
+
ZSTD_dictContentType_e dictContentType)
|
|
465
477
|
{
|
|
466
478
|
/* Adjust parameters */
|
|
467
|
-
if (params.ldmParams.enableLdm) {
|
|
479
|
+
if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
468
480
|
DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10);
|
|
469
481
|
ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams);
|
|
470
482
|
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
|
|
471
483
|
assert(params.ldmParams.hashRateLog < 32);
|
|
472
|
-
serialState->ldmState.hashPower =
|
|
473
|
-
ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
|
|
474
484
|
} else {
|
|
475
|
-
|
|
485
|
+
ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams));
|
|
476
486
|
}
|
|
477
487
|
serialState->nextJobID = 0;
|
|
478
488
|
if (params.fParams.checksumFlag)
|
|
479
489
|
XXH64_reset(&serialState->xxhState, 0);
|
|
480
|
-
if (params.ldmParams.enableLdm) {
|
|
490
|
+
if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
481
491
|
ZSTD_customMem cMem = params.customMem;
|
|
482
492
|
unsigned const hashLog = params.ldmParams.hashLog;
|
|
483
493
|
size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
|
|
484
494
|
unsigned const bucketLog =
|
|
485
495
|
params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
|
|
486
|
-
size_t const bucketSize = (size_t)1 << bucketLog;
|
|
487
496
|
unsigned const prevBucketLog =
|
|
488
497
|
serialState->params.ldmParams.hashLog -
|
|
489
498
|
serialState->params.ldmParams.bucketSizeLog;
|
|
499
|
+
size_t const numBuckets = (size_t)1 << bucketLog;
|
|
490
500
|
/* Size the seq pool tables */
|
|
491
501
|
ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
|
|
492
502
|
/* Reset the window */
|
|
493
|
-
|
|
494
|
-
serialState->ldmWindow = serialState->ldmState.window;
|
|
503
|
+
ZSTD_window_init(&serialState->ldmState.window);
|
|
495
504
|
/* Resize tables and output space if necessary. */
|
|
496
505
|
if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
|
|
497
|
-
|
|
498
|
-
serialState->ldmState.hashTable = (ldmEntry_t*)
|
|
506
|
+
ZSTD_customFree(serialState->ldmState.hashTable, cMem);
|
|
507
|
+
serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem);
|
|
499
508
|
}
|
|
500
509
|
if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
|
|
501
|
-
|
|
502
|
-
serialState->ldmState.bucketOffsets = (BYTE*)
|
|
510
|
+
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
|
|
511
|
+
serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);
|
|
503
512
|
}
|
|
504
513
|
if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
|
|
505
514
|
return 1;
|
|
506
515
|
/* Zero the tables */
|
|
507
|
-
|
|
508
|
-
|
|
516
|
+
ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);
|
|
517
|
+
ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);
|
|
518
|
+
|
|
519
|
+
/* Update window state and fill hash table with dict */
|
|
520
|
+
serialState->ldmState.loadedDictEnd = 0;
|
|
521
|
+
if (dictSize > 0) {
|
|
522
|
+
if (dictContentType == ZSTD_dct_rawContent) {
|
|
523
|
+
BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
|
|
524
|
+
ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);
|
|
525
|
+
ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
|
|
526
|
+
serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
|
|
527
|
+
} else {
|
|
528
|
+
/* don't even load anything */
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* Initialize serialState's copy of ldmWindow. */
|
|
533
|
+
serialState->ldmWindow = serialState->ldmState.window;
|
|
509
534
|
}
|
|
535
|
+
|
|
510
536
|
serialState->params = params;
|
|
511
537
|
serialState->params.jobSize = (U32)jobSize;
|
|
512
538
|
return 0;
|
|
@@ -515,7 +541,7 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool*
|
|
|
515
541
|
static int ZSTDMT_serialState_init(serialState_t* serialState)
|
|
516
542
|
{
|
|
517
543
|
int initError = 0;
|
|
518
|
-
|
|
544
|
+
ZSTD_memset(serialState, 0, sizeof(*serialState));
|
|
519
545
|
initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);
|
|
520
546
|
initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);
|
|
521
547
|
initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);
|
|
@@ -530,8 +556,8 @@ static void ZSTDMT_serialState_free(serialState_t* serialState)
|
|
|
530
556
|
ZSTD_pthread_cond_destroy(&serialState->cond);
|
|
531
557
|
ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);
|
|
532
558
|
ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);
|
|
533
|
-
|
|
534
|
-
|
|
559
|
+
ZSTD_customFree(serialState->ldmState.hashTable, cMem);
|
|
560
|
+
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
|
|
535
561
|
}
|
|
536
562
|
|
|
537
563
|
static void ZSTDMT_serialState_update(serialState_t* serialState,
|
|
@@ -547,12 +573,12 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
|
|
|
547
573
|
/* A future job may error and skip our job */
|
|
548
574
|
if (serialState->nextJobID == jobID) {
|
|
549
575
|
/* It is now our turn, do any processing necessary */
|
|
550
|
-
if (serialState->params.ldmParams.enableLdm) {
|
|
576
|
+
if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
551
577
|
size_t error;
|
|
552
578
|
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
|
|
553
579
|
seqStore.size == 0 && seqStore.capacity > 0);
|
|
554
580
|
assert(src.size <= serialState->params.jobSize);
|
|
555
|
-
ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
|
|
581
|
+
ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);
|
|
556
582
|
error = ZSTD_ldm_generateSequences(
|
|
557
583
|
&serialState->ldmState, &seqStore,
|
|
558
584
|
&serialState->params.ldmParams, src.start, src.size);
|
|
@@ -577,7 +603,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
|
|
|
577
603
|
if (seqStore.size > 0) {
|
|
578
604
|
size_t const err = ZSTD_referenceExternalSequences(
|
|
579
605
|
jobCCtx, seqStore.seq, seqStore.size);
|
|
580
|
-
assert(serialState->params.ldmParams.enableLdm);
|
|
606
|
+
assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable);
|
|
581
607
|
assert(!ZSTD_isError(err));
|
|
582
608
|
(void)err;
|
|
583
609
|
}
|
|
@@ -655,7 +681,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
655
681
|
if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));
|
|
656
682
|
job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
|
|
657
683
|
}
|
|
658
|
-
if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL)
|
|
684
|
+
if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL)
|
|
659
685
|
JOB_ERROR(ERROR(memory_allocation));
|
|
660
686
|
|
|
661
687
|
/* Don't compute the checksum for chunks, since we compute it externally,
|
|
@@ -663,7 +689,9 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
663
689
|
*/
|
|
664
690
|
if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
|
|
665
691
|
/* Don't run LDM for the chunks, since we handle it externally */
|
|
666
|
-
jobParams.ldmParams.enableLdm =
|
|
692
|
+
jobParams.ldmParams.enableLdm = ZSTD_ps_disable;
|
|
693
|
+
/* Correct nbWorkers to 0. */
|
|
694
|
+
jobParams.nbWorkers = 0;
|
|
667
695
|
|
|
668
696
|
|
|
669
697
|
/* init */
|
|
@@ -676,6 +704,10 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
676
704
|
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
|
677
705
|
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
|
678
706
|
}
|
|
707
|
+
if (!job->firstJob) {
|
|
708
|
+
size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);
|
|
709
|
+
if (ZSTD_isError(err)) JOB_ERROR(err);
|
|
710
|
+
}
|
|
679
711
|
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
|
680
712
|
job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
|
|
681
713
|
ZSTD_dtlm_fast,
|
|
@@ -688,7 +720,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
688
720
|
ZSTDMT_serialState_update(job->serial, cctx, rawSeqStore, job->src, job->jobID);
|
|
689
721
|
|
|
690
722
|
if (!job->firstJob) { /* flush and overwrite frame header when it's not first job */
|
|
691
|
-
size_t const hSize =
|
|
723
|
+
size_t const hSize = ZSTD_compressContinue_public(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);
|
|
692
724
|
if (ZSTD_isError(hSize)) JOB_ERROR(hSize);
|
|
693
725
|
DEBUGLOG(5, "ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)", (U32)hSize);
|
|
694
726
|
ZSTD_invalidateRepCodes(cctx);
|
|
@@ -706,7 +738,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
706
738
|
DEBUGLOG(5, "ZSTDMT_compressionJob: compress %u bytes in %i blocks", (U32)job->src.size, nbChunks);
|
|
707
739
|
assert(job->cSize == 0);
|
|
708
740
|
for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {
|
|
709
|
-
size_t const cSize =
|
|
741
|
+
size_t const cSize = ZSTD_compressContinue_public(cctx, op, oend-op, ip, chunkSize);
|
|
710
742
|
if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
|
|
711
743
|
ip += chunkSize;
|
|
712
744
|
op += cSize; assert(op < oend);
|
|
@@ -726,11 +758,18 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
|
|
726
758
|
size_t const lastBlockSize1 = job->src.size & (chunkSize-1);
|
|
727
759
|
size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;
|
|
728
760
|
size_t const cSize = (job->lastJob) ?
|
|
729
|
-
|
|
730
|
-
|
|
761
|
+
ZSTD_compressEnd_public(cctx, op, oend-op, ip, lastBlockSize) :
|
|
762
|
+
ZSTD_compressContinue_public(cctx, op, oend-op, ip, lastBlockSize);
|
|
731
763
|
if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
|
|
732
764
|
lastCBlockSize = cSize;
|
|
733
765
|
} }
|
|
766
|
+
if (!job->firstJob) {
|
|
767
|
+
/* Double check that we don't have an ext-dict, because then our
|
|
768
|
+
* repcode invalidation doesn't work.
|
|
769
|
+
*/
|
|
770
|
+
assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
|
|
771
|
+
}
|
|
772
|
+
ZSTD_CCtx_trace(cctx, 0);
|
|
734
773
|
|
|
735
774
|
_endJob:
|
|
736
775
|
ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
|
|
@@ -777,6 +816,15 @@ typedef struct {
|
|
|
777
816
|
static const roundBuff_t kNullRoundBuff = {NULL, 0, 0};
|
|
778
817
|
|
|
779
818
|
#define RSYNC_LENGTH 32
|
|
819
|
+
/* Don't create chunks smaller than the zstd block size.
|
|
820
|
+
* This stops us from regressing compression ratio too much,
|
|
821
|
+
* and ensures our output fits in ZSTD_compressBound().
|
|
822
|
+
*
|
|
823
|
+
* If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then
|
|
824
|
+
* ZSTD_COMPRESSBOUND() will need to be updated.
|
|
825
|
+
*/
|
|
826
|
+
#define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX
|
|
827
|
+
#define RSYNC_MIN_BLOCK_SIZE (1<<RSYNC_MIN_BLOCK_LOG)
|
|
780
828
|
|
|
781
829
|
typedef struct {
|
|
782
830
|
U64 hash;
|
|
@@ -798,7 +846,6 @@ struct ZSTDMT_CCtx_s {
|
|
|
798
846
|
roundBuff_t roundBuff;
|
|
799
847
|
serialState_t serial;
|
|
800
848
|
rsyncState_t rsync;
|
|
801
|
-
unsigned singleBlockingThread;
|
|
802
849
|
unsigned jobIDMask;
|
|
803
850
|
unsigned doneJobID;
|
|
804
851
|
unsigned nextJobID;
|
|
@@ -810,6 +857,7 @@ struct ZSTDMT_CCtx_s {
|
|
|
810
857
|
ZSTD_customMem cMem;
|
|
811
858
|
ZSTD_CDict* cdictLocal;
|
|
812
859
|
const ZSTD_CDict* cdict;
|
|
860
|
+
unsigned providedFactory: 1;
|
|
813
861
|
};
|
|
814
862
|
|
|
815
863
|
static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)
|
|
@@ -820,7 +868,7 @@ static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZS
|
|
|
820
868
|
ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);
|
|
821
869
|
ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);
|
|
822
870
|
}
|
|
823
|
-
|
|
871
|
+
ZSTD_customFree(jobTable, cMem);
|
|
824
872
|
}
|
|
825
873
|
|
|
826
874
|
/* ZSTDMT_allocJobsTable()
|
|
@@ -832,7 +880,7 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom
|
|
|
832
880
|
U32 const nbJobs = 1 << nbJobsLog2;
|
|
833
881
|
U32 jobNb;
|
|
834
882
|
ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)
|
|
835
|
-
|
|
883
|
+
ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);
|
|
836
884
|
int initError = 0;
|
|
837
885
|
if (jobTable==NULL) return NULL;
|
|
838
886
|
*nbJobsPtr = nbJobs;
|
|
@@ -863,12 +911,12 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
|
|
|
863
911
|
|
|
864
912
|
/* ZSTDMT_CCtxParam_setNbWorkers():
|
|
865
913
|
* Internal use only */
|
|
866
|
-
size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
|
|
914
|
+
static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
|
|
867
915
|
{
|
|
868
916
|
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
|
|
869
917
|
}
|
|
870
918
|
|
|
871
|
-
MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
|
|
919
|
+
MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
|
|
872
920
|
{
|
|
873
921
|
ZSTDMT_CCtx* mtctx;
|
|
874
922
|
U32 nbJobs = nbWorkers + 2;
|
|
@@ -881,16 +929,23 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
|
|
|
881
929
|
/* invalid custom allocator */
|
|
882
930
|
return NULL;
|
|
883
931
|
|
|
884
|
-
mtctx = (ZSTDMT_CCtx*)
|
|
932
|
+
mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem);
|
|
885
933
|
if (!mtctx) return NULL;
|
|
886
934
|
ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);
|
|
887
935
|
mtctx->cMem = cMem;
|
|
888
936
|
mtctx->allJobsCompleted = 1;
|
|
889
|
-
|
|
937
|
+
if (pool != NULL) {
|
|
938
|
+
mtctx->factory = pool;
|
|
939
|
+
mtctx->providedFactory = 1;
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
942
|
+
mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);
|
|
943
|
+
mtctx->providedFactory = 0;
|
|
944
|
+
}
|
|
890
945
|
mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
|
|
891
946
|
assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
|
|
892
947
|
mtctx->jobIDMask = nbJobs - 1;
|
|
893
|
-
mtctx->bufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
|
|
948
|
+
mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
|
|
894
949
|
mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);
|
|
895
950
|
mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);
|
|
896
951
|
initError = ZSTDMT_serialState_init(&mtctx->serial);
|
|
@@ -903,22 +958,18 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
|
|
|
903
958
|
return mtctx;
|
|
904
959
|
}
|
|
905
960
|
|
|
906
|
-
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
|
|
961
|
+
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)
|
|
907
962
|
{
|
|
908
963
|
#ifdef ZSTD_MULTITHREAD
|
|
909
|
-
return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
|
|
964
|
+
return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool);
|
|
910
965
|
#else
|
|
911
966
|
(void)nbWorkers;
|
|
912
967
|
(void)cMem;
|
|
968
|
+
(void)pool;
|
|
913
969
|
return NULL;
|
|
914
970
|
#endif
|
|
915
971
|
}
|
|
916
972
|
|
|
917
|
-
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
|
|
918
|
-
{
|
|
919
|
-
return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
|
|
920
|
-
}
|
|
921
|
-
|
|
922
973
|
|
|
923
974
|
/* ZSTDMT_releaseAllJobResources() :
|
|
924
975
|
* note : ensure all workers are killed first ! */
|
|
@@ -935,7 +986,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
|
|
|
935
986
|
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
|
|
936
987
|
|
|
937
988
|
/* Clear the job description, but keep the mutex/cond */
|
|
938
|
-
|
|
989
|
+
ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
|
|
939
990
|
mtctx->jobs[jobID].job_mutex = mutex;
|
|
940
991
|
mtctx->jobs[jobID].job_cond = cond;
|
|
941
992
|
}
|
|
@@ -962,7 +1013,8 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)
|
|
|
962
1013
|
size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
|
|
963
1014
|
{
|
|
964
1015
|
if (mtctx==NULL) return 0; /* compatible with free on NULL */
|
|
965
|
-
|
|
1016
|
+
if (!mtctx->providedFactory)
|
|
1017
|
+
POOL_free(mtctx->factory); /* stop and free worker threads */
|
|
966
1018
|
ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */
|
|
967
1019
|
ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);
|
|
968
1020
|
ZSTDMT_freeBufferPool(mtctx->bufPool);
|
|
@@ -971,8 +1023,8 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
|
|
|
971
1023
|
ZSTDMT_serialState_free(&mtctx->serial);
|
|
972
1024
|
ZSTD_freeCDict(mtctx->cdictLocal);
|
|
973
1025
|
if (mtctx->roundBuff.buffer)
|
|
974
|
-
|
|
975
|
-
|
|
1026
|
+
ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
|
|
1027
|
+
ZSTD_customFree(mtctx, mtctx->cMem);
|
|
976
1028
|
return 0;
|
|
977
1029
|
}
|
|
978
1030
|
|
|
@@ -989,73 +1041,14 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
|
|
|
989
1041
|
+ mtctx->roundBuff.capacity;
|
|
990
1042
|
}
|
|
991
1043
|
|
|
992
|
-
/* Internal only */
|
|
993
|
-
size_t
|
|
994
|
-
ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
|
|
995
|
-
ZSTDMT_parameter parameter,
|
|
996
|
-
int value)
|
|
997
|
-
{
|
|
998
|
-
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter");
|
|
999
|
-
switch(parameter)
|
|
1000
|
-
{
|
|
1001
|
-
case ZSTDMT_p_jobSize :
|
|
1002
|
-
DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
|
|
1003
|
-
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
|
|
1004
|
-
case ZSTDMT_p_overlapLog :
|
|
1005
|
-
DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
|
|
1006
|
-
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
|
|
1007
|
-
case ZSTDMT_p_rsyncable :
|
|
1008
|
-
DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
|
|
1009
|
-
return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
|
|
1010
|
-
default :
|
|
1011
|
-
return ERROR(parameter_unsupported);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value)
|
|
1016
|
-
{
|
|
1017
|
-
DEBUGLOG(4, "ZSTDMT_setMTCtxParameter");
|
|
1018
|
-
return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value);
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value)
|
|
1022
|
-
{
|
|
1023
|
-
switch (parameter) {
|
|
1024
|
-
case ZSTDMT_p_jobSize:
|
|
1025
|
-
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
|
|
1026
|
-
case ZSTDMT_p_overlapLog:
|
|
1027
|
-
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
|
|
1028
|
-
case ZSTDMT_p_rsyncable:
|
|
1029
|
-
return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
|
|
1030
|
-
default:
|
|
1031
|
-
return ERROR(parameter_unsupported);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
/* Sets parameters relevant to the compression job,
|
|
1036
|
-
* initializing others to default values. */
|
|
1037
|
-
static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params)
|
|
1038
|
-
{
|
|
1039
|
-
ZSTD_CCtx_params jobParams = *params;
|
|
1040
|
-
/* Clear parameters related to multithreading */
|
|
1041
|
-
jobParams.forceWindow = 0;
|
|
1042
|
-
jobParams.nbWorkers = 0;
|
|
1043
|
-
jobParams.jobSize = 0;
|
|
1044
|
-
jobParams.overlapLog = 0;
|
|
1045
|
-
jobParams.rsyncable = 0;
|
|
1046
|
-
memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
|
|
1047
|
-
memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
|
|
1048
|
-
return jobParams;
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1044
|
|
|
1052
1045
|
/* ZSTDMT_resize() :
|
|
1053
1046
|
* @return : error code if fails, 0 on success */
|
|
1054
1047
|
static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
|
|
1055
1048
|
{
|
|
1056
1049
|
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
|
|
1057
|
-
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
|
|
1058
|
-
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
|
|
1050
|
+
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , "");
|
|
1051
|
+
mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers));
|
|
1059
1052
|
if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
|
|
1060
1053
|
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
|
|
1061
1054
|
if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);
|
|
@@ -1076,7 +1069,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
|
|
|
1076
1069
|
DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)",
|
|
1077
1070
|
compressionLevel);
|
|
1078
1071
|
mtctx->params.compressionLevel = compressionLevel;
|
|
1079
|
-
{ ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, 0,
|
|
1072
|
+
{ ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
|
1080
1073
|
cParams.windowLog = saved_wlog;
|
|
1081
1074
|
mtctx->params.cParams = cParams;
|
|
1082
1075
|
}
|
|
@@ -1160,11 +1153,11 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
|
|
|
1160
1153
|
static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)
|
|
1161
1154
|
{
|
|
1162
1155
|
unsigned jobLog;
|
|
1163
|
-
if (params->ldmParams.enableLdm) {
|
|
1156
|
+
if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
1164
1157
|
/* In Long Range Mode, the windowLog is typically oversized.
|
|
1165
1158
|
* In which case, it's preferable to determine the jobSize
|
|
1166
|
-
* based on
|
|
1167
|
-
jobLog = MAX(21, params->cParams.chainLog +
|
|
1159
|
+
* based on cycleLog instead. */
|
|
1160
|
+
jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3);
|
|
1168
1161
|
} else {
|
|
1169
1162
|
jobLog = MAX(20, params->cParams.windowLog + 2);
|
|
1170
1163
|
}
|
|
@@ -1204,7 +1197,7 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
|
|
|
1204
1197
|
int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);
|
|
1205
1198
|
int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);
|
|
1206
1199
|
assert(0 <= overlapRLog && overlapRLog <= 8);
|
|
1207
|
-
if (params->ldmParams.enableLdm) {
|
|
1200
|
+
if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
1208
1201
|
/* In Long Range Mode, the windowLog is typically oversized.
|
|
1209
1202
|
* In which case, it's preferable to determine the jobSize
|
|
1210
1203
|
* based on chainLog instead.
|
|
@@ -1218,172 +1211,6 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
|
|
|
1218
1211
|
return (ovLog==0) ? 0 : (size_t)1 << ovLog;
|
|
1219
1212
|
}
|
|
1220
1213
|
|
|
1221
|
-
static unsigned
|
|
1222
|
-
ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers)
|
|
1223
|
-
{
|
|
1224
|
-
assert(nbWorkers>0);
|
|
1225
|
-
{ size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
|
|
1226
|
-
size_t const jobMaxSize = jobSizeTarget << 2;
|
|
1227
|
-
size_t const passSizeMax = jobMaxSize * nbWorkers;
|
|
1228
|
-
unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1;
|
|
1229
|
-
unsigned const nbJobsLarge = multiplier * nbWorkers;
|
|
1230
|
-
unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1;
|
|
1231
|
-
unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers);
|
|
1232
|
-
return (multiplier>1) ? nbJobsLarge : nbJobsSmall;
|
|
1233
|
-
} }
|
|
1234
|
-
|
|
1235
|
-
/* ZSTDMT_compress_advanced_internal() :
|
|
1236
|
-
* This is a blocking function : it will only give back control to caller after finishing its compression job.
|
|
1237
|
-
*/
|
|
1238
|
-
static size_t ZSTDMT_compress_advanced_internal(
|
|
1239
|
-
ZSTDMT_CCtx* mtctx,
|
|
1240
|
-
void* dst, size_t dstCapacity,
|
|
1241
|
-
const void* src, size_t srcSize,
|
|
1242
|
-
const ZSTD_CDict* cdict,
|
|
1243
|
-
ZSTD_CCtx_params params)
|
|
1244
|
-
{
|
|
1245
|
-
ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(¶ms);
|
|
1246
|
-
size_t const overlapSize = ZSTDMT_computeOverlapSize(¶ms);
|
|
1247
|
-
unsigned const nbJobs = ZSTDMT_computeNbJobs(¶ms, srcSize, params.nbWorkers);
|
|
1248
|
-
size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
|
|
1249
|
-
size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
|
|
1250
|
-
const char* const srcStart = (const char*)src;
|
|
1251
|
-
size_t remainingSrcSize = srcSize;
|
|
1252
|
-
unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */
|
|
1253
|
-
size_t frameStartPos = 0, dstBufferPos = 0;
|
|
1254
|
-
assert(jobParams.nbWorkers == 0);
|
|
1255
|
-
assert(mtctx->cctxPool->totalCCtx == params.nbWorkers);
|
|
1256
|
-
|
|
1257
|
-
params.jobSize = (U32)avgJobSize;
|
|
1258
|
-
DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ",
|
|
1259
|
-
nbJobs, (U32)proposedJobSize, (U32)avgJobSize);
|
|
1260
|
-
|
|
1261
|
-
if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */
|
|
1262
|
-
ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
|
|
1263
|
-
DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode");
|
|
1264
|
-
if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
|
|
1265
|
-
return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams);
|
|
1266
|
-
}
|
|
1267
|
-
|
|
1268
|
-
assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */
|
|
1269
|
-
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
|
|
1270
|
-
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
|
|
1271
|
-
return ERROR(memory_allocation);
|
|
1272
|
-
|
|
1273
|
-
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
|
|
1274
|
-
|
|
1275
|
-
{ unsigned u;
|
|
1276
|
-
for (u=0; u<nbJobs; u++) {
|
|
1277
|
-
size_t const jobSize = MIN(remainingSrcSize, avgJobSize);
|
|
1278
|
-
size_t const dstBufferCapacity = ZSTD_compressBound(jobSize);
|
|
1279
|
-
buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity };
|
|
1280
|
-
buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer;
|
|
1281
|
-
size_t dictSize = u ? overlapSize : 0;
|
|
1282
|
-
|
|
1283
|
-
mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize;
|
|
1284
|
-
mtctx->jobs[u].prefix.size = dictSize;
|
|
1285
|
-
mtctx->jobs[u].src.start = srcStart + frameStartPos;
|
|
1286
|
-
mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */
|
|
1287
|
-
mtctx->jobs[u].consumed = 0;
|
|
1288
|
-
mtctx->jobs[u].cSize = 0;
|
|
1289
|
-
mtctx->jobs[u].cdict = (u==0) ? cdict : NULL;
|
|
1290
|
-
mtctx->jobs[u].fullFrameSize = srcSize;
|
|
1291
|
-
mtctx->jobs[u].params = jobParams;
|
|
1292
|
-
/* do not calculate checksum within sections, but write it in header for first section */
|
|
1293
|
-
mtctx->jobs[u].dstBuff = dstBuffer;
|
|
1294
|
-
mtctx->jobs[u].cctxPool = mtctx->cctxPool;
|
|
1295
|
-
mtctx->jobs[u].bufPool = mtctx->bufPool;
|
|
1296
|
-
mtctx->jobs[u].seqPool = mtctx->seqPool;
|
|
1297
|
-
mtctx->jobs[u].serial = &mtctx->serial;
|
|
1298
|
-
mtctx->jobs[u].jobID = u;
|
|
1299
|
-
mtctx->jobs[u].firstJob = (u==0);
|
|
1300
|
-
mtctx->jobs[u].lastJob = (u==nbJobs-1);
|
|
1301
|
-
|
|
1302
|
-
DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize);
|
|
1303
|
-
DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12);
|
|
1304
|
-
POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]);
|
|
1305
|
-
|
|
1306
|
-
frameStartPos += jobSize;
|
|
1307
|
-
dstBufferPos += dstBufferCapacity;
|
|
1308
|
-
remainingSrcSize -= jobSize;
|
|
1309
|
-
} }
|
|
1310
|
-
|
|
1311
|
-
/* collect result */
|
|
1312
|
-
{ size_t error = 0, dstPos = 0;
|
|
1313
|
-
unsigned jobID;
|
|
1314
|
-
for (jobID=0; jobID<nbJobs; jobID++) {
|
|
1315
|
-
DEBUGLOG(5, "waiting for job %u ", jobID);
|
|
1316
|
-
ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);
|
|
1317
|
-
while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {
|
|
1318
|
-
DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID);
|
|
1319
|
-
ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);
|
|
1320
|
-
}
|
|
1321
|
-
ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);
|
|
1322
|
-
DEBUGLOG(5, "ready to write job %u ", jobID);
|
|
1323
|
-
|
|
1324
|
-
{ size_t const cSize = mtctx->jobs[jobID].cSize;
|
|
1325
|
-
if (ZSTD_isError(cSize)) error = cSize;
|
|
1326
|
-
if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall);
|
|
1327
|
-
if (jobID) { /* note : job 0 is written directly at dst, which is correct position */
|
|
1328
|
-
if (!error)
|
|
1329
|
-
memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */
|
|
1330
|
-
if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */
|
|
1331
|
-
DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst);
|
|
1332
|
-
ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
|
|
1333
|
-
} }
|
|
1334
|
-
mtctx->jobs[jobID].dstBuff = g_nullBuffer;
|
|
1335
|
-
mtctx->jobs[jobID].cSize = 0;
|
|
1336
|
-
dstPos += cSize ;
|
|
1337
|
-
}
|
|
1338
|
-
} /* for (jobID=0; jobID<nbJobs; jobID++) */
|
|
1339
|
-
|
|
1340
|
-
DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag);
|
|
1341
|
-
if (params.fParams.checksumFlag) {
|
|
1342
|
-
U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);
|
|
1343
|
-
if (dstPos + 4 > dstCapacity) {
|
|
1344
|
-
error = ERROR(dstSize_tooSmall);
|
|
1345
|
-
} else {
|
|
1346
|
-
DEBUGLOG(4, "writing checksum : %08X \n", checksum);
|
|
1347
|
-
MEM_writeLE32((char*)dst + dstPos, checksum);
|
|
1348
|
-
dstPos += 4;
|
|
1349
|
-
} }
|
|
1350
|
-
|
|
1351
|
-
if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos);
|
|
1352
|
-
return error ? error : dstPos;
|
|
1353
|
-
}
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx,
|
|
1357
|
-
void* dst, size_t dstCapacity,
|
|
1358
|
-
const void* src, size_t srcSize,
|
|
1359
|
-
const ZSTD_CDict* cdict,
|
|
1360
|
-
ZSTD_parameters params,
|
|
1361
|
-
int overlapLog)
|
|
1362
|
-
{
|
|
1363
|
-
ZSTD_CCtx_params cctxParams = mtctx->params;
|
|
1364
|
-
cctxParams.cParams = params.cParams;
|
|
1365
|
-
cctxParams.fParams = params.fParams;
|
|
1366
|
-
assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX);
|
|
1367
|
-
cctxParams.overlapLog = overlapLog;
|
|
1368
|
-
return ZSTDMT_compress_advanced_internal(mtctx,
|
|
1369
|
-
dst, dstCapacity,
|
|
1370
|
-
src, srcSize,
|
|
1371
|
-
cdict, cctxParams);
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
|
1376
|
-
void* dst, size_t dstCapacity,
|
|
1377
|
-
const void* src, size_t srcSize,
|
|
1378
|
-
int compressionLevel)
|
|
1379
|
-
{
|
|
1380
|
-
ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0);
|
|
1381
|
-
int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy);
|
|
1382
|
-
params.fParams.contentSizeFlag = 1;
|
|
1383
|
-
return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog);
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
1214
|
/* ====================================== */
|
|
1388
1215
|
/* ======= Streaming API ======= */
|
|
1389
1216
|
/* ====================================== */
|
|
@@ -1403,21 +1230,11 @@ size_t ZSTDMT_initCStream_internal(
|
|
|
1403
1230
|
|
|
1404
1231
|
/* init */
|
|
1405
1232
|
if (params.nbWorkers != mtctx->params.nbWorkers)
|
|
1406
|
-
FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) );
|
|
1233
|
+
FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) , "");
|
|
1407
1234
|
|
|
1408
1235
|
if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
|
|
1409
1236
|
if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
|
|
1410
1237
|
|
|
1411
|
-
mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
|
|
1412
|
-
if (mtctx->singleBlockingThread) {
|
|
1413
|
-
ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(¶ms);
|
|
1414
|
-
DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode");
|
|
1415
|
-
assert(singleThreadParams.nbWorkers == 0);
|
|
1416
|
-
return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0],
|
|
1417
|
-
dict, dictSize, cdict,
|
|
1418
|
-
&singleThreadParams, pledgedSrcSize);
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
1238
|
DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers);
|
|
1422
1239
|
|
|
1423
1240
|
if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */
|
|
@@ -1451,9 +1268,11 @@ size_t ZSTDMT_initCStream_internal(
|
|
|
1451
1268
|
|
|
1452
1269
|
if (params.rsyncable) {
|
|
1453
1270
|
/* Aim for the targetsectionSize as the average job size. */
|
|
1454
|
-
U32 const
|
|
1455
|
-
U32 const rsyncBits = ZSTD_highbit32(
|
|
1456
|
-
|
|
1271
|
+
U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);
|
|
1272
|
+
U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);
|
|
1273
|
+
/* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our
|
|
1274
|
+
* expected job size is at least 4x larger. */
|
|
1275
|
+
assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2);
|
|
1457
1276
|
DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
|
|
1458
1277
|
mtctx->rsync.hash = 0;
|
|
1459
1278
|
mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
|
|
@@ -1465,7 +1284,7 @@ size_t ZSTDMT_initCStream_internal(
|
|
|
1465
1284
|
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));
|
|
1466
1285
|
{
|
|
1467
1286
|
/* If ldm is enabled we need windowSize space. */
|
|
1468
|
-
size_t const windowSize = mtctx->params.ldmParams.enableLdm ? (1U << mtctx->params.cParams.windowLog) : 0;
|
|
1287
|
+
size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0;
|
|
1469
1288
|
/* Two buffers of slack, plus extra space for the overlap
|
|
1470
1289
|
* This is the minimum slack that LDM works with. One extra because
|
|
1471
1290
|
* flush might waste up to targetSectionSize-1 bytes. Another extra
|
|
@@ -1480,8 +1299,8 @@ size_t ZSTDMT_initCStream_internal(
|
|
|
1480
1299
|
size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;
|
|
1481
1300
|
if (mtctx->roundBuff.capacity < capacity) {
|
|
1482
1301
|
if (mtctx->roundBuff.buffer)
|
|
1483
|
-
|
|
1484
|
-
mtctx->roundBuff.buffer = (BYTE*)
|
|
1302
|
+
ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);
|
|
1303
|
+
mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem);
|
|
1485
1304
|
if (mtctx->roundBuff.buffer == NULL) {
|
|
1486
1305
|
mtctx->roundBuff.capacity = 0;
|
|
1487
1306
|
return ERROR(memory_allocation);
|
|
@@ -1500,58 +1319,12 @@ size_t ZSTDMT_initCStream_internal(
|
|
|
1500
1319
|
mtctx->allJobsCompleted = 0;
|
|
1501
1320
|
mtctx->consumed = 0;
|
|
1502
1321
|
mtctx->produced = 0;
|
|
1503
|
-
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize
|
|
1322
|
+
if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize,
|
|
1323
|
+
dict, dictSize, dictContentType))
|
|
1504
1324
|
return ERROR(memory_allocation);
|
|
1505
1325
|
return 0;
|
|
1506
1326
|
}
|
|
1507
1327
|
|
|
1508
|
-
size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
|
1509
|
-
const void* dict, size_t dictSize,
|
|
1510
|
-
ZSTD_parameters params,
|
|
1511
|
-
unsigned long long pledgedSrcSize)
|
|
1512
|
-
{
|
|
1513
|
-
ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
|
|
1514
|
-
DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize);
|
|
1515
|
-
cctxParams.cParams = params.cParams;
|
|
1516
|
-
cctxParams.fParams = params.fParams;
|
|
1517
|
-
return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL,
|
|
1518
|
-
cctxParams, pledgedSrcSize);
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
|
1522
|
-
const ZSTD_CDict* cdict,
|
|
1523
|
-
ZSTD_frameParameters fParams,
|
|
1524
|
-
unsigned long long pledgedSrcSize)
|
|
1525
|
-
{
|
|
1526
|
-
ZSTD_CCtx_params cctxParams = mtctx->params;
|
|
1527
|
-
if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
|
|
1528
|
-
cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict);
|
|
1529
|
-
cctxParams.fParams = fParams;
|
|
1530
|
-
return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict,
|
|
1531
|
-
cctxParams, pledgedSrcSize);
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
/* ZSTDMT_resetCStream() :
|
|
1536
|
-
* pledgedSrcSize can be zero == unknown (for the time being)
|
|
1537
|
-
* prefer using ZSTD_CONTENTSIZE_UNKNOWN,
|
|
1538
|
-
* as `0` might mean "empty" in the future */
|
|
1539
|
-
size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize)
|
|
1540
|
-
{
|
|
1541
|
-
if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
|
1542
|
-
return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params,
|
|
1543
|
-
pledgedSrcSize);
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
|
|
1547
|
-
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0);
|
|
1548
|
-
ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */
|
|
1549
|
-
DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel);
|
|
1550
|
-
cctxParams.cParams = params.cParams;
|
|
1551
|
-
cctxParams.fParams = params.fParams;
|
|
1552
|
-
return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN);
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
1328
|
|
|
1556
1329
|
/* ZSTDMT_writeLastEmptyBlock()
|
|
1557
1330
|
* Write a single empty block with an end-of-frame to finish a frame.
|
|
@@ -1714,9 +1487,11 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
|
|
|
1714
1487
|
assert(mtctx->doneJobID < mtctx->nextJobID);
|
|
1715
1488
|
assert(cSize >= mtctx->jobs[wJobID].dstFlushed);
|
|
1716
1489
|
assert(mtctx->jobs[wJobID].dstBuff.start != NULL);
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1490
|
+
if (toFlush > 0) {
|
|
1491
|
+
ZSTD_memcpy((char*)output->dst + output->pos,
|
|
1492
|
+
(const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
|
|
1493
|
+
toFlush);
|
|
1494
|
+
}
|
|
1720
1495
|
output->pos += toFlush;
|
|
1721
1496
|
mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */
|
|
1722
1497
|
|
|
@@ -1784,17 +1559,21 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
|
|
|
1784
1559
|
static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
|
|
1785
1560
|
{
|
|
1786
1561
|
BYTE const* const bufferStart = (BYTE const*)buffer.start;
|
|
1787
|
-
BYTE const* const bufferEnd = bufferStart + buffer.capacity;
|
|
1788
1562
|
BYTE const* const rangeStart = (BYTE const*)range.start;
|
|
1789
|
-
BYTE const* const rangeEnd = rangeStart + range.size;
|
|
1790
1563
|
|
|
1791
1564
|
if (rangeStart == NULL || bufferStart == NULL)
|
|
1792
1565
|
return 0;
|
|
1793
|
-
/* Empty ranges cannot overlap */
|
|
1794
|
-
if (bufferStart == bufferEnd || rangeStart == rangeEnd)
|
|
1795
|
-
return 0;
|
|
1796
1566
|
|
|
1797
|
-
|
|
1567
|
+
{
|
|
1568
|
+
BYTE const* const bufferEnd = bufferStart + buffer.capacity;
|
|
1569
|
+
BYTE const* const rangeEnd = rangeStart + range.size;
|
|
1570
|
+
|
|
1571
|
+
/* Empty ranges cannot overlap */
|
|
1572
|
+
if (bufferStart == bufferEnd || rangeStart == rangeEnd)
|
|
1573
|
+
return 0;
|
|
1574
|
+
|
|
1575
|
+
return bufferStart < rangeEnd && rangeStart < bufferEnd;
|
|
1576
|
+
}
|
|
1798
1577
|
}
|
|
1799
1578
|
|
|
1800
1579
|
static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
|
|
@@ -1821,7 +1600,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
|
|
|
1821
1600
|
|
|
1822
1601
|
static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
|
|
1823
1602
|
{
|
|
1824
|
-
if (mtctx->params.ldmParams.enableLdm) {
|
|
1603
|
+
if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) {
|
|
1825
1604
|
ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
|
|
1826
1605
|
DEBUGLOG(5, "ZSTDMT_waitForLdmComplete");
|
|
1827
1606
|
DEBUGLOG(5, "source [0x%zx, 0x%zx)",
|
|
@@ -1867,7 +1646,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)
|
|
|
1867
1646
|
return 0;
|
|
1868
1647
|
}
|
|
1869
1648
|
ZSTDMT_waitForLdmComplete(mtctx, buffer);
|
|
1870
|
-
|
|
1649
|
+
ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);
|
|
1871
1650
|
mtctx->inBuff.prefix.start = start;
|
|
1872
1651
|
mtctx->roundBuff.pos = prefixSize;
|
|
1873
1652
|
}
|
|
@@ -1924,6 +1703,11 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
|
|
|
1924
1703
|
if (!mtctx->params.rsyncable)
|
|
1925
1704
|
/* Rsync is disabled. */
|
|
1926
1705
|
return syncPoint;
|
|
1706
|
+
if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE)
|
|
1707
|
+
/* We don't emit synchronization points if it would produce too small blocks.
|
|
1708
|
+
* We don't have enough input to find a synchronization point, so don't look.
|
|
1709
|
+
*/
|
|
1710
|
+
return syncPoint;
|
|
1927
1711
|
if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)
|
|
1928
1712
|
/* Not enough to compute the hash.
|
|
1929
1713
|
* We will miss any synchronization points in this RSYNC_LENGTH byte
|
|
@@ -1934,23 +1718,41 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
|
|
|
1934
1718
|
*/
|
|
1935
1719
|
return syncPoint;
|
|
1936
1720
|
/* Initialize the loop variables. */
|
|
1937
|
-
if (mtctx->inBuff.filled
|
|
1938
|
-
/* We
|
|
1721
|
+
if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) {
|
|
1722
|
+
/* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions
|
|
1723
|
+
* because they can't possibly be a sync point. So we can start
|
|
1724
|
+
* part way through the input buffer.
|
|
1725
|
+
*/
|
|
1726
|
+
pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled;
|
|
1727
|
+
if (pos >= RSYNC_LENGTH) {
|
|
1728
|
+
prev = istart + pos - RSYNC_LENGTH;
|
|
1729
|
+
hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
|
|
1730
|
+
} else {
|
|
1731
|
+
assert(mtctx->inBuff.filled >= RSYNC_LENGTH);
|
|
1732
|
+
prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
|
|
1733
|
+
hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos));
|
|
1734
|
+
hash = ZSTD_rollingHash_append(hash, istart, pos);
|
|
1735
|
+
}
|
|
1736
|
+
} else {
|
|
1737
|
+
/* We have enough bytes buffered to initialize the hash,
|
|
1738
|
+
* and have processed enough bytes to find a sync point.
|
|
1939
1739
|
* Start scanning at the beginning of the input.
|
|
1940
1740
|
*/
|
|
1741
|
+
assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE);
|
|
1742
|
+
assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH);
|
|
1941
1743
|
pos = 0;
|
|
1942
1744
|
prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
|
|
1943
1745
|
hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1746
|
+
if ((hash & hitMask) == hitMask) {
|
|
1747
|
+
/* We're already at a sync point so don't load any more until
|
|
1748
|
+
* we're able to flush this sync point.
|
|
1749
|
+
* This likely happened because the job table was full so we
|
|
1750
|
+
* couldn't add our job.
|
|
1751
|
+
*/
|
|
1752
|
+
syncPoint.toLoad = 0;
|
|
1753
|
+
syncPoint.flush = 1;
|
|
1754
|
+
return syncPoint;
|
|
1755
|
+
}
|
|
1954
1756
|
}
|
|
1955
1757
|
/* Starting with the hash of the previous RSYNC_LENGTH bytes, roll
|
|
1956
1758
|
* through the input. If we hit a synchronization point, then cut the
|
|
@@ -1960,16 +1762,24 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
|
|
|
1960
1762
|
* then a block will be emitted anyways, but this is okay, since if we
|
|
1961
1763
|
* are already synchronized we will remain synchronized.
|
|
1962
1764
|
*/
|
|
1765
|
+
assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);
|
|
1963
1766
|
for (; pos < syncPoint.toLoad; ++pos) {
|
|
1964
1767
|
BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];
|
|
1965
|
-
/*
|
|
1768
|
+
/* This assert is very expensive, and Debian compiles with asserts enabled.
|
|
1769
|
+
* So disable it for now. We can get similar coverage by checking it at the
|
|
1770
|
+
* beginning & end of the loop.
|
|
1771
|
+
* assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);
|
|
1772
|
+
*/
|
|
1966
1773
|
hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);
|
|
1774
|
+
assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE);
|
|
1967
1775
|
if ((hash & hitMask) == hitMask) {
|
|
1968
1776
|
syncPoint.toLoad = pos + 1;
|
|
1969
1777
|
syncPoint.flush = 1;
|
|
1778
|
+
++pos; /* for assert */
|
|
1970
1779
|
break;
|
|
1971
1780
|
}
|
|
1972
1781
|
}
|
|
1782
|
+
assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);
|
|
1973
1783
|
return syncPoint;
|
|
1974
1784
|
}
|
|
1975
1785
|
|
|
@@ -1995,34 +1805,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
|
1995
1805
|
assert(output->pos <= output->size);
|
|
1996
1806
|
assert(input->pos <= input->size);
|
|
1997
1807
|
|
|
1998
|
-
if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
|
|
1999
|
-
return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
1808
|
if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
|
|
2003
1809
|
/* current frame being ended. Only flush/end are allowed */
|
|
2004
1810
|
return ERROR(stage_wrong);
|
|
2005
1811
|
}
|
|
2006
1812
|
|
|
2007
|
-
/* single-pass shortcut (note : synchronous-mode) */
|
|
2008
|
-
if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */
|
|
2009
|
-
&& (mtctx->nextJobID == 0) /* just started */
|
|
2010
|
-
&& (mtctx->inBuff.filled == 0) /* nothing buffered */
|
|
2011
|
-
&& (!mtctx->jobReady) /* no job already created */
|
|
2012
|
-
&& (endOp == ZSTD_e_end) /* end order */
|
|
2013
|
-
&& (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */
|
|
2014
|
-
size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx,
|
|
2015
|
-
(char*)output->dst + output->pos, output->size - output->pos,
|
|
2016
|
-
(const char*)input->src + input->pos, input->size - input->pos,
|
|
2017
|
-
mtctx->cdict, mtctx->params);
|
|
2018
|
-
if (ZSTD_isError(cSize)) return cSize;
|
|
2019
|
-
input->pos = input->size;
|
|
2020
|
-
output->pos += cSize;
|
|
2021
|
-
mtctx->allJobsCompleted = 1;
|
|
2022
|
-
mtctx->frameEnded = 1;
|
|
2023
|
-
return 0;
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
1813
|
/* fill input buffer */
|
|
2027
1814
|
if ( (!mtctx->jobReady)
|
|
2028
1815
|
&& (input->size > input->pos) ) { /* support NULL input */
|
|
@@ -2045,13 +1832,21 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
|
2045
1832
|
assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);
|
|
2046
1833
|
DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u",
|
|
2047
1834
|
(U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);
|
|
2048
|
-
|
|
1835
|
+
ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);
|
|
2049
1836
|
input->pos += syncPoint.toLoad;
|
|
2050
1837
|
mtctx->inBuff.filled += syncPoint.toLoad;
|
|
2051
1838
|
forwardInputProgress = syncPoint.toLoad>0;
|
|
2052
1839
|
}
|
|
2053
|
-
|
|
2054
|
-
|
|
1840
|
+
}
|
|
1841
|
+
if ((input->pos < input->size) && (endOp == ZSTD_e_end)) {
|
|
1842
|
+
/* Can't end yet because the input is not fully consumed.
|
|
1843
|
+
* We are in one of these cases:
|
|
1844
|
+
* - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job.
|
|
1845
|
+
* - We filled the input buffer: flush this job but don't end the frame.
|
|
1846
|
+
* - We hit a synchronization point: flush this job but don't end the frame.
|
|
1847
|
+
*/
|
|
1848
|
+
assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable);
|
|
1849
|
+
endOp = ZSTD_e_flush;
|
|
2055
1850
|
}
|
|
2056
1851
|
|
|
2057
1852
|
if ( (mtctx->jobReady)
|
|
@@ -2060,7 +1855,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
|
2060
1855
|
|| ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
|
|
2061
1856
|
size_t const jobSize = mtctx->inBuff.filled;
|
|
2062
1857
|
assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
|
|
2063
|
-
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
|
|
1858
|
+
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , "");
|
|
2064
1859
|
}
|
|
2065
1860
|
|
|
2066
1861
|
/* check for potential compressed data ready to be flushed */
|
|
@@ -2070,47 +1865,3 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
|
|
2070
1865
|
return remainingToFlush;
|
|
2071
1866
|
}
|
|
2072
1867
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
|
2076
|
-
{
|
|
2077
|
-
FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
|
|
2078
|
-
|
|
2079
|
-
/* recommended next input size : fill current input buffer */
|
|
2080
|
-
return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame)
|
|
2085
|
-
{
|
|
2086
|
-
size_t const srcSize = mtctx->inBuff.filled;
|
|
2087
|
-
DEBUGLOG(5, "ZSTDMT_flushStream_internal");
|
|
2088
|
-
|
|
2089
|
-
if ( mtctx->jobReady /* one job ready for a worker to pick up */
|
|
2090
|
-
|| (srcSize > 0) /* still some data within input buffer */
|
|
2091
|
-
|| ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
|
|
2092
|
-
DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
|
|
2093
|
-
(U32)srcSize, (U32)endFrame);
|
|
2094
|
-
FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
|
-
/* check if there is any data available to flush */
|
|
2098
|
-
return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame);
|
|
2099
|
-
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
|
|
2103
|
-
{
|
|
2104
|
-
DEBUGLOG(5, "ZSTDMT_flushStream");
|
|
2105
|
-
if (mtctx->singleBlockingThread)
|
|
2106
|
-
return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output);
|
|
2107
|
-
return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush);
|
|
2108
|
-
}
|
|
2109
|
-
|
|
2110
|
-
size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output)
|
|
2111
|
-
{
|
|
2112
|
-
DEBUGLOG(4, "ZSTDMT_endStream");
|
|
2113
|
-
if (mtctx->singleBlockingThread)
|
|
2114
|
-
return ZSTD_endStream(mtctx->cctxPool->cctx[0], output);
|
|
2115
|
-
return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end);
|
|
2116
|
-
}
|