use serde::Deserialize;
use serde::Serialize;
use crate::pid::DetTid;
pub type RawFd = std::os::unix::io::RawFd;
pub type RawInode = u64;
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
PartialOrd,
Ord,
Serialize,
Deserialize
)]
pub struct DetInode(RawInode);
impl DetInode {
pub const fn mint(value: RawInode) -> Self {
Self(value)
}
pub const fn as_raw(self) -> RawInode {
self.0
}
}
impl std::fmt::Display for DetInode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FilesId {
creator: DetTid,
generation: u64,
}
impl FilesId {
pub const fn initial(creator: DetTid) -> Self {
Self {
creator,
generation: 0,
}
}
pub const fn forked(creator: DetTid) -> Self {
Self::initial(creator)
}
pub fn for_exec(self, creator: DetTid) -> Self {
let generation = if self.creator == creator {
self.generation + 1
} else {
0
};
Self {
creator,
generation,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FdSlot {
pub files: FilesId,
pub fd: RawFd,
}
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
Deserialize
)]
pub struct OpenFileId {
creator: DetTid,
sequence: u64,
}
const SOCKET_SEQUENCE_DOMAIN: u64 = 1 << 63;
impl OpenFileId {
pub const fn new(creator: DetTid, sequence: u64) -> Self {
assert!(sequence < SOCKET_SEQUENCE_DOMAIN);
Self { creator, sequence }
}
pub const fn new_socket(creator: DetTid, sequence: u64) -> Self {
assert!(sequence < SOCKET_SEQUENCE_DOMAIN);
Self {
creator,
sequence: SOCKET_SEQUENCE_DOMAIN | sequence,
}
}
pub const fn is_socket(self) -> bool {
self.sequence & SOCKET_SEQUENCE_DOMAIN != 0
}
pub fn deterministic_socket_cookie(self) -> u64 {
let creator = self.creator.as_raw() as u32 as u64;
(creator << 32) | (self.sequence & u32::MAX as u64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deterministic_socket_cookies_track_open_file_identity() {
let first = OpenFileId::new_socket(DetTid::from_raw(3), 7);
let alias = first;
let next = OpenFileId::new_socket(DetTid::from_raw(3), 8);
let other_task = OpenFileId::new_socket(DetTid::from_raw(4), 7);
assert_ne!(first.deterministic_socket_cookie(), 0);
assert!(first.is_socket());
assert!(!OpenFileId::new(DetTid::from_raw(3), 7).is_socket());
assert_eq!(
first.deterministic_socket_cookie(),
alias.deterministic_socket_cookie()
);
assert_ne!(
first.deterministic_socket_cookie(),
next.deterministic_socket_cookie()
);
assert_ne!(
first.deterministic_socket_cookie(),
other_task.deterministic_socket_cookie()
);
assert_ne!(first, OpenFileId::new(DetTid::from_raw(3), 7));
assert_eq!(first.deterministic_socket_cookie(), (3_u64 << 32) | 7);
}
}