zstd-ruby 1.3.8.0 → 1.4.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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -5
  3. data/README.md +1 -1
  4. data/ext/zstdruby/libzstd/Makefile +133 -61
  5. data/ext/zstdruby/libzstd/README.md +51 -18
  6. data/ext/zstdruby/libzstd/common/bitstream.h +38 -39
  7. data/ext/zstdruby/libzstd/common/compiler.h +41 -6
  8. data/ext/zstdruby/libzstd/common/cpu.h +1 -1
  9. data/ext/zstdruby/libzstd/common/debug.c +11 -31
  10. data/ext/zstdruby/libzstd/common/debug.h +11 -31
  11. data/ext/zstdruby/libzstd/common/entropy_common.c +13 -33
  12. data/ext/zstdruby/libzstd/common/error_private.c +2 -1
  13. data/ext/zstdruby/libzstd/common/error_private.h +6 -2
  14. data/ext/zstdruby/libzstd/common/fse.h +13 -33
  15. data/ext/zstdruby/libzstd/common/fse_decompress.c +12 -35
  16. data/ext/zstdruby/libzstd/common/huf.h +15 -33
  17. data/ext/zstdruby/libzstd/common/mem.h +75 -2
  18. data/ext/zstdruby/libzstd/common/pool.c +8 -4
  19. data/ext/zstdruby/libzstd/common/pool.h +2 -2
  20. data/ext/zstdruby/libzstd/common/threading.c +52 -6
  21. data/ext/zstdruby/libzstd/common/threading.h +36 -4
  22. data/ext/zstdruby/libzstd/common/xxhash.c +25 -37
  23. data/ext/zstdruby/libzstd/common/xxhash.h +11 -31
  24. data/ext/zstdruby/libzstd/common/zstd_common.c +1 -1
  25. data/ext/zstdruby/libzstd/common/zstd_errors.h +2 -1
  26. data/ext/zstdruby/libzstd/common/zstd_internal.h +203 -22
  27. data/ext/zstdruby/libzstd/compress/fse_compress.c +19 -42
  28. data/ext/zstdruby/libzstd/compress/hist.c +15 -35
  29. data/ext/zstdruby/libzstd/compress/hist.h +12 -32
  30. data/ext/zstdruby/libzstd/compress/huf_compress.c +92 -92
  31. data/ext/zstdruby/libzstd/compress/zstd_compress.c +1460 -1472
  32. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +330 -65
  33. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.c +158 -0
  34. data/ext/zstdruby/libzstd/compress/zstd_compress_literals.h +29 -0
  35. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.c +419 -0
  36. data/ext/zstdruby/libzstd/compress/zstd_compress_sequences.h +54 -0
  37. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +845 -0
  38. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.h +32 -0
  39. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +525 -0
  40. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +65 -43
  41. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +2 -2
  42. data/ext/zstdruby/libzstd/compress/zstd_fast.c +264 -159
  43. data/ext/zstdruby/libzstd/compress/zstd_fast.h +2 -2
  44. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +74 -42
  45. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +2 -2
  46. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +33 -11
  47. data/ext/zstdruby/libzstd/compress/zstd_ldm.h +7 -2
  48. data/ext/zstdruby/libzstd/compress/zstd_opt.c +108 -125
  49. data/ext/zstdruby/libzstd/compress/zstd_opt.h +1 -1
  50. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +129 -93
  51. data/ext/zstdruby/libzstd/compress/zstdmt_compress.h +46 -28
  52. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +76 -60
  53. data/ext/zstdruby/libzstd/decompress/zstd_ddict.c +14 -10
  54. data/ext/zstdruby/libzstd/decompress/zstd_ddict.h +2 -2
  55. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +471 -258
  56. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +471 -346
  57. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +3 -3
  58. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +25 -4
  59. data/ext/zstdruby/libzstd/deprecated/zbuff.h +9 -8
  60. data/ext/zstdruby/libzstd/deprecated/zbuff_common.c +2 -2
  61. data/ext/zstdruby/libzstd/deprecated/zbuff_compress.c +1 -1
  62. data/ext/zstdruby/libzstd/deprecated/zbuff_decompress.c +1 -1
  63. data/ext/zstdruby/libzstd/dictBuilder/cover.c +220 -65
  64. data/ext/zstdruby/libzstd/dictBuilder/cover.h +81 -7
  65. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +85 -56
  66. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +43 -19
  67. data/ext/zstdruby/libzstd/dictBuilder/zdict.h +73 -35
  68. data/ext/zstdruby/libzstd/dll/example/Makefile +2 -1
  69. data/ext/zstdruby/libzstd/dll/example/build_package.bat +3 -2
  70. data/ext/zstdruby/libzstd/legacy/zstd_legacy.h +49 -15
  71. data/ext/zstdruby/libzstd/legacy/zstd_v01.c +142 -117
  72. data/ext/zstdruby/libzstd/legacy/zstd_v01.h +13 -8
  73. data/ext/zstdruby/libzstd/legacy/zstd_v02.c +54 -25
  74. data/ext/zstdruby/libzstd/legacy/zstd_v02.h +13 -8
  75. data/ext/zstdruby/libzstd/legacy/zstd_v03.c +55 -25
  76. data/ext/zstdruby/libzstd/legacy/zstd_v03.h +13 -8
  77. data/ext/zstdruby/libzstd/legacy/zstd_v04.c +62 -29
  78. data/ext/zstdruby/libzstd/legacy/zstd_v04.h +13 -8
  79. data/ext/zstdruby/libzstd/legacy/zstd_v05.c +145 -109
  80. data/ext/zstdruby/libzstd/legacy/zstd_v05.h +14 -9
  81. data/ext/zstdruby/libzstd/legacy/zstd_v06.c +56 -26
  82. data/ext/zstdruby/libzstd/legacy/zstd_v06.h +11 -6
  83. data/ext/zstdruby/libzstd/legacy/zstd_v07.c +65 -28
  84. data/ext/zstdruby/libzstd/legacy/zstd_v07.h +11 -6
  85. data/ext/zstdruby/libzstd/libzstd.pc.in +3 -2
  86. data/ext/zstdruby/libzstd/zstd.h +921 -597
  87. data/lib/zstd-ruby/version.rb +1 -1
  88. data/zstd-ruby.gemspec +2 -2
  89. metadata +19 -14
  90. data/ext/zstdruby/libzstd/dll/libzstd.def +0 -87
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
2
+ * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under both the BSD-style license (found in the
@@ -22,8 +22,9 @@
22
22
  /* ====== Dependencies ====== */
23
23
  #include <string.h> /* memcpy, memset */
24
24
  #include <limits.h> /* INT_MAX, UINT_MAX */
25
- #include "pool.h" /* threadpool */
26
- #include "threading.h" /* mutex */
25
+ #include "../common/mem.h" /* MEM_STATIC */
26
+ #include "../common/pool.h" /* threadpool */
27
+ #include "../common/threading.h" /* mutex */
27
28
  #include "zstd_compress_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
28
29
  #include "zstd_ldm.h"
29
30
  #include "zstdmt_compress.h"
@@ -456,11 +457,17 @@ typedef struct {
456
457
  * Must be acquired after the main mutex when acquiring both.
457
458
  */
458
459
  ZSTD_pthread_mutex_t ldmWindowMutex;
459
- ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is udpated */
460
+ ZSTD_pthread_cond_t ldmWindowCond; /* Signaled when ldmWindow is updated */
460
461
  ZSTD_window_t ldmWindow; /* A thread-safe copy of ldmState.window */
461
462
  } serialState_t;
462
463
 
463
- static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool* seqPool, ZSTD_CCtx_params params, size_t jobSize)
464
+ static int
465
+ ZSTDMT_serialState_reset(serialState_t* serialState,
466
+ ZSTDMT_seqPool* seqPool,
467
+ ZSTD_CCtx_params params,
468
+ size_t jobSize,
469
+ const void* dict, size_t const dictSize,
470
+ ZSTD_dictContentType_e dictContentType)
464
471
  {
465
472
  /* Adjust parameters */
466
473
  if (params.ldmParams.enableLdm) {
@@ -489,8 +496,7 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool*
489
496
  /* Size the seq pool tables */
490
497
  ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
491
498
  /* Reset the window */
492
- ZSTD_window_clear(&serialState->ldmState.window);
493
- serialState->ldmWindow = serialState->ldmState.window;
499
+ ZSTD_window_init(&serialState->ldmState.window);
494
500
  /* Resize tables and output space if necessary. */
495
501
  if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {
496
502
  ZSTD_free(serialState->ldmState.hashTable, cMem);
@@ -505,7 +511,24 @@ static int ZSTDMT_serialState_reset(serialState_t* serialState, ZSTDMT_seqPool*
505
511
  /* Zero the tables */
506
512
  memset(serialState->ldmState.hashTable, 0, hashSize);
507
513
  memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
514
+
515
+ /* Update window state and fill hash table with dict */
516
+ serialState->ldmState.loadedDictEnd = 0;
517
+ if (dictSize > 0) {
518
+ if (dictContentType == ZSTD_dct_rawContent) {
519
+ BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
520
+ ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
521
+ ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, &params.ldmParams);
522
+ serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
523
+ } else {
524
+ /* don't even load anything */
525
+ }
526
+ }
527
+
528
+ /* Initialize serialState's copy of ldmWindow. */
529
+ serialState->ldmWindow = serialState->ldmState.window;
508
530
  }
531
+
509
532
  serialState->params = params;
510
533
  serialState->params.jobSize = (U32)jobSize;
511
534
  return 0;
@@ -647,7 +670,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
647
670
  buffer_t dstBuff = job->dstBuff;
648
671
  size_t lastCBlockSize = 0;
649
672
 
650
- /* ressources */
673
+ /* resources */
651
674
  if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));
