zstd-ruby 1.3.8.0 → 1.4.5.0

Sign up to get free protection for your applications and to get access to all the features.
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 */