jay-compositor 1.15.0

The Jay compositor
use crate::async_engine::AsyncEngine;
use crate::async_engine::SpawnedFuture;
use crate::io_uring::IoUring;
use crate::io_uring::PendingReadMultishot;
use crate::io_uring::buffer_ring::BufferRing;
use crate::utils::box_cache::BoxCache;
use crate::utils::box_cache::BoxReset;
use crate::utils::clonecell::CloneCell;
use crate::utils::fuse::fuse_dir::FuseDirents;
use crate::utils::fuse::fuse_dir::FuseOpenDir;
use crate::utils::fuse::fuse_error::FuseError;
use crate::utils::fuse::fuse_inode_cache::InodeCache;
use crate::utils::fuse::fuse_mgr::FuseMgrShutdownQueue;
use crate::utils::fuse::fuse_out::OutCache;
use crate::utils::fuse::fuse_reg::FuseOpenReg;
use crate::utils::fx_hash::FHashMap;
use crate::utils::numcell::NumCell;
use crate::utils::run_toplevel::RunToplevel;
use jay_algorithms::oserror::OsError;
use std::cell::Cell;
use std::cell::RefCell;
use std::mem::ManuallyDrop;
use std::rc::Rc;
use std::rc::Weak;
use uapi::OwnedFd;
use uapi::c;

pub trait FuseMountOwner {
    fn success(&self);
    fn failed(self: Rc<Self>, error: FuseError);
}

pub struct FuseMount {
    pub(super) shared: Rc<FuseMountEarlyShared>,
}

pub(super) struct FuseMountOwnerHolder {
    pub(super) run_toplevel: Rc<RunToplevel>,
    pub(super) owner: Rc<CloneCell<Option<Rc<dyn FuseMountOwner>>>>,
    pub(super) error: Cell<Option<FuseError>>,
}

pub(super) struct FuseMountEarlyShared {
    pub(super) shutdown: Rc<FuseMgrShutdownQueue>,
    pub(super) read_multishot: Cell<Option<PendingReadMultishot>>,
    pub(super) futures: Cell<Vec<SpawnedFuture<()>>>,
    pub(super) cancelled: Cell<bool>,
    pub(super) owner: Weak<FuseMountOwnerHolder>,
}

pub(super) struct FuseMountShared {
    pub(super) eng: Rc<AsyncEngine>,
    pub(super) ring: Rc<IoUring>,
    pub(super) _socket: Rc<OwnedFd>,
    pub(super) fd: Rc<OwnedFd>,
    pub(super) buffer_ring: Rc<BufferRing>,
    pub(super) cache: Rc<OutCache>,
    pub(super) inodes: ManuallyDrop<InodeCache>,
    pub(super) early: Rc<FuseMountEarlyShared>,
    pub(super) fh: NumCell<u64>,
    pub(super) dirs: RefCell<FHashMap<u64, FuseOpenDir>>,
    pub(super) dirents: Rc<BoxCache<FuseDirents, BoxReset>>,
    pub(super) files: RefCell<FHashMap<u64, FuseOpenReg>>,
    pub(super) contents: Rc<BoxCache<String, BoxReset>>,
}

impl Drop for FuseMountShared {
    fn drop(&mut self) {
        self.cache.clear();
        let inodes = unsafe { ManuallyDrop::take(&mut self.inodes) };
        self.early.shutdown.push(inodes);
    }
}

impl FuseMountEarlyShared {
    fn clear(&self) {
        if let Some(v) = self.owner.upgrade() {
            v.owner.take();
        }
        self.cancel();
    }

    pub(super) fn fatal(&self, mut error: FuseError) {
        if let FuseError::ReadRequests(OsError(c::ECONNABORTED)) = error {
            error = FuseError::Aborted;
        }
        if let Some(v) = self.owner.upgrade() {
            v.error.set(Some(error));
        }
        self.cancel();
    }

    fn cancel(&self) {
        self.cancelled.set(true);
        self.futures.take();
        self.read_multishot.take();
    }
}

impl FuseMountOwnerHolder {
    pub(super) fn success(&self) {
        let owner = self.owner.clone();
        self.run_toplevel.schedule(move || {
            if let Some(owner) = owner.get() {
                owner.success();
            }
        });
    }
}

impl Drop for FuseMountOwnerHolder {
    fn drop(&mut self) {
        let error = self.error.take().unwrap_or(FuseError::Unknown);
        let owner = self.owner.clone();
        self.run_toplevel.schedule(move || {
            if let Some(owner) = owner.take() {
                owner.failed(error);
            }
        });
    }
}

impl Drop for FuseMount {
    fn drop(&mut self) {
        self.shared.clear();
    }
}