652
675
  if (dstBuff.start == NULL) { /* streaming job : doesn't provide a dstBuffer */
653
676
  dstBuff = ZSTDMT_getBuffer(job->bufPool);
@@ -667,19 +690,19 @@ static void ZSTDMT_compressionJob(void* jobDescription)
667
690
 
668
691
  /* init */
669
692
  if (job->cdict) {
670
- size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, jobParams, job->fullFrameSize);
693
+ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize);
671
694
  assert(job->firstJob); /* only allowed for first job */
672
695
  if (ZSTD_isError(initError)) JOB_ERROR(initError);
673
696
  } else { /* srcStart points at reloaded section */
674
697
  U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;
675
- { size_t const forceWindowError = ZSTD_CCtxParam_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
698
+ { size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
676
699
  if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
677
700
  }
678
701
  { size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
679
702
  job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
680
703
  ZSTD_dtlm_fast,
681
704
  NULL, /*cdict*/
682
- jobParams, pledgedSrcSize);
705
+ &jobParams, pledgedSrcSize);
683
706
  if (ZSTD_isError(initError)) JOB_ERROR(initError);
684
707
  } }
685
708
 
@@ -864,14 +887,10 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {
864
887
  * Internal use only */
865
888
  size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)
866
889
  {
867
- if (nbWorkers > ZSTDMT_NBWORKERS_MAX) nbWorkers = ZSTDMT_NBWORKERS_MAX;
868
- params->nbWorkers = nbWorkers;
869
- params->overlapLog = ZSTDMT_OVERLAPLOG_DEFAULT;
870
- params->jobSize = 0;
871
- return nbWorkers;
890
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);
872
891
  }
