jay-compositor 1.15.0

The Jay compositor
use crate::async_engine::AsyncEngine;
use crate::async_engine::SpawnedFuture;
use crate::forker::ForkerProxy;
use crate::io_uring::IoUring;
use crate::state::State;
use crate::utils::clonecell::CloneCell;
use crate::utils::fuse::fuse_inode::FuseInode;
use crate::utils::fuse::fuse_inode_cache::InodeCache;
use crate::utils::fuse::fuse_mount::FuseMount;
use crate::utils::fuse::fuse_mount::FuseMountEarlyShared;
use crate::utils::fuse::fuse_mount::FuseMountOwner;
use crate::utils::fuse::fuse_mount::FuseMountOwnerHolder;
use crate::utils::queue::AsyncQueue;
use crate::utils::run_toplevel::RunToplevel;
use std::cell::Cell;
use std::num::NonZeroU64;
use std::rc::Rc;

#[jay_proc::jay_hash]
#[derive(Copy, Clone, Debug, Eq, Ord, PartialOrd)]
pub(super) struct FuseIno(pub(super) NonZeroU64);

pub struct FuseMgr {
    run_toplevel: Rc<RunToplevel>,
    pub(super) eng: Rc<AsyncEngine>,
    pub(super) ring: Rc<IoUring>,
    shutdown: Rc<FuseMgrShutdownQueue>,
    _task: SpawnedFuture<()>,
}

pub(super) struct FuseMgrShutdownQueue {
    ring: Rc<IoUring>,
    dropped: Cell<bool>,
    queue: AsyncQueue<InodeCache>,
}

impl FuseMgrShutdownQueue {
    async fn run(self: Rc<Self>) {
        loop {
            self.queue.pop().await.shutdown(&self.ring).await;
        }
    }

    pub(super) fn push(&self, cache: InodeCache) {
        if self.dropped.get() {
            return;
        }
        self.queue.push(cache);
    }
}

impl FuseMgr {
    pub fn new(eng: &Rc<AsyncEngine>, ring: &Rc<IoUring>, run_toplevel: &Rc<RunToplevel>) -> Self {
        let shutdown = Rc::new(FuseMgrShutdownQueue {
            ring: ring.clone(),
            dropped: Default::default(),
            queue: Default::default(),
        });
        let task = eng.spawn("fuse shutdown queue", shutdown.clone().run());
        Self {
            run_toplevel: run_toplevel.clone(),
            eng: eng.clone(),
            ring: ring.clone(),
            shutdown,
            _task: task,
        }
    }

    fn mount(
        &self,
        forker: Option<Rc<ForkerProxy>>,
        owner: Rc<dyn FuseMountOwner>,
        root: Rc<dyn FuseInode>,
        path: &str,
    ) -> FuseMount {
        let owner = Rc::new(FuseMountOwnerHolder {
            run_toplevel: self.run_toplevel.clone(),
            owner: Rc::new(CloneCell::new(Some(owner))),
            error: Default::default(),
        });
        let shared = Rc::new(FuseMountEarlyShared {
            shutdown: self.shutdown.clone(),
            read_multishot: Default::default(),
            futures: Default::default(),
            cancelled: Default::default(),
            owner: Rc::downgrade(&owner),
        });
        let future = self.fusermount(forker, &shared, path, owner, Rc::downgrade(&root));
        shared.futures.set(vec![future]);
        FuseMount { shared }
    }
}

impl State {
    pub fn fuse_mount(
        &self,
        owner: Rc<dyn FuseMountOwner>,
        root: Rc<dyn FuseInode>,
        path: &str,
    ) -> FuseMount {
        self.fuse.mount(self.forker.get(), owner, root, path)
    }
}

impl Drop for FuseMgr {
    fn drop(&mut self) {
        self.shutdown.dropped.set(true);
        self.shutdown.queue.clear();
    }
}