diff --git a/programs/fileio.c b/programs/fileio.c index c21070ee8..27bc17920 100644 --- a/programs/fileio.c +++ b/programs/fileio.c @@ -2063,11 +2063,29 @@ typedef size_t (*FIO_rust_createCResources_set_parameter_f)(void* context, int value); typedef int (*FIO_rust_createCResources_is_error_f)(size_t result); typedef void (*FIO_rust_createCResources_display_overlap_f)(int overlapLog); +typedef void (*FIO_rust_createCResources_create_cctx_f)(void* context); +typedef void (*FIO_rust_createCResources_prepare_dictionary_f)( + void* context, const FIO_prefs_t* prefs, const char* dictFileName, + U64 maxSrcFileSize, int cLevel, void* comprParams); +typedef void (*FIO_rust_createCResources_create_pool_f)( + void* context, const FIO_prefs_t* prefs); +typedef void (*FIO_rust_createCResources_validate_dictionary_f)(void* context); +typedef size_t (*FIO_rust_createCResources_load_dictionary_f)( + void* context, int patchFromMode); typedef struct { void* callbackContext; const FIO_prefs_t* prefs; ZSTD_compressionParameters comprParams; int cLevel; + const char* dictFileName; + U64 maxSrcFileSize; + int multithreaded; + FIO_rust_createCResources_create_cctx_f createCctx; + FIO_rust_createCResources_prepare_dictionary_f prepareDictionary; + FIO_rust_createCResources_create_pool_f createWritePool; + FIO_rust_createCResources_create_pool_f createReadPool; + FIO_rust_createCResources_validate_dictionary_f validateDictionary; + FIO_rust_createCResources_load_dictionary_f loadDictionary; FIO_rust_createCResources_set_parameter_f setParameter; FIO_rust_createCResources_is_error_f isError; FIO_rust_createCResources_display_overlap_f displayOverlap; @@ -2081,10 +2099,21 @@ typedef char FIO_rust_create_c_resources_state_params_offset[ typedef char FIO_rust_create_c_resources_state_level_offset[ (offsetof(FIO_rust_createCResourcesState, cLevel) == 2 * sizeof(void*) + sizeof(ZSTD_compressionParameters)) ? 1 : -1]; -typedef char FIO_rust_create_c_resources_state_set_parameter_offset[ - (offsetof(FIO_rust_createCResourcesState, setParameter) +typedef char FIO_rust_create_c_resources_state_dict_name_offset[ + (offsetof(FIO_rust_createCResourcesState, dictFileName) == ((2 * sizeof(void*) + sizeof(ZSTD_compressionParameters) + sizeof(int) + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*)) ? 1 : -1]; +typedef char FIO_rust_create_c_resources_state_max_src_offset[ + (offsetof(FIO_rust_createCResourcesState, maxSrcFileSize) + == offsetof(FIO_rust_createCResourcesState, dictFileName) + sizeof(void*)) ? 1 : -1]; +typedef char FIO_rust_create_c_resources_state_mt_offset[ + (offsetof(FIO_rust_createCResourcesState, multithreaded) + == offsetof(FIO_rust_createCResourcesState, maxSrcFileSize) + sizeof(U64)) ? 1 : -1]; +typedef char FIO_rust_create_c_resources_state_set_parameter_offset[ + (offsetof(FIO_rust_createCResourcesState, setParameter) + == ((offsetof(FIO_rust_createCResourcesState, multithreaded) + sizeof(int) + + sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*) + + 6 * sizeof(void*)) ? 1 : -1]; typedef char FIO_rust_create_c_resources_state_is_error_offset[ (offsetof(FIO_rust_createCResourcesState, isError) == offsetof(FIO_rust_createCResourcesState, setParameter) + sizeof(void*)) ? 1 : -1]; @@ -2093,14 +2122,17 @@ typedef char FIO_rust_create_c_resources_state_display_overlap_offset[ == offsetof(FIO_rust_createCResourcesState, isError) + sizeof(void*)) ? 1 : -1]; typedef char FIO_rust_create_c_resources_state_size[ (sizeof(FIO_rust_createCResourcesState) - == offsetof(FIO_rust_createCResourcesState, setParameter) + 3 * sizeof(void*)) ? 1 : -1]; + == offsetof(FIO_rust_createCResourcesState, displayOverlap) + sizeof(void*)) ? 1 : -1]; size_t FIO_rust_createCResources(const FIO_rust_createCResourcesState* state); static size_t FIO_rust_createCResources_setParameter(void* context, int parameter, int value) { - return ZSTD_CCtx_setParameter((ZSTD_CCtx*)context, (ZSTD_cParameter)parameter, value); + cRess_t* const ress = (cRess_t*)context; + if (parameter == ZSTD_c_nbWorkers) + DISPLAYLEVEL(5, "set nb workers = %u \n", (unsigned)value); + return ZSTD_CCtx_setParameter(ress->cctx, (ZSTD_cParameter)parameter, value); } static int FIO_rust_createCResources_isError(size_t result) @@ -2113,67 +2145,107 @@ static void FIO_rust_createCResources_displayOverlap(int overlapLog) DISPLAYLEVEL(3,"set overlapLog = %u \n", overlapLog); } -size_t FIO_rust_setCResourcesMtParameters(const FIO_rust_createCResourcesState* state); +static void FIO_rust_createCResources_createCctx(void* context) +{ + cRess_t* const ress = (cRess_t*)context; + ress->cctx = ZSTD_createCCtx(); + if (ress->cctx == NULL) + EXM_THROW(30, "allocation error (%s): can't create ZSTD_CCtx", + strerror(errno)); +} + +static void FIO_rust_createCResources_prepareDictionary( + void* context, const FIO_prefs_t* prefs, const char* dictFileName, + U64 maxSrcFileSize, int cLevel, void* comprParams) +{ + cRess_t* const ress = (cRess_t*)context; + ZSTD_compressionParameters* const params = + (ZSTD_compressionParameters*)comprParams; + unsigned long long dictSize = 0; + unsigned long long ssSize = 0; + FIO_dictBufferType_t dictBufferType; + + FIO_getDictFileStat(dictFileName, &ress->dictFileStat); + + /* need to update memLimit before calling createDictBuffer + * because of memLimit check inside it */ + if (prefs->patchFromMode) { + dictSize = (unsigned long long)UTIL_getFileSizeStat(&ress->dictFileStat); + ssSize = (unsigned long long)prefs->streamSrcSize; + FIO_adjustParamsForPatchFromMode( + (FIO_prefs_t*)prefs, params, dictSize, + ssSize > 0 ? ssSize : maxSrcFileSize, cLevel); + } + + dictBufferType = (FIO_dictBufferType_t)FIO_rust_selectDictBufferType( + prefs->mmapDict, prefs->patchFromMode, dictSize, prefs->memLimit); + FIO_initDict(&ress->dict, dictFileName, (FIO_prefs_t*)prefs, + &ress->dictFileStat, dictBufferType); + ress->dictFileName = dictFileName; +} + +static void FIO_rust_createCResources_createWritePool( + void* context, const FIO_prefs_t* prefs) +{ + cRess_t* const ress = (cRess_t*)context; + ress->writeCtx = AIO_WritePool_create(prefs, ZSTD_CStreamOutSize()); +} + +static void FIO_rust_createCResources_createReadPool( + void* context, const FIO_prefs_t* prefs) +{ + cRess_t* const ress = (cRess_t*)context; + ress->readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize()); +} + +static void FIO_rust_createCResources_validateDictionary(void* context) +{ + cRess_t* const ress = (cRess_t*)context; + if (ress->dictFileName && (ress->dict.dictBuffer == NULL)) + EXM_THROW(32, "allocation error : can't create dictBuffer"); +} + +static size_t FIO_rust_createCResources_loadDictionary( + void* context, int patchFromMode) +{ + cRess_t* const ress = (cRess_t*)context; + if (patchFromMode) + return ZSTD_CCtx_refPrefix( + ress->cctx, ress->dict.dictBuffer, ress->dict.dictBufferSize); + return ZSTD_CCtx_loadDictionary_byReference( + ress->cctx, ress->dict.dictBuffer, ress->dict.dictBufferSize); +} static cRess_t FIO_createCResources(FIO_prefs_t* const prefs, const char* dictFileName, unsigned long long const maxSrcFileSize, int cLevel, ZSTD_compressionParameters comprParams) { - unsigned long long dictSize = 0; - unsigned long long ssSize = 0; - FIO_dictBufferType_t dictBufferType; cRess_t ress; FIO_rust_createCResourcesState policy; memset(&ress, 0, sizeof(ress)); DISPLAYLEVEL(6, "FIO_createCResources \n"); - ress.cctx = ZSTD_createCCtx(); - if (ress.cctx == NULL) - EXM_THROW(30, "allocation error (%s): can't create ZSTD_CCtx", - strerror(errno)); - - FIO_getDictFileStat(dictFileName, &ress.dictFileStat); - - /* need to update memLimit before calling createDictBuffer - * because of memLimit check inside it */ - if (prefs->patchFromMode) { - dictSize = (unsigned long long)UTIL_getFileSizeStat(&ress.dictFileStat); - ssSize = (unsigned long long)prefs->streamSrcSize; - FIO_adjustParamsForPatchFromMode(prefs, &comprParams, dictSize, ssSize > 0 ? ssSize : maxSrcFileSize, cLevel); - } - - dictBufferType = (FIO_dictBufferType_t)FIO_rust_selectDictBufferType( - prefs->mmapDict, prefs->patchFromMode, dictSize, prefs->memLimit); - FIO_initDict(&ress.dict, dictFileName, prefs, &ress.dictFileStat, dictBufferType); /* works with dictFileName==NULL */ - - ress.writeCtx = AIO_WritePool_create(prefs, ZSTD_CStreamOutSize()); - ress.readCtx = AIO_ReadPool_create(prefs, ZSTD_CStreamInSize()); - - /* Advanced parameters, including dictionary */ - if (dictFileName && (ress.dict.dictBuffer==NULL)) - EXM_THROW(32, "allocation error : can't create dictBuffer"); - ress.dictFileName = dictFileName; - - policy.callbackContext = ress.cctx; + policy.callbackContext = &ress; policy.prefs = prefs; policy.comprParams = comprParams; policy.cLevel = cLevel; + policy.dictFileName = dictFileName; + policy.maxSrcFileSize = maxSrcFileSize; +#ifdef ZSTD_MULTITHREAD + policy.multithreaded = 1; +#else + policy.multithreaded = 0; +#endif + policy.createCctx = FIO_rust_createCResources_createCctx; + policy.prepareDictionary = FIO_rust_createCResources_prepareDictionary; + policy.createWritePool = FIO_rust_createCResources_createWritePool; + policy.createReadPool = FIO_rust_createCResources_createReadPool; + policy.validateDictionary = FIO_rust_createCResources_validateDictionary; + policy.loadDictionary = FIO_rust_createCResources_loadDictionary; policy.setParameter = FIO_rust_createCResources_setParameter; policy.isError = FIO_rust_createCResources_isError; policy.displayOverlap = FIO_rust_createCResources_displayOverlap; CHECK( FIO_rust_createCResources(&policy) ); - /* multi-threading */ -#ifdef ZSTD_MULTITHREAD - DISPLAYLEVEL(5,"set nb workers = %u \n", prefs->nbWorkers); - CHECK( FIO_rust_setCResourcesMtParameters(&policy) ); -#endif - /* dictionary */ - if (prefs->patchFromMode) { - CHECK( ZSTD_CCtx_refPrefix(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) ); - } else { - CHECK( ZSTD_CCtx_loadDictionary_byReference(ress.cctx, ress.dict.dictBuffer, ress.dict.dictBufferSize) ); - } - return ress; } diff --git a/rust/src/fileio_prefs.rs b/rust/src/fileio_prefs.rs index c6f878452..ae5926f7c 100644 --- a/rust/src/fileio_prefs.rs +++ b/rust/src/fileio_prefs.rs @@ -288,20 +288,14 @@ pub struct FIO_rust_freeCResourcesState { const _: () = { assert!(offset_of!(FIO_rust_freeCResourcesState, callback_context) == 0); assert!(offset_of!(FIO_rust_freeCResourcesState, free_dict) == size_of::()); - assert!( - offset_of!(FIO_rust_freeCResourcesState, free_write_pool) == 2 * size_of::() - ); - assert!( - offset_of!(FIO_rust_freeCResourcesState, free_read_pool) == 3 * size_of::() - ); + assert!(offset_of!(FIO_rust_freeCResourcesState, free_write_pool) == 2 * size_of::()); + assert!(offset_of!(FIO_rust_freeCResourcesState, free_read_pool) == 3 * size_of::()); assert!(offset_of!(FIO_rust_freeCResourcesState, free_cctx) == 4 * size_of::()); assert!(size_of::() == 5 * size_of::()); }; #[no_mangle] -pub unsafe extern "C" fn FIO_rust_freeCResources( - state: *const FIO_rust_freeCResourcesState, -) { +pub unsafe extern "C" fn FIO_rust_freeCResources(state: *const FIO_rust_freeCResourcesState) { if state.is_null() { return; } @@ -439,15 +433,14 @@ fn ceil_log2_window_size(window_size: u64) -> c_uint { if window_size == 0 { return 0; } - highbit64(window_size) - + c_uint::from((window_size & window_size.wrapping_sub(1)) != 0) + highbit64(window_size) + c_uint::from((window_size & window_size.wrapping_sub(1)) != 0) } #[cfg(feature = "decompression")] const _: () = { let callback_offset = (offset_of!(FIO_rust_zstdErrorHelpState, error_code) + size_of::()) - .div_ceil(size_of::()) + .div_ceil(size_of::()) * size_of::(); assert!(offset_of!(FIO_rust_zstdErrorHelpState, callback_context) == 0); assert!(offset_of!(FIO_rust_zstdErrorHelpState, src_file_name) == size_of::()); @@ -537,68 +530,105 @@ pub type FIO_createCResourcesSetParameterFn = unsafe extern "C" fn(*mut c_void, c_int, c_int) -> usize; pub type FIO_createCResourcesIsErrorFn = unsafe extern "C" fn(usize) -> c_int; pub type FIO_createCResourcesDisplayOverlapFn = unsafe extern "C" fn(c_int); +pub type FIO_createCResourcesCreateCctxFn = unsafe extern "C" fn(*mut c_void); +pub type FIO_createCResourcesPrepareDictionaryFn = + unsafe extern "C" fn(*mut c_void, *const FIO_prefs_t, *const c_char, u64, c_int, *mut c_void); +pub type FIO_createCResourcesCreatePoolFn = unsafe extern "C" fn(*mut c_void, *const FIO_prefs_t); +pub type FIO_createCResourcesValidateDictionaryFn = unsafe extern "C" fn(*mut c_void); +pub type FIO_createCResourcesLoadDictionaryFn = unsafe extern "C" fn(*mut c_void, c_int) -> usize; -/// C-owned compression-resource parameter policy projection. +/// Compression-resource initialization projection. /// -/// Rust owns the ordered, short-circuiting parameter policy. C keeps the -/// `ZSTD_CCtx` layout private and exposes parameter/diagnostic callbacks; -/// resource allocation, dictionary/pool setup, and dictionary loading remain -/// in C. +/// Rust owns the resource lifecycle and parameter order. C keeps the +/// `cRess_t`, `ZSTD_CCtx`, dictionary, and asynchronous-pool layouts private +/// behind callbacks which retain the original diagnostics and side effects. #[repr(C)] +#[derive(Clone, Copy)] pub struct FIO_rust_createCResourcesState { callback_context: *mut c_void, prefs: *const FIO_prefs_t, compression_params: FIO_compressionParameters, compression_level: c_int, + dict_file_name: *const c_char, + max_src_file_size: u64, + multithreaded: c_int, + create_cctx: FIO_createCResourcesCreateCctxFn, + prepare_dictionary: FIO_createCResourcesPrepareDictionaryFn, + create_write_pool: FIO_createCResourcesCreatePoolFn, + create_read_pool: FIO_createCResourcesCreatePoolFn, + validate_dictionary: FIO_createCResourcesValidateDictionaryFn, + load_dictionary: FIO_createCResourcesLoadDictionaryFn, set_parameter: FIO_createCResourcesSetParameterFn, is_error: FIO_createCResourcesIsErrorFn, display_overlap: FIO_createCResourcesDisplayOverlapFn, } const _: () = { - let callback_offset = (2 * size_of::() - + size_of::() - + size_of::()) - .div_ceil(size_of::()) - * size_of::(); + let word = size_of::(); + let dict_file_name_offset = + (2 * word + size_of::() + size_of::()).div_ceil(word) + * word; + let callback_offset = (dict_file_name_offset + word + size_of::() + size_of::()) + .div_ceil(word) + * word; assert!(offset_of!(FIO_rust_createCResourcesState, callback_context) == 0); - assert!(offset_of!(FIO_rust_createCResourcesState, prefs) == size_of::()); - assert!( - offset_of!(FIO_rust_createCResourcesState, compression_params) - == 2 * size_of::() - ); + assert!(offset_of!(FIO_rust_createCResourcesState, prefs) == word); + assert!(offset_of!(FIO_rust_createCResourcesState, compression_params) == 2 * word); assert!( offset_of!(FIO_rust_createCResourcesState, compression_level) - == 2 * size_of::() + size_of::() + == 2 * word + size_of::() ); - assert!(offset_of!(FIO_rust_createCResourcesState, set_parameter) == callback_offset); - assert!(offset_of!(FIO_rust_createCResourcesState, is_error) == callback_offset + size_of::()); + assert!(offset_of!(FIO_rust_createCResourcesState, dict_file_name) == dict_file_name_offset); assert!( - offset_of!(FIO_rust_createCResourcesState, display_overlap) - == callback_offset + 2 * size_of::() + offset_of!(FIO_rust_createCResourcesState, max_src_file_size) + == dict_file_name_offset + word ); assert!( - size_of::() == callback_offset + 3 * size_of::() + offset_of!(FIO_rust_createCResourcesState, multithreaded) + == dict_file_name_offset + word + size_of::() ); + assert!(offset_of!(FIO_rust_createCResourcesState, create_cctx) == callback_offset); + assert!( + offset_of!(FIO_rust_createCResourcesState, prepare_dictionary) == callback_offset + word + ); + assert!( + offset_of!(FIO_rust_createCResourcesState, create_write_pool) == callback_offset + 2 * word + ); + assert!( + offset_of!(FIO_rust_createCResourcesState, create_read_pool) == callback_offset + 3 * word + ); + assert!( + offset_of!(FIO_rust_createCResourcesState, validate_dictionary) + == callback_offset + 4 * word + ); + assert!( + offset_of!(FIO_rust_createCResourcesState, load_dictionary) == callback_offset + 5 * word + ); + assert!( + offset_of!(FIO_rust_createCResourcesState, set_parameter) == callback_offset + 6 * word + ); + assert!(offset_of!(FIO_rust_createCResourcesState, is_error) == callback_offset + 7 * word); + assert!( + offset_of!(FIO_rust_createCResourcesState, display_overlap) == callback_offset + 8 * word + ); + assert!(size_of::() == callback_offset + 9 * word); }; -#[no_mangle] -pub unsafe extern "C" fn FIO_rust_createCResources( - state: *const FIO_rust_createCResourcesState, -) -> usize { - if state.is_null() { - return usize::MAX; - } - let state = unsafe { &*state }; +#[inline] +unsafe fn set_c_resources_parameters(state: &FIO_rust_createCResourcesState) -> usize { if state.prefs.is_null() { return usize::MAX; } let prefs = unsafe { &*state.prefs }; - let mut compression_params = state.compression_params; - if prefs.adaptiveMode != 0 && prefs.ldmFlag == 0 && compression_params.windowLog == 0 { - compression_params.windowLog = FIO_ADAPT_WINDOWLOG_DEFAULT; - } - + let compression_params = state.compression_params; + let set_parameter = |parameter: c_int, value: c_int| { + let result = unsafe { (state.set_parameter)(state.callback_context, parameter, value) }; + if unsafe { (state.is_error)(result) } != 0 { + Some(result) + } else { + None + } + }; let parameters = [ (FIO_ZSTD_C_CONTENT_SIZE_FLAG, prefs.contentSize), (FIO_ZSTD_C_DICT_ID_FLAG, prefs.dictIDFlag), @@ -614,33 +644,18 @@ pub unsafe extern "C" fn FIO_rust_createCResources( (FIO_ZSTD_C_LDM_MIN_MATCH, prefs.ldmMinMatch), ]; for (parameter, value) in parameters { - let result = unsafe { (state.set_parameter)(state.callback_context, parameter, value) }; - if unsafe { (state.is_error)(result) } != 0 { - return result; + if let Some(error) = set_parameter(parameter, value) { + return error; } } if prefs.ldmBucketSizeLog != FIO_LDM_PARAM_NOTSET { - let result = unsafe { - (state.set_parameter)( - state.callback_context, - FIO_ZSTD_C_LDM_BUCKET_SIZE_LOG, - prefs.ldmBucketSizeLog, - ) - }; - if unsafe { (state.is_error)(result) } != 0 { - return result; + if let Some(error) = set_parameter(FIO_ZSTD_C_LDM_BUCKET_SIZE_LOG, prefs.ldmBucketSizeLog) { + return error; } } if prefs.ldmHashRateLog != FIO_LDM_PARAM_NOTSET { - let result = unsafe { - (state.set_parameter)( - state.callback_context, - FIO_ZSTD_C_LDM_HASH_RATE_LOG, - prefs.ldmHashRateLog, - ) - }; - if unsafe { (state.is_error)(result) } != 0 { - return result; + if let Some(error) = set_parameter(FIO_ZSTD_C_LDM_HASH_RATE_LOG, prefs.ldmHashRateLog) { + return error; } } @@ -663,11 +678,62 @@ pub unsafe extern "C" fn FIO_rust_createCResources( (FIO_ZSTD_C_ENABLE_DEDICATED_DICT_SEARCH, 1), ]; for (parameter, value) in parameters { - let result = unsafe { (state.set_parameter)(state.callback_context, parameter, value) }; + if let Some(error) = set_parameter(parameter, value) { + return error; + } + } + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn FIO_rust_createCResources( + state: *const FIO_rust_createCResourcesState, +) -> usize { + let Some(state) = (unsafe { state.as_ref() }) else { + return usize::MAX; + }; + if state.prefs.is_null() { + return usize::MAX; + } + let prefs = unsafe { &*state.prefs }; + + unsafe { (state.create_cctx)(state.callback_context) }; + let mut policy = *state; + let mut compression_params = state.compression_params; + unsafe { + (state.prepare_dictionary)( + state.callback_context, + state.prefs, + state.dict_file_name, + state.max_src_file_size, + state.compression_level, + (&mut compression_params as *mut FIO_compressionParameters).cast(), + ); + (state.create_write_pool)(state.callback_context, state.prefs); + (state.create_read_pool)(state.callback_context, state.prefs); + (state.validate_dictionary)(state.callback_context); + } + if prefs.adaptiveMode != 0 && prefs.ldmFlag == 0 && compression_params.windowLog == 0 { + compression_params.windowLog = FIO_ADAPT_WINDOWLOG_DEFAULT; + } + policy.compression_params = compression_params; + + let result = unsafe { set_c_resources_parameters(&policy) }; + if unsafe { (state.is_error)(result) } != 0 { + return result; + } + if state.multithreaded != 0 { + let result = unsafe { FIO_rust_setCResourcesMtParameters(&policy) }; if unsafe { (state.is_error)(result) } != 0 { return result; } } + + let patch_from_mode = prefs.patchFromMode; + let result = unsafe { (state.load_dictionary)(state.callback_context, patch_from_mode) }; + if unsafe { (state.is_error)(result) } != 0 { + return result; + } 0 } @@ -711,7 +777,11 @@ pub unsafe extern "C" fn FIO_rust_setCResourcesMtParameters( } } let result = unsafe { - (state.set_parameter)(state.callback_context, FIO_ZSTD_C_RSYNCABLE, prefs.rsyncable) + (state.set_parameter)( + state.callback_context, + FIO_ZSTD_C_RSYNCABLE, + prefs.rsyncable, + ) }; if unsafe { (state.is_error)(result) } != 0 { return result; @@ -730,19 +800,12 @@ pub type FIO_listMultipleFilesListFileFn = unsafe extern "C" fn( pub type FIO_listMultipleFilesDisplayTotalFn = unsafe extern "C" fn(*mut c_void, *const FIO_listFileInfoProjection_t); -pub type FIO_listFileGetInfoFn = unsafe extern "C" fn( - *mut c_void, - *const c_char, - *mut FIO_fileInfo_t, -) -> c_int; +pub type FIO_listFileGetInfoFn = + unsafe extern "C" fn(*mut c_void, *const c_char, *mut FIO_fileInfo_t) -> c_int; pub type FIO_listFileDisplayStatusFn = unsafe extern "C" fn(*mut c_void, c_int, *const c_char, c_int); -pub type FIO_listFileDisplayInfoFn = unsafe extern "C" fn( - *mut c_void, - *const c_char, - *const FIO_fileInfo_t, - c_int, -); +pub type FIO_listFileDisplayInfoFn = + unsafe extern "C" fn(*mut c_void, *const c_char, *const FIO_fileInfo_t, c_int); /// Callbacks for the C-owned `--list` file operation. /// @@ -902,11 +965,7 @@ pub extern "C" fn FIO_rust_compressDestinationTransferStat( destination_is_stdout: c_int, source_is_regular: c_int, ) -> c_int { - compress_destination_transfer_stat( - source_is_stdin, - destination_is_stdout, - source_is_regular, - ) + compress_destination_transfer_stat(source_is_stdin, destination_is_stdout, source_is_regular) } /// Callback projection for the C-owned `--list` file operations. @@ -2895,18 +2954,12 @@ mod tests { #[test] fn list_file_status_action_preserves_cli_mapping_and_abi() { for (status, action) in [ - ( - FIO_LIST_INFO_SUCCESS, - FIO_RUST_LIST_FILE_ACTION_SUCCESS, - ), + (FIO_LIST_INFO_SUCCESS, FIO_RUST_LIST_FILE_ACTION_SUCCESS), ( FIO_LIST_INFO_FRAME_ERROR, FIO_RUST_LIST_FILE_ACTION_FRAME_ERROR, ), - ( - FIO_LIST_INFO_NOT_ZSTD, - FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD, - ), + (FIO_LIST_INFO_NOT_ZSTD, FIO_RUST_LIST_FILE_ACTION_NOT_ZSTD), ( FIO_LIST_INFO_FILE_ERROR, FIO_RUST_LIST_FILE_ACTION_FILE_ERROR, @@ -2935,10 +2988,7 @@ mod tests { #[test] fn remove_file_action_preserves_status_mapping_and_unknown_failure_policy() { for (status, action) in [ - ( - FIO_REMOVE_SUCCESS, - FIO_RUST_REMOVE_FILE_ACTION_SUCCESS, - ), + (FIO_REMOVE_SUCCESS, FIO_RUST_REMOVE_FILE_ACTION_SUCCESS), ( FIO_REMOVE_STAT_FAILED, FIO_RUST_REMOVE_FILE_ACTION_STAT_FAILED, @@ -2947,10 +2997,7 @@ mod tests { FIO_REMOVE_NON_REGULAR, FIO_RUST_REMOVE_FILE_ACTION_NON_REGULAR, ), - ( - FIO_REMOVE_FAILED, - FIO_RUST_REMOVE_FILE_ACTION_FAILED, - ), + (FIO_REMOVE_FAILED, FIO_RUST_REMOVE_FILE_ACTION_FAILED), (-1, FIO_RUST_REMOVE_FILE_ACTION_INVALID), (c_int::MAX, FIO_RUST_REMOVE_FILE_ACTION_INVALID), ] { @@ -3289,9 +3336,75 @@ mod tests { #[derive(Default)] struct CreateCResourcesTestState { events: Vec<(c_int, c_int)>, + lifecycle: Vec<&'static str>, fail_parameter: Option, } + unsafe extern "C" fn create_c_resources_create_cctx_test(context: *mut c_void) { + unsafe { + (*context.cast::()) + .lifecycle + .push("create-cctx"); + } + } + + unsafe extern "C" fn create_c_resources_prepare_dictionary_test( + context: *mut c_void, + _prefs: *const FIO_prefs_t, + _dict_file_name: *const c_char, + _max_src_file_size: u64, + _compression_level: c_int, + _compression_params: *mut c_void, + ) { + unsafe { + (*context.cast::()) + .lifecycle + .push("prepare-dictionary"); + } + } + + unsafe extern "C" fn create_c_resources_create_write_pool_test( + context: *mut c_void, + _prefs: *const FIO_prefs_t, + ) { + unsafe { + (*context.cast::()) + .lifecycle + .push("create-write-pool"); + } + } + + unsafe extern "C" fn create_c_resources_create_read_pool_test( + context: *mut c_void, + _prefs: *const FIO_prefs_t, + ) { + unsafe { + (*context.cast::()) + .lifecycle + .push("create-read-pool"); + } + } + + unsafe extern "C" fn create_c_resources_validate_dictionary_test(context: *mut c_void) { + unsafe { + (*context.cast::()) + .lifecycle + .push("validate-dictionary"); + } + } + + unsafe extern "C" fn create_c_resources_load_dictionary_test( + context: *mut c_void, + _patch_from_mode: c_int, + ) -> usize { + unsafe { + (*context.cast::()) + .lifecycle + .push("load-dictionary"); + } + 0 + } + unsafe extern "C" fn create_c_resources_set_parameter_test( context: *mut c_void, parameter: c_int, @@ -3342,6 +3455,15 @@ mod tests { strategy: 6, }, compression_level: 7, + dict_file_name: ptr::null(), + max_src_file_size: 0, + multithreaded: 0, + create_cctx: create_c_resources_create_cctx_test, + prepare_dictionary: create_c_resources_prepare_dictionary_test, + create_write_pool: create_c_resources_create_write_pool_test, + create_read_pool: create_c_resources_create_read_pool_test, + validate_dictionary: create_c_resources_validate_dictionary_test, + load_dictionary: create_c_resources_load_dictionary_test, set_parameter: create_c_resources_set_parameter_test, is_error: create_c_resources_is_error_test, display_overlap: create_c_resources_display_overlap_test, @@ -3357,6 +3479,17 @@ mod tests { let result = unsafe { FIO_rust_createCResources(&state) }; assert_eq!(result, 0); + assert_eq!( + context.lifecycle, + vec![ + "create-cctx", + "prepare-dictionary", + "create-write-pool", + "create-read-pool", + "validate-dictionary", + "load-dictionary", + ] + ); assert_eq!( context.events, vec![ @@ -3464,10 +3597,7 @@ mod tests { assert_eq!(result, usize::MAX); assert_eq!( context.events, - vec![ - (FIO_ZSTD_C_NB_WORKERS, 3), - (FIO_ZSTD_C_JOB_SIZE, 4096), - ] + vec![(FIO_ZSTD_C_NB_WORKERS, 3), (FIO_ZSTD_C_JOB_SIZE, 4096),] ); } @@ -4564,12 +4694,7 @@ mod tests { let mut output = sentinel; let result = unsafe { - FIO_rust_listFile( - file_name.as_ptr(), - display_level, - &mut output, - &callbacks, - ) + FIO_rust_listFile(file_name.as_ptr(), display_level, &mut output, &callbacks) }; assert_eq!(result, expected_return, "status {status}"); @@ -4803,20 +4928,15 @@ mod tests { let output_dir = CString::new("out").unwrap(); unsafe { - let name = - FIO_determineCompressedName(source.as_ptr(), ptr::null(), suffix.as_ptr()); + let name = FIO_determineCompressedName(source.as_ptr(), ptr::null(), suffix.as_ptr()); assert_eq!(CStr::from_ptr(name).to_bytes(), b"input/nested/file.zst"); - let name = FIO_determineCompressedName( - source.as_ptr(), - output_dir.as_ptr(), - suffix.as_ptr(), - ); + let name = + FIO_determineCompressedName(source.as_ptr(), output_dir.as_ptr(), suffix.as_ptr()); assert_eq!(CStr::from_ptr(name).to_bytes(), b"out/file.zst"); let stdin = CString::new("/*stdin*\\").unwrap(); - let name = - FIO_determineCompressedName(stdin.as_ptr(), ptr::null(), suffix.as_ptr()); + let name = FIO_determineCompressedName(stdin.as_ptr(), ptr::null(), suffix.as_ptr()); assert_eq!(CStr::from_ptr(name).to_bytes(), b"/*stdout*\\"); } } @@ -5105,33 +5225,21 @@ mod tests { for display_level in [0, 2, 3] { FIO_setNotificationLevel(display_level); - assert_eq!( - unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, - 0 - ); + assert_eq!(unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, 0); } ctx.nbFilesProcessed = 1; for display_level in [0, 2, 3] { FIO_setNotificationLevel(display_level); - assert_eq!( - unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, - 1 - ); + assert_eq!(unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, 1); } ctx.nbFilesProcessed = 2; FIO_setNotificationLevel(0); - assert_eq!( - unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, - 1 - ); + assert_eq!(unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, 1); ctx.nbFilesTotal = 1; - assert_eq!( - unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, - 0 - ); + assert_eq!(unsafe { FIO_shouldDisplayMultipleFileSummary(&ctx) }, 0); FIO_setNotificationLevel(2); }