873
892
 
874
- ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
893
+ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem)
875
894
  {
876
895
  ZSTDMT_CCtx* mtctx;
877
896
  U32 nbJobs = nbWorkers + 2;
@@ -906,6 +925,17 @@ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
906
925
  return mtctx;
907
926
  }
908
927
 
928
+ ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem)
929
+ {
930
+ #ifdef ZSTD_MULTITHREAD
931
+ return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem);
932
+ #else
933
+ (void)nbWorkers;
934
+ (void)cMem;
935
+ return NULL;
936
+ #endif
937
+ }
938
+
909
939
  ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers)
910
940
  {
911
941
  return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem);
@@ -919,12 +949,18 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)
919
949
  unsigned jobID;
920
950
  DEBUGLOG(3, "ZSTDMT_releaseAllJobResources");
921
951
  for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {
952
+ /* Copy the mutex/cond out */
953
+ ZSTD_pthread_mutex_t const mutex = mtctx->jobs[jobID].job_mutex;
954
+ ZSTD_pthread_cond_t const cond = mtctx->jobs[jobID].job_cond;
955
+
922
956
  DEBUGLOG(4, "job%02u: release dst address %08X", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);
923
957
  ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);
924
- mtctx->jobs[jobID].dstBuff = g_nullBuffer;
925
- mtctx->jobs[jobID].cSize = 0;
958
+
959
+ /* Clear the job description, but keep the mutex/cond */
960
+ memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));
961
+ mtctx->jobs[jobID].job_mutex = mutex;
962
+ mtctx->jobs[jobID].job_cond = cond;
926
963
  }
