#![cfg(feature = "io-uring")]
use crate::io_uring_backend::ops::UserData;
use crate::io_uring_backend::send_buffer_pool::RegisteredSendBufferId;
use bytes::Bytes; use std::collections::HashMap;
use std::os::unix::io::RawFd;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum InternalOpType {
Accept,
RingRead,
Send,
CloseFd,
GenericHandlerOp,
EventFdPoll,
RingReadMultishot,
AsyncCancel,
SendZeroCopy,
}
#[derive(Debug, Clone)] pub(crate) enum InternalOpPayload {
None,
SendBuffer {
buffer: Bytes, app_op_ud: Option<UserData>, app_op_name: Option<String>, },
CancelTarget {
target_user_data: UserData,
},
SendZeroCopy {
send_buf_id: RegisteredSendBufferId, app_op_ud: UserData, app_op_name: String, },
}
impl Default for InternalOpPayload {
fn default() -> Self {
InternalOpPayload::None
}
}
#[derive(Debug, Clone)] pub(crate) struct InternalOpDetails {
pub fd: RawFd,
pub op_type: InternalOpType,
pub payload: InternalOpPayload, }
#[derive(Debug)]
pub(crate) struct InternalOpTracker {
pub(crate) op_to_details: HashMap<UserData, InternalOpDetails>,
pub(crate) next_id: UserData,
}
impl InternalOpTracker {
pub fn new() -> Self {
Self {
op_to_details: HashMap::new(),
next_id: 1_000_000_000,
}
}
pub fn new_op_id(
&mut self,
fd: RawFd,
op_type: InternalOpType,
payload: InternalOpPayload, ) -> UserData {
let id = self.next_id;
self.next_id = self.next_id.wrapping_add(1);
if self.next_id == 0 {
self.next_id = 1_000_000_000;
}
self.op_to_details.insert(
id,
InternalOpDetails {
fd,
op_type,
payload,
},
);
id
}
pub fn take_op_details(&mut self, user_data: UserData) -> Option<InternalOpDetails> {
self.op_to_details.remove(&user_data)
}
#[allow(dead_code)]
pub fn get_op_details(&self, user_data: UserData) -> Option<&InternalOpDetails> {
self.op_to_details.get(&user_data)
}
pub fn is_empty(&self) -> bool {
self.op_to_details.is_empty()
}
pub fn remove_ops_for_fd(&mut self, fd_to_remove: RawFd) {
self
.op_to_details
.retain(|_user_data, details| details.fd != fd_to_remove);
}
pub fn find_ops_for_fd(
&self,
fd_to_find: RawFd,
predicate: impl Fn(InternalOpType) -> bool,
) -> Vec<UserData> {
self
.op_to_details
.iter()
.filter(|(_, details)| details.fd == fd_to_find && predicate(details.op_type))
.map(|(user_data, _)| *user_data)
.collect()
}
pub(crate) fn has_pending_read_op(&self, fd_to_check: RawFd) -> bool {
self.op_to_details.values().any(|details| {
details.fd == fd_to_check
&& matches!(
details.op_type,
InternalOpType::RingRead | InternalOpType::RingReadMultishot
)
})
}
}