diff --git a/programs/fileio.c b/programs/fileio.c index 4af2c0942..6ce4c32ab 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -329,6 +329,10 @@ int FIO_rust_checkFilenameCollisions(const char** filenameTable, unsigned nbFile unsigned FIO_rust_highbit64(unsigned long long v); unsigned long long FIO_rust_getLargestFileSize(const char** inFileNames, unsigned nbFiles); unsigned FIO_rust_cycleLog(unsigned hashLog, int strategy); +void FIO_rust_patchFromWindowPolicy(unsigned fileWindowLog, + unsigned cycleLog, + unsigned* windowLog, + int* enableLdm); void FIO_rust_setInBuffer(ZSTD_inBuffer* output, const void* buf, size_t s, size_t pos); void FIO_rust_setOutBuffer(ZSTD_outBuffer* output, void* buf, size_t s, size_t pos); const char* FIO_rust_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix); @@ -877,11 +881,17 @@ static void FIO_adjustParamsForPatchFromMode(FIO_prefs_t* const prefs, { unsigned const fileWindowLog = FIO_highbit64(maxSrcFileSize) + 1; ZSTD_compressionParameters const cParams = ZSTD_getCParams(cLevel, (size_t)maxSrcFileSize, (size_t)dictSize); + unsigned windowLog; + int enableLdm; FIO_adjustMemLimitForPatchFromMode(prefs, dictSize, maxSrcFileSize); + FIO_rust_patchFromWindowPolicy(fileWindowLog, + ZSTD_cycleLog(cParams.chainLog, cParams.strategy), + &windowLog, + &enableLdm); if (fileWindowLog > ZSTD_WINDOWLOG_MAX) DISPLAYLEVEL(1, "Max window log exceeded by file (compression ratio will suffer)\n"); - comprParams->windowLog = MAX(ZSTD_WINDOWLOG_MIN, MIN(ZSTD_WINDOWLOG_MAX, fileWindowLog)); - if (fileWindowLog > ZSTD_cycleLog(cParams.chainLog, cParams.strategy)) { + comprParams->windowLog = windowLog; + if (enableLdm) { if (!prefs->ldmFlag) DISPLAYLEVEL(2, "long mode automatically triggered\n"); FIO_setLdmFlag(prefs, 1); diff --git a/rust/src/fileio_prefs.rs b/rust/src/fileio_prefs.rs index 101db5fba..42ca020e3 100644 --- a/rust/src/fileio_prefs.rs +++ b/rust/src/fileio_prefs.rs @@ -29,6 +29,7 @@ const FIO_MULTI_FILES_ACTION_DISABLE_REMOVE: c_int = 3; const FIO_MULTI_FILES_ACTION_QUIET_ABORT: c_int = 4; const FIO_MULTI_FILES_ACTION_CONFIRM: c_int = 5; const UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX; +const ZSTD_WINDOWLOG_MIN: u32 = 10; const ZSTD_WINDOWLOG_MAX: u32 = if size_of::() == 4 { 30 } else { 31 }; const ZSTD_BTLAZY2: c_int = 6; static STDOUT_MARK: &[u8] = b"/*stdout*\\\0"; @@ -609,6 +610,20 @@ pub extern "C" fn FIO_rust_cycleLog(hash_log: c_uint, strategy: c_int) -> c_uint cycle_log(hash_log, strategy) } +/// Rust scalar ABI for patch-from window and automatic-LDM policy. +#[no_mangle] +pub unsafe extern "C" fn FIO_rust_patchFromWindowPolicy( + file_window_log: c_uint, + cycle_log: c_uint, + window_log: *mut c_uint, + enable_ldm: *mut c_int, +) { + unsafe { + window_log.write(file_window_log.clamp(ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX)); + enable_ldm.write(c_int::from(file_window_log > cycle_log)); + } +} + #[allow(clippy::too_many_arguments)] #[inline] fn multi_files_concat_action( @@ -1179,6 +1194,54 @@ mod tests { assert_eq!(FIO_rust_cycleLog(20, ZSTD_BTLAZY2 + 3), 19); } + fn patch_from_window_policy(file_window_log: c_uint, cycle_log: c_uint) -> (c_uint, c_int) { + let mut window_log = c_uint::MAX; + let mut enable_ldm = -1; + unsafe { + FIO_rust_patchFromWindowPolicy( + file_window_log, + cycle_log, + &mut window_log, + &mut enable_ldm, + ); + } + (window_log, enable_ldm) + } + + #[test] + fn patch_from_window_policy_clamps_to_lower_bound() { + assert_eq!( + patch_from_window_policy(ZSTD_WINDOWLOG_MIN - 1, ZSTD_WINDOWLOG_MIN), + (ZSTD_WINDOWLOG_MIN, 0) + ); + } + + #[test] + fn patch_from_window_policy_clamps_to_upper_bound() { + assert_eq!( + patch_from_window_policy(ZSTD_WINDOWLOG_MAX + 1, ZSTD_WINDOWLOG_MAX + 1), + (ZSTD_WINDOWLOG_MAX, 0) + ); + } + + #[test] + fn patch_from_window_policy_keeps_equal_cycle_log_out_of_ldm() { + assert_eq!(patch_from_window_policy(20, 20), (20, 0)); + } + + #[test] + fn patch_from_window_policy_enables_ldm_one_above_cycle_log() { + assert_eq!(patch_from_window_policy(20, 19), (20, 1)); + } + + #[test] + fn patch_from_window_policy_uses_raw_value_above_upper_bound_for_ldm() { + assert_eq!( + patch_from_window_policy(ZSTD_WINDOWLOG_MAX + 1, ZSTD_WINDOWLOG_MAX), + (ZSTD_WINDOWLOG_MAX, 1) + ); + } + #[test] fn multi_files_concat_policy_protects_stdout_and_test_mode_removal() { assert_eq!(