927
- memset(mtctx->jobs, 0, (mtctx->jobIDMask+1)*sizeof(ZSTDMT_jobDescription));
928
964
  mtctx->inBuff.buffer = g_nullBuffer;
929
965
  mtctx->inBuff.filled = 0;
930
966
  mtctx->allJobsCompleted = 1;
@@ -986,26 +1022,13 @@ ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params,
986
1022
  {
987
1023
  case ZSTDMT_p_jobSize :
988
1024
  DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value);
989
- if ( value != 0 /* default */
990
- && value < ZSTDMT_JOBSIZE_MIN)
991
- value = ZSTDMT_JOBSIZE_MIN;
992
- assert(value >= 0);
993
- if (value > ZSTDMT_JOBSIZE_MAX) value = ZSTDMT_JOBSIZE_MAX;
994
- params->jobSize = value;
995
- return value;
996
-
1025
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value);
997
1026
  case ZSTDMT_p_overlapLog :
998
1027
  DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value);
999
- if (value < ZSTD_OVERLAPLOG_MIN) value = ZSTD_OVERLAPLOG_MIN;
1000
- if (value > ZSTD_OVERLAPLOG_MAX) value = ZSTD_OVERLAPLOG_MAX;
1001
- params->overlapLog = value;
1002
- return value;
1003
-
1028
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value);
1004
1029
  case ZSTDMT_p_rsyncable :
1005
- value = (value != 0);
1006
- params->rsyncable = value;
1007
- return value;
1008
-
1030
+ DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value);
1031
+ return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value);
1009
1032
  default :
1010
1033
  return ERROR(parameter_unsupported);
1011
1034
  }
@@ -1021,32 +1044,29 @@ size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter,
1021
1044
  {
1022
1045
  switch (parameter) {
1023
1046
  case ZSTDMT_p_jobSize:
1024
- assert(mtctx->params.jobSize <= INT_MAX);
1025
- *value = (int)(mtctx->params.jobSize);
1026
- break;
1047
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value);
1027
1048
  case ZSTDMT_p_overlapLog:
1028
- *value = mtctx->params.overlapLog;
1029
- break;
1049
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value);
1030
1050
  case ZSTDMT_p_rsyncable:
1031
- *value = mtctx->params.rsyncable;
1032
- break;
1051
+ return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value);
1033
1052
  default:
1034
1053
  return ERROR(parameter_unsupported);
1035
1054
  }
1036
- return 0;
1037
1055
  }
1038
1056
 
1039
1057
  /* Sets parameters relevant to the compression job,
1040
1058
  * initializing others to default values. */
1041
- static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
1042
- {
1043
- ZSTD_CCtx_params jobParams;
1044
- memset(&jobParams, 0, sizeof(jobParams));
1045
-
1046
- jobParams.cParams = params.cParams;
1047
- jobParams.fParams = params.fParams;
1048
- jobParams.compressionLevel = params.compressionLevel;
1049
-
1059
+ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params)
1060
+ {
1061
+ ZSTD_CCtx_params jobParams = *params;
1062
+ /* Clear parameters related to multithreading */
1063
+ jobParams.forceWindow = 0;
1064
+ jobParams.nbWorkers = 0;
1065
+ jobParams.jobSize = 0;
1066
+ jobParams.overlapLog = 0;
1067
+ jobParams.rsyncable = 0;
1068
+ memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t));
1069
+ memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem));
1050
1070
  return jobParams;
1051
1071
  }
1052
1072
 
@@ -1056,7 +1076,7 @@ static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(ZSTD_CCtx_params const params)
1056
1076
  static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
