use std::collections::{BTreeMap, HashMap};
use std::io::{Read, Seek, SeekFrom, self};
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct ZeroCopyReceiverConfig {
pub buffer_size: usize,
pub max_receive_size: usize,
pub receive_timeout: Duration,
pub enable_read_ahead: bool,
pub read_ahead_size: usize,
}
impl Default for ZeroCopyReceiverConfig {
fn default() -> Self {
Self {
buffer_size: 64 * 1024,
max_receive_size: 1024 * 1024 * 1024, receive_timeout: Duration::from_secs(30),
enable_read_ahead: true,
read_ahead_size: 128 * 1024,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ZeroCopyReceiverStats {
pub total_bytes_received: u64,
pub success_count: u64,
pub error_count: u64,
pub avg_receive_speed: f64,
pub peak_receive_speed: f64,
pub splice_count: u64,
pub total_receive_time: Duration,
pub last_receive: Option<Instant>,
}
#[derive(Debug)]
pub struct ZeroCopyReceiver {
config: ZeroCopyReceiverConfig,
stats: Arc<Mutex<ZeroCopyReceiverStats>>,
splice: Splice,
current_pos: u64,
}
impl ZeroCopyReceiver {
pub fn new(config: Option<ZeroCopyReceiverConfig>) -> io::Result<Self> {
let config: _ = config.unwrap_or_default();
let splice: _ = Splice::new();
Ok(Self {
config,
stats: Arc::new(Mutex::new(ZeroCopyReceiverStats::default())),
splice,
current_pos: 0,
})
}
pub fn receive_from_socket<S: AsRawFd>(
&mut self,
socket: &S,
file: &mut File,
max_bytes: usize,
) -> io::Result<u64> {
let start_time: _ = Instant::now();
let socket_fd: _ = socket.as_raw_fd();
file.seek(SeekFrom::Start(self.current_pos))?;
match self.splice.fd_to_pipe(socket_fd, &std::os::unix::net::UnixStream::pair()?.1, max_bytes) {
Ok(bytes_received) => {
self.current_pos += bytes_received;
self.update_stats_on_success(bytes_received, &start_time);
println!("✅ 零拷贝接收成功: {} bytes", bytes_received);
Ok(bytes_received)
}
Err(e) => {
self.update_stats_on_error(&start_time);
println!("❌ 零拷贝接收失败: {}", e);
Err(e)
}
}
}
pub fn receive_to_buffer<S: AsRawFd>(
&mut self,
socket: &S,
buffer: &mut Vec<u8>,
max_bytes: usize,
) -> io::Result<u64> {
let start_time: _ = Instant::now();
let socket_fd: _ = socket.as_raw_fd();
if buffer.len() < max_bytes {
buffer.resize(max_bytes, 0);
}
let mut temp_file = tempfile::tempfile()?;
let pipe: _ = std::os::unix::net::UnixStream::pair()?.1;
match self.splice.fd_to_pipe(socket_fd, &pipe, max_bytes) {
Ok(bytes_received) => {
temp_file.seek(SeekFrom::Start(0))?;
let bytes_to_read: _ = bytes_received as usize;
temp_file.read_exact(&mut buffer[0..bytes_to_read])?;
self.current_pos += bytes_received;
self.update_stats_on_success(bytes_received, &start_time);
println!("✅ 零拷贝接收数据到缓冲区成功: {} bytes", bytes_received);
Ok(bytes_received)
}
Err(e) => {
self.update_stats_on_error(&start_time);
println!("❌ 零拷贝接收数据到缓冲区失败: {}", e);
Err(e)
}
}
}
pub fn set_position(&mut self, pos: u64) {
self.current_pos = pos;
}
pub fn position(&self) -> u64 {
self.current_pos
}
pub fn reset(&mut self) {
self.current_pos = 0;
let mut stats = self.stats.lock().unwrap();
*stats = ZeroCopyReceiverStats::default();
}
pub fn get_stats(&self) -> ZeroCopyReceiverStats {
self.stats.lock().unwrap().clone()
}
pub fn progress(&self, total_size: u64) -> f64 {
if total_size > 0 {
(self.current_pos as f64 / total_size as f64) * 100.0
} else {
0.0
}
}
pub fn speed(&self) -> f64 {
let stats: _ = self.stats.lock().unwrap();
stats.avg_receive_speed
}
pub fn can_continue(&self, max_size: u64) -> bool {
self.current_pos < max_size && self.current_pos < self.config.max_receive_size as u64
}
fn update_stats_on_success(&self, bytes: u64, start_time: &Instant) {
let mut stats = self.stats.lock().unwrap();
stats.total_bytes_received += bytes;
stats.success_count += 1;
stats.last_receive = Some(Instant::now());
let elapsed: _ = start_time.elapsed();
stats.total_receive_time += elapsed;
if elapsed.as_secs_f64() > 0.0 {
let current_speed: _ = bytes as f64 / elapsed.as_secs_f64();
stats.avg_receive_speed = (stats.avg_receive_speed * (stats.success_count - 1) as f64
+ current_speed)
/ stats.success_count as f64;
if current_speed > stats.peak_receive_speed {
stats.peak_receive_speed = current_speed;
}
}
stats.splice_count += 1;
}
fn update_stats_on_error(&self, start_time: &Instant) {
let mut stats = self.stats.lock().unwrap();
stats.error_count += 1;
stats.total_receive_time += start_time.elapsed();
}
}
impl Default for ZeroCopyReceiver {
fn default() -> Self {
Self::new(None).expect("Failed to create default ZeroCopyReceiver")
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_zero_copy_receiver_creation() {
let config: _ = ZeroCopyReceiverConfig::default();
let receiver: _ = ZeroCopyReceiver::new(Some(config)).expect("创建接收器失败");
let stats: _ = receiver.get_stats();
assert_eq!(stats.total_bytes_received, 0);
assert_eq!(stats.success_count, 0);
assert_eq!(stats.error_count, 0);
println!("✅ 测试通过: 零拷贝接收器创建");
}
#[test]
fn test_position_setting() {
let mut receiver = ZeroCopyReceiver::new(None).expect("创建接收器失败");
receiver.set_position(2048);
assert_eq!(receiver.position(), 2048);
println!("✅ 测试通过: 接收位置设置");
}
#[test]
fn test_progress_calculation() {
let mut receiver = ZeroCopyReceiver::new(None).expect("创建接收器失败");
receiver.set_position(512);
let progress: _ = receiver.progress(1024);
assert_eq!(progress, 50.0);
println!("进度: {:.1}%", progress);
println!("✅ 测试通过: 进度计算");
}
#[test]
fn test_receive_stats() {
let receiver: _ = ZeroCopyReceiver::new(None).expect("创建接收器失败");
let start_time: _ = Instant::now();
receiver.update_stats_on_success(2048, &start_time);
let stats: _ = receiver.get_stats();
assert_eq!(stats.total_bytes_received, 2048);
assert_eq!(stats.success_count, 1);
assert_eq!(stats.error_count, 0);
println!("✅ 测试通过: 接收统计");
}
}