refactor(cli): move compression metadata policy to Rust
Keep the private stat_t probe, destination opening, metadata syscalls, and format callbacks in C, but route the regular-source plus stdin/stdout exception policy through the Rust fileio preference layer. The Rust ABI bridge normalizes the scalar consumed by the existing destination lifecycle, with compile-time value assertions and focused tests covering regular, non-regular, stdin, stdout, and nonzero scalar inputs. Test Plan: Not run by request; cargo, make, native tests, and heavy commands were intentionally avoided. Lightweight git diff --check passed.
This commit is contained in:
+19
-6
@@ -334,6 +334,16 @@ int FIO_rust_adjustParamsForPatchFromMode(FIO_prefs_t* prefs,
|
|||||||
const char* FIO_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix);
|
const char* FIO_determineCompressedName(const char* srcFileName, const char* outDirName, const char* suffix);
|
||||||
const char* FIO_rust_determineDstName(const char* srcFileName, const char* outDirName,
|
const char* FIO_rust_determineDstName(const char* srcFileName, const char* outDirName,
|
||||||
const char* const* suffixList, const char* suffixListStr);
|
const char* const* suffixList, const char* suffixListStr);
|
||||||
|
enum {
|
||||||
|
FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO = 0,
|
||||||
|
FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES = 1
|
||||||
|
};
|
||||||
|
typedef char FIO_rust_compress_dst_transfer_stat_values[
|
||||||
|
(FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO == 0
|
||||||
|
&& FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES == 1) ? 1 : -1];
|
||||||
|
int FIO_rust_compressDestinationTransferStat(int sourceIsStdin,
|
||||||
|
int destinationIsStdout,
|
||||||
|
int sourceIsRegular);
|
||||||
int FIO_rust_adjustMemLimitForPatchFromMode(FIO_prefs_t* prefs,
|
int FIO_rust_adjustMemLimitForPatchFromMode(FIO_prefs_t* prefs,
|
||||||
unsigned long long dictSize,
|
unsigned long long dictSize,
|
||||||
unsigned long long maxSrcFileSize);
|
unsigned long long maxSrcFileSize);
|
||||||
@@ -3258,8 +3268,9 @@ static void FIO_rust_compressDestinationRemove(void* opaque,
|
|||||||
/*! FIO_compressFilename_dstFile() :
|
/*! FIO_compressFilename_dstFile() :
|
||||||
* open the destination, or pass through if the write pool already owns it,
|
* open the destination, or pass through if the write pool already owns it,
|
||||||
* then start compression with FIO_compressFilename_internal().
|
* then start compression with FIO_compressFilename_internal().
|
||||||
* Rust owns the lifecycle ordering; C retains opaque resources, diagnostics,
|
* Rust owns the lifecycle ordering and scalar metadata-transfer policy; C
|
||||||
* metadata operations, and format-specific compression callbacks.
|
* retains opaque resources, the private stat probe, metadata operations, and
|
||||||
|
* format-specific compression callbacks.
|
||||||
* note : ress.readCtx must already have a source file attached,
|
* note : ress.readCtx must already have a source file attached,
|
||||||
* so reach this function through FIO_compressFilename_srcFile().
|
* so reach this function through FIO_compressFilename_srcFile().
|
||||||
* @return : 0 : compression completed correctly,
|
* @return : 0 : compression completed correctly,
|
||||||
@@ -3293,10 +3304,12 @@ static int FIO_compressFilename_dstFile(FIO_ctx_t* const fCtx,
|
|||||||
projection.destinationAlreadyOpen = AIO_WritePool_getFile(ress.writeCtx) != NULL;
|
projection.destinationAlreadyOpen = AIO_WritePool_getFile(ress.writeCtx) != NULL;
|
||||||
projection.sourceIsStdin = !strcmp(srcFileName, stdinmark);
|
projection.sourceIsStdin = !strcmp(srcFileName, stdinmark);
|
||||||
projection.destinationIsStdout = !strcmp(dstFileName, stdoutmark);
|
projection.destinationIsStdout = !strcmp(dstFileName, stdoutmark);
|
||||||
projection.sourceIsRegular = (projection.sourceIsStdin
|
/* C probes the private stat_t; Rust owns the stdin/stdout exceptions and
|
||||||
|| projection.destinationIsStdout)
|
* normalizes the scalar consumed by the Rust destination lifecycle. */
|
||||||
? 0
|
projection.sourceIsRegular = FIO_rust_compressDestinationTransferStat(
|
||||||
: UTIL_isRegularFileStat(srcFileStat);
|
projection.sourceIsStdin,
|
||||||
|
projection.destinationIsStdout,
|
||||||
|
UTIL_isRegularFileStat(srcFileStat));
|
||||||
projection.openDestination = FIO_rust_compressDestinationOpen;
|
projection.openDestination = FIO_rust_compressDestinationOpen;
|
||||||
projection.attachDestination = FIO_rust_compressDestinationAttach;
|
projection.attachDestination = FIO_rust_compressDestinationAttach;
|
||||||
projection.addHandler = FIO_rust_compressAddHandler;
|
projection.addHandler = FIO_rust_compressAddHandler;
|
||||||
|
|||||||
@@ -48,7 +48,14 @@ pub const FIO_RUST_REMOVE_FILE_ACTION_STAT_FAILED: c_int = 1;
|
|||||||
pub const FIO_RUST_REMOVE_FILE_ACTION_NON_REGULAR: c_int = 2;
|
pub const FIO_RUST_REMOVE_FILE_ACTION_NON_REGULAR: c_int = 2;
|
||||||
pub const FIO_RUST_REMOVE_FILE_ACTION_FAILED: c_int = 3;
|
pub const FIO_RUST_REMOVE_FILE_ACTION_FAILED: c_int = 3;
|
||||||
pub const FIO_RUST_REMOVE_FILE_ACTION_INVALID: c_int = 4;
|
pub const FIO_RUST_REMOVE_FILE_ACTION_INVALID: c_int = 4;
|
||||||
|
const FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO: c_int = 0;
|
||||||
|
const FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES: c_int = 1;
|
||||||
const UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX;
|
const UTIL_FILESIZE_UNKNOWN: u64 = u64::MAX;
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
assert!(FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO == 0);
|
||||||
|
assert!(FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES == 1);
|
||||||
|
};
|
||||||
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
|
const COMPRESSED_FILE_EXTENSIONS: &[&[u8]] = &[
|
||||||
b".zst",
|
b".zst",
|
||||||
b".tzst",
|
b".tzst",
|
||||||
@@ -764,6 +771,37 @@ pub extern "C" fn FIO_rust_removeFileAction(status: c_int) -> c_int {
|
|||||||
remove_file_action(status)
|
remove_file_action(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn compress_destination_transfer_stat(
|
||||||
|
source_is_stdin: c_int,
|
||||||
|
destination_is_stdout: c_int,
|
||||||
|
source_is_regular: c_int,
|
||||||
|
) -> c_int {
|
||||||
|
if source_is_stdin != 0 || destination_is_stdout != 0 {
|
||||||
|
FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO
|
||||||
|
} else {
|
||||||
|
c_int::from(source_is_regular != 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Select whether compression should transfer source metadata to its output.
|
||||||
|
///
|
||||||
|
/// C retains the private `stat_t` probe and the actual metadata operations.
|
||||||
|
/// Rust owns the scalar policy: stdin and stdout never transfer metadata, and
|
||||||
|
/// otherwise a regular source enables the transfer.
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn FIO_rust_compressDestinationTransferStat(
|
||||||
|
source_is_stdin: c_int,
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Callback projection for the C-owned `--list` file operations.
|
/// Callback projection for the C-owned `--list` file operations.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct FIO_listMultipleFilesCallbacks_t {
|
pub struct FIO_listMultipleFilesCallbacks_t {
|
||||||
@@ -2677,6 +2715,36 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_destination_transfer_stat_preserves_metadata_exceptions() {
|
||||||
|
for (source_is_stdin, destination_is_stdout, source_is_regular, expected) in [
|
||||||
|
(0, 0, 0, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
|
||||||
|
(0, 0, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES),
|
||||||
|
(-1, 0, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
|
||||||
|
(0, 1, 1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_NO),
|
||||||
|
(0, 0, -1, FIO_RUST_COMPRESS_DST_TRANSFER_STAT_YES),
|
||||||
|
] {
|
||||||
|
assert_eq!(
|
||||||
|
compress_destination_transfer_stat(
|
||||||
|
source_is_stdin,
|
||||||
|
destination_is_stdout,
|
||||||
|
source_is_regular,
|
||||||
|
),
|
||||||
|
expected,
|
||||||
|
"unexpected metadata policy for stdin={source_is_stdin}, stdout={destination_is_stdout}, regular={source_is_regular}"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
FIO_rust_compressDestinationTransferStat(
|
||||||
|
source_is_stdin,
|
||||||
|
destination_is_stdout,
|
||||||
|
source_is_regular,
|
||||||
|
),
|
||||||
|
expected,
|
||||||
|
"C ABI disagrees for stdin={source_is_stdin}, stdout={destination_is_stdout}, regular={source_is_regular}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
|
fn source_exclusion_preserves_case_sensitive_suffixes_and_null_policy() {
|
||||||
let cases = [
|
let cases = [
|
||||||
|
|||||||
Reference in New Issue
Block a user