1057
1077
  {
1058
1078
  if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
1059
- CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbWorkers) );
1079
+ FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , "");
1060
1080
  mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
1061
1081
  if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
1062
1082
  mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
@@ -1078,7 +1098,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p
1078
1098
  DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)",
1079
1099
  compressionLevel);
1080
1100
  mtctx->params.compressionLevel = compressionLevel;
1081
- { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, 0, 0);
1101
+ { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0);
1082
1102
  cParams.windowLog = saved_wlog;
1083
1103
  mtctx->params.cParams = cParams;
1084
1104
  }
@@ -1137,9 +1157,14 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
1137
1157
  size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;
1138
1158
  size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;
1139
1159
  assert(flushed <= produced);
1160
+ assert(jobPtr->consumed <= jobPtr->src.size);
1140
1161
  toFlush = produced - flushed;
1141
- if (toFlush==0 && (jobPtr->consumed >= jobPtr->src.size)) {
1142
- /* doneJobID is not-fully-flushed, but toFlush==0 : doneJobID should be compressing some more data */
1162
+ /* if toFlush==0, nothing is available to flush.
1163
+ * However, jobID is expected to still be active:
1164
+ * if jobID was already completed and fully flushed,
1165
+ * ZSTDMT_flushProduced() should have already moved onto next job.
1166
+ * Therefore, some input has not yet been consumed. */
1167
+ if (toFlush==0) {
1143
1168
  assert(jobPtr->consumed < jobPtr->src.size);
1144
1169
  }
1145
1170
  }
@@ -1154,14 +1179,18 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
1154
1179
  /* ===== Multi-threaded compression ===== */
1155
1180
  /* ------------------------------------------ */
1156
1181
 
1157
- static unsigned ZSTDMT_computeTargetJobLog(ZSTD_CCtx_params const params)
1182
+ static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)
1158
1183
  {
1159
- if (params.ldmParams.enableLdm)
1184
+ unsigned jobLog;
1185
+ if (params->ldmParams.enableLdm) {
1160
1186
  /* In Long Range Mode, the windowLog is typically oversized.
1161
1187
  * In which case, it's preferable to determine the jobSize
1162
1188
  * based on chainLog instead. */
1163
- return MAX(21, params.cParams.chainLog + 4);
1164
- return MAX(20, params.cParams.windowLog + 2);
1189
+ jobLog = MAX(21, params->cParams.chainLog + 4);
1190
+ } else {
1191
+ jobLog = MAX(20, params->cParams.windowLog + 2);
1192
+ }
1193
+ return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX);
1165
1194
  }
1166
1195
 
1167
1196
  static int ZSTDMT_overlapLog_default(ZSTD_strategy strat)
@@ -1192,27 +1221,27 @@ static int ZSTDMT_overlapLog(int ovlog, ZSTD_strategy strat)
1192
1221
  return ovlog;
1193
1222
  }
1194
1223
 
1195
- static size_t ZSTDMT_computeOverlapSize(ZSTD_CCtx_params const params)
1224
+ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
1196
1225
  {
1197
- int const overlapRLog = 9 - ZSTDMT_overlapLog(params.overlapLog, params.cParams.strategy);
1198
- int ovLog = (overlapRLog >= 8) ? 0 : (params.cParams.windowLog - overlapRLog);
1226
+ int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);
1227
+ int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);
1199
1228
  assert(0 <= overlapRLog && overlapRLog <= 8);
1200
- if (params.ldmParams.enableLdm) {
1229
+ if (params->ldmParams.enableLdm) {
1201
1230
  /* In Long Range Mode, the windowLog is typically oversized.
1202
1231
  * In which case, it's preferable to determine the jobSize
1203
1232
  * based on chainLog instead.
1204
1233
  * Then, ovLog becomes a fraction of the jobSize, rather than windowSize */
1205
- ovLog = MIN(params.cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)
1234
+ ovLog = MIN(params->cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)
1206
1235
  - overlapRLog;
1207
1236
  }
1208
- assert(0 <= ovLog && ovLog <= 30);
1209
- DEBUGLOG(4, "overlapLog : %i", params.overlapLog);
1237
+ assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX);
1238
+ DEBUGLOG(4, "overlapLog : %i", params->overlapLog);
1210
1239
  DEBUGLOG(4, "overlap size : %i", 1 << ovLog);
