#[cfg(target_os = "macos")]
use std::sync::atomic::AtomicI64;
use std::{borrow::Borrow, collections::BTreeMap, sync::atomic::AtomicU64};
#[cfg(target_os = "linux")]
use std::{
collections::BTreeSet,
fs::File,
sync::{Mutex, RwLock},
};
#[derive(Default)]
pub(crate) struct MultikeyBTreeMap<K1, K2, V>
where
K1: Ord,
K2: Ord,
{
main: BTreeMap<K1, (K2, V)>,
alt: BTreeMap<K2, K1>,
}
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
#[cfg_attr(target_os = "linux", allow(dead_code))]
pub(crate) struct InodeAltKey {
pub ino: u64,
pub dev: u64,
#[cfg(target_os = "linux")]
pub mnt_id: u64,
}
#[cfg(target_os = "linux")]
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
pub(crate) struct NamespaceAlias {
pub parent: u64,
pub name: Vec<u8>,
}
#[cfg_attr(target_os = "linux", allow(dead_code))]
pub(crate) struct InodeData {
pub inode: u64,
pub ino: u64,
pub dev: u64,
pub refcount: AtomicU64,
#[cfg(target_os = "linux")]
pub mnt_id: u64,
#[cfg(target_os = "linux")]
pub anchor_parent: AtomicU64,
#[cfg(target_os = "linux")]
pub anchor_name: RwLock<Vec<u8>>,
#[cfg(target_os = "linux")]
pub aliases: RwLock<BTreeSet<NamespaceAlias>>,
#[cfg(target_os = "linux")]
pub anchor_children: AtomicU64,
#[cfg(target_os = "linux")]
pub retained_fd: Mutex<Option<File>>,
#[cfg(target_os = "macos")]
pub unlinked_fd: AtomicI64,
}
impl<K1, K2, V> MultikeyBTreeMap<K1, K2, V>
where
K1: Clone + Ord,
K2: Clone + Ord,
{
pub fn new() -> Self {
MultikeyBTreeMap {
main: BTreeMap::default(),
alt: BTreeMap::default(),
}
}
pub fn get<Q>(&self, key: &Q) -> Option<&V>
where
K1: Borrow<Q>,
Q: Ord + ?Sized,
{
self.main.get(key).map(|(_, v)| v)
}
pub fn get_alt<Q2>(&self, key: &Q2) -> Option<&V>
where
K2: Borrow<Q2>,
Q2: Ord + ?Sized,
{
if let Some(k) = self.alt.get(key) {
self.get(k)
} else {
None
}
}
pub fn insert(&mut self, k1: K1, k2: K2, v: V) -> Option<V> {
let oldval = if let Some(oldkey) = self.alt.insert(k2.clone(), k1.clone()) {
self.main.remove(&oldkey)
} else {
None
};
self.main
.insert(k1, (k2.clone(), v))
.or(oldval)
.map(|(oldk2, v)| {
if oldk2 != k2 {
self.alt.remove(&oldk2);
}
v
})
}
pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
K1: Borrow<Q>,
Q: Ord + ?Sized,
{
self.main.remove(key).map(|(k2, v)| {
self.alt.remove(&k2);
v
})
}
pub fn clear(&mut self) {
self.alt.clear();
self.main.clear();
}
}
impl InodeAltKey {
#[cfg(target_os = "linux")]
pub fn new(ino: u64, dev: u64, mnt_id: u64) -> Self {
Self { ino, dev, mnt_id }
}
#[cfg(target_os = "macos")]
pub fn new(ino: u64, dev: u64) -> Self {
Self { ino, dev }
}
}
#[cfg(target_os = "linux")]
impl NamespaceAlias {
pub fn new(parent: u64, name: &[u8]) -> Self {
Self {
parent,
name: name.to_vec(),
}
}
}