feat(cli): move trace callbacks into Rust
The CLI trace translation unit still contained the complete CSV writer and strong callback implementations even though the Rust CLI archive already had the equivalent trace module. Reduce the C file to its public-header shim and make the Rust implementation authoritative, preserving the exact CSV header, version assertion, timing fields, and no-trace build behavior. Focused tests cover header creation and the version-mismatch assertion. Test Plan: - CLI tests: 161 default and 127 reduced-feature -- passed - Focused trace tests: 3/3 in both configurations -- passed - `make -B -C programs -j2` for all CLI variants -- passed - Trace compression/decompression smoke test -- passed - C shim compile with and without `ZSTD_NOTRACE` -- passed - Clippy, nightly rustfmt, and `git diff --check` -- passed
This commit is contained in:
+39
-11
@@ -4,11 +4,12 @@
|
||||
|
||||
//! Command-line trace callbacks.
|
||||
//!
|
||||
//! `programs/zstdcli_trace.c` is a small strong-symbol override for the
|
||||
//! library's weak tracing callbacks. Keep the wire-visible structures and
|
||||
//! CSV format here so the CLI archive does not need a C implementation merely
|
||||
//! to enable tracing. The decompression-only CLI still gets the no-op
|
||||
//! callbacks below; that variant does not link the compression parameter API.
|
||||
//! `programs/zstdcli_trace.c` is a declaration-only ABI shim. These functions
|
||||
//! provide the strong-symbol override for the library's weak tracing
|
||||
//! callbacks. Keep the wire-visible structures and CSV format here so the CLI
|
||||
//! archive does not need a C implementation merely to enable tracing. The
|
||||
//! decompression-only CLI still gets the no-op callbacks below; that variant
|
||||
//! does not link the compression parameter API.
|
||||
|
||||
use std::ffi::{c_char, c_int, c_uint, c_void, CStr};
|
||||
use std::fs::{File, OpenOptions};
|
||||
@@ -17,6 +18,10 @@ use std::path::Path;
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
use std::time::Instant;
|
||||
|
||||
/* Mirrors ZSTD_VERSION_NUMBER in lib/zstd.h for the CLI/library ABI check. */
|
||||
const ZSTD_VERSION_NUMBER: c_uint = 10_507;
|
||||
const TRACE_HEADER: &str = "Algorithm, Version, Method, Mode, Level, Workers, Dictionary Size, Uncompressed Size, Compressed Size, Duration Nanos, Compression Ratio, Speed MB/s";
|
||||
|
||||
#[cfg(feature = "compression")]
|
||||
const ZSTD_C_COMPRESSION_LEVEL: c_int = 100;
|
||||
#[cfg(feature = "compression")]
|
||||
@@ -81,10 +86,7 @@ pub unsafe extern "C" fn TRACE_enable(filename: *const c_char) {
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
if let Some(mut file) = file {
|
||||
if !was_regular_file {
|
||||
let _ = writeln!(
|
||||
file,
|
||||
"Algorithm, Version, Method, Mode, Level, Workers, Dictionary Size, Uncompressed Size, Compressed Size, Duration Nanos, Compression Ratio, Speed MB/s"
|
||||
);
|
||||
let _ = writeln!(file, "{TRACE_HEADER}");
|
||||
}
|
||||
state.file = Some(file);
|
||||
} else {
|
||||
@@ -163,6 +165,13 @@ fn trace_log(method: &str, begin: u64, trace: &ZSTD_Trace, state: &mut TraceStat
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_trace_version(trace: &ZSTD_Trace) {
|
||||
debug_assert_eq!(
|
||||
trace.version, ZSTD_VERSION_NUMBER,
|
||||
"CLI version must match trace version"
|
||||
);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ZSTD_trace_compress_begin(_cctx: *const c_void) -> u64 {
|
||||
trace_begin()
|
||||
@@ -176,6 +185,7 @@ pub unsafe extern "C" fn ZSTD_trace_compress_end(ctx: u64, trace: *const ZSTD_Tr
|
||||
let mut state = trace_state()
|
||||
.lock()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
assert_trace_version(unsafe { &*trace });
|
||||
trace_log("compress", ctx, unsafe { &*trace }, &mut state);
|
||||
}
|
||||
|
||||
@@ -192,6 +202,7 @@ pub unsafe extern "C" fn ZSTD_trace_decompress_end(ctx: u64, trace: *const ZSTD_
|
||||
let mut state = trace_state()
|
||||
.lock()
|
||||
.unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
assert_trace_version(unsafe { &*trace });
|
||||
trace_log("decompress", ctx, unsafe { &*trace }, &mut state);
|
||||
}
|
||||
|
||||
@@ -222,8 +233,25 @@ mod tests {
|
||||
assert_ne!(ZSTD_trace_compress_begin(std::ptr::null()), 0);
|
||||
TRACE_finish();
|
||||
let contents = fs::read_to_string(&path).unwrap();
|
||||
assert_eq!(contents.lines().count(), 1);
|
||||
assert!(contents.starts_with("Algorithm, Version,"));
|
||||
assert_eq!(contents, format!("{TRACE_HEADER}\n"));
|
||||
let _ = fs::remove_file(path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "CLI version must match trace version")]
|
||||
fn trace_version_mismatch_panics_like_c_assertion() {
|
||||
let trace = ZSTD_Trace {
|
||||
version: ZSTD_VERSION_NUMBER - 1,
|
||||
streaming: 0,
|
||||
dictionaryID: 0,
|
||||
dictionaryIsCold: 0,
|
||||
dictionarySize: 0,
|
||||
uncompressedSize: 0,
|
||||
compressedSize: 1,
|
||||
params: std::ptr::null(),
|
||||
cctx: std::ptr::null(),
|
||||
dctx: std::ptr::null(),
|
||||
};
|
||||
assert_trace_version(&trace);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user