1211
1240
  return (ovLog==0) ? 0 : (size_t)1 << ovLog;
1212
1241
  }
1213
1242
 
1214
1243
  static unsigned
1215
- ZSTDMT_computeNbJobs(ZSTD_CCtx_params params, size_t srcSize, unsigned nbWorkers)
1244
+ ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers)
1216
1245
  {
1217
1246
  assert(nbWorkers>0);
1218
1247
  { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params);
@@ -1228,16 +1257,17 @@ ZSTDMT_computeNbJobs(ZSTD_CCtx_params params, size_t srcSize, unsigned nbWorkers
1228
1257
  /* ZSTDMT_compress_advanced_internal() :
1229
1258
  * This is a blocking function : it will only give back control to caller after finishing its compression job.
1230
1259
  */
1231
- static size_t ZSTDMT_compress_advanced_internal(
1260
+ static size_t
1261
+ ZSTDMT_compress_advanced_internal(
1232
1262
  ZSTDMT_CCtx* mtctx,
1233
1263
  void* dst, size_t dstCapacity,
1234
1264
  const void* src, size_t srcSize,
1235
1265
  const ZSTD_CDict* cdict,
1236
1266
  ZSTD_CCtx_params params)
1237
1267
  {
1238
- ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(params);
1239
- size_t const overlapSize = ZSTDMT_computeOverlapSize(params);
1240
- unsigned const nbJobs = ZSTDMT_computeNbJobs(params, srcSize, params.nbWorkers);
1268
+ ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(&params);
1269
+ size_t const overlapSize = ZSTDMT_computeOverlapSize(&params);
1270
+ unsigned const nbJobs = ZSTDMT_computeNbJobs(&params, srcSize, params.nbWorkers);
1241
1271
  size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs;
1242
1272
  size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */
1243
1273
  const char* const srcStart = (const char*)src;
@@ -1255,15 +1285,16 @@ static size_t ZSTDMT_compress_advanced_internal(
1255
1285
  ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0];
1256
1286
  DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode");
1257
1287
  if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams);
1258
- return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, jobParams);
1288
+ return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams);
1259
1289
  }
1260
1290
 
1261
1291
  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) */
1262
1292
  ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) );
1263
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize))
1293
+ /* LDM doesn't even try to load the dictionary in single-ingestion mode */
1294
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto))
1264
1295
  return ERROR(memory_allocation);
1265
1296
 
1266
- CHECK_F( ZSTDMT_expandJobsTable(mtctx, nbJobs) ); /* only expands if necessary */
1297
+ FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */
1267
1298
 
1268
1299
  { unsigned u;
1269
1300
  for (u=0; u<nbJobs; u++) {
@@ -1396,19 +1427,19 @@ size_t ZSTDMT_initCStream_internal(
1396
1427
 
1397
1428
  /* init */
1398
1429
  if (params.nbWorkers != mtctx->params.nbWorkers)
1399
- CHECK_F( ZSTDMT_resize(mtctx, params.nbWorkers) );
1430
+ FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, params.nbWorkers) , "");
1400
1431
 
1401
1432
  if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;
1402
- if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = ZSTDMT_JOBSIZE_MAX;
1433
+ if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;
1403
1434
 
1404
1435
  mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */
1405
1436
  if (mtctx->singleBlockingThread) {
1406
- ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(params);
1437
+ ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(&params);
1407
1438
  DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode");
1408
1439
  assert(singleThreadParams.nbWorkers == 0);
1409
1440
  return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0],
1410
1441
  dict, dictSize, cdict,
1411
- singleThreadParams, pledgedSrcSize);
1442
+ &singleThreadParams, pledgedSrcSize);
1412
1443
  }
1413
1444
 
1414
1445
  DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers);
@@ -1434,12 +1465,14 @@ size_t ZSTDMT_initCStream_internal(
1434
1465
  mtctx->cdict = cdict;
1435
1466
  }
1436
1467
 
1437
- mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(params);
1468
+ mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(&params);
1438
1469
  DEBUGLOG(4, "overlapLog=%i => %u KB", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10));
1439
1470
  mtctx->targetSectionSize = params.jobSize;
1440
1471
  if (mtctx->targetSectionSize == 0) {
1441
- mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(params);
1472
+ mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(&params);
1442
1473
  }
1474
+ assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX);
1475
+
1443
1476
  if (params.rsyncable) {
1444
1477
  /* Aim for the targetsectionSize as the average job size. */
1445
1478
  U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
@@ -1491,7 +1524,8 @@ size_t ZSTDMT_initCStream_internal(
1491
1524
  mtctx->allJobsCompleted = 0;
1492
1525
  mtctx->consumed = 0;
1493
1526
  mtctx->produced = 0;
1494
- if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize))
1527
+ if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize,
1528
+ dict, dictSize, dictContentType))
1495
1529
  return ERROR(memory_allocation);
1496
1530
  return 0;
1497
1531
  }
@@ -1547,7 +1581,7 @@ size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) {
1547
1581
  /* ZSTDMT_writeLastEmptyBlock()
1548
1582
  * Write a single empty block with an end-of-frame to finish a frame.
1549
1583
  * Job must be created from streaming variant.
1550
- * This function is always successfull if expected conditions are fulfilled.
1584
+ * This function is always successful if expected conditions are fulfilled.
1551
1585
  */
1552
1586
  static void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)
1553
1587
  {
@@ -1705,9 +1739,11 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u
1705
1739
  assert(mtctx->doneJobID < mtctx->nextJobID);
1706
1740
  assert(cSize >= mtctx->jobs[wJobID].dstFlushed);
1707
1741
  assert(mtctx->jobs[wJobID].dstBuff.start != NULL);
1708
- memcpy((char*)output->dst + output->pos,
1709
- (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
1710
- toFlush);
1742
+ if (toFlush > 0) {
1743
+ memcpy((char*)output->dst + output->pos,
1744
+ (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,
1745
+ toFlush);
1746
+ }
1711
1747
  output->pos += toFlush;
1712
1748
  mtctx->jobs[wJobID].dstFlushed += toFlush; /* can write : this value is only used by mtctx */
1713
1749
 
@@ -1777,7 +1813,7 @@ static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
1777
1813
  BYTE const* const bufferStart = (BYTE const*)buffer.start;
1778
1814
  BYTE const* const bufferEnd = bufferStart + buffer.capacity;
1779
1815
  BYTE const* const rangeStart = (BYTE const*)range.start;
1780
- BYTE const* const rangeEnd = rangeStart + range.size;
1816
+ BYTE const* const rangeEnd = range.size != 0 ? rangeStart + range.size : rangeStart;
1781
1817
 
1782
1818
  if (rangeStart == NULL || bufferStart == NULL)
1783
1819
  return 0;
@@ -1987,7 +2023,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
1987
2023
  assert(input->pos <= input->size);
1988
2024
 
1989
2025
  if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */
1990
- return ZSTD_compressStream_generic(mtctx->cctxPool->cctx[0], output, input, endOp);
2026
+ return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp);
1991
2027
  }
1992
2028
 
1993
2029
  if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {
@@ -2051,7 +2087,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
2051
2087
  || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) { /* must finish the frame with a zero-size block */
2052
2088
  size_t const jobSize = mtctx->inBuff.filled;
2053
2089
  assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);
2054
- CHECK_F( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) );
2090
+ FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , "");
2055
2091
  }
2056
2092
 
2057
2093
  /* check for potential compressed data ready to be flushed */
@@ -2065,7 +2101,7 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
2065
2101
 
2066
2102
  size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
2067
2103
  {
2068
- CHECK_F( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) );
2104
+ FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , "");
2069
2105
 
2070
2106
  /* recommended next input size : fill current input buffer */
2071
2107
  return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
@@ -2082,7 +2118,7 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* ou
2082
2118
  || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */
2083
2119
  DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)",
2084
2120
  (U32)srcSize, (U32)endFrame);
2085
- CHECK_F( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) );
2121
+ FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , "");
2086
2122
  }
2087
2123
 
2088
2124
  /* check if there is any data available to flush */