Skip to main content

dope_core/driver/ops/access/
maintenance.rs

1use std::io;
2
3use crate::{
4    backend::fixed,
5    driver::{self, schedule::ready, settings, storage::retirements},
6    io::fd::handles,
7};
8
9pub(super) struct State {
10    retirements: retirements::Queue,
11}
12
13impl State {
14    pub(super) fn try_new(file_slots: settings::FileSlots) -> io::Result<Self> {
15        Ok(Self {
16            retirements: retirements::Queue::try_new(file_slots)?,
17        })
18    }
19}
20
21#[derive(Clone, Copy)]
22#[repr(transparent)]
23pub struct Maintenance<'d>(driver::Reference<'d>);
24
25impl<'d> Maintenance<'d> {
26    pub(in crate::driver) const fn new(driver: driver::Reference<'d>) -> Self {
27        Self(driver)
28    }
29
30    pub(crate) fn has_deferred_maintenance(self) -> bool {
31        !self.0.shared.receive.returned.is_empty()
32            || !self.0.shared.maintenance.retirements.is_empty()
33    }
34
35    pub(crate) fn return_buffer(self, buffer: driver::Buffer) {
36        self.0.shared.receive.returned.push(buffer);
37    }
38
39    pub(crate) fn pop_returned_buffer(self) -> Option<driver::Buffer> {
40        self.0.shared.receive.returned.pop()
41    }
42
43    pub(crate) fn defer_route(self, id: u8) {
44        self.0
45            .shared
46            .maintenance
47            .retirements
48            .push(retirements::Record::Route(id));
49    }
50
51    pub(crate) fn defer_descriptor(
52        self,
53        slot: handles::FixedSlot,
54        outbound: Option<driver::OutboundKey>,
55    ) {
56        self.0
57            .shared
58            .maintenance
59            .retirements
60            .push(retirements::Record::Descriptor { slot, outbound });
61    }
62
63    pub(crate) fn defer_fixed_slot(self, slot: fixed::Retirement<'d>) {
64        self.0
65            .shared
66            .maintenance
67            .retirements
68            .push(retirements::Record::Retire(slot));
69    }
70
71    pub(crate) fn defer_outbound_slots(self, slots: driver::RetiredSlots<'d>) {
72        self.0
73            .shared
74            .maintenance
75            .retirements
76            .push(retirements::Record::OutboundSlots { slots });
77    }
78
79    pub(crate) fn defer_close(self, close: driver::Close<'d>) {
80        self.0
81            .shared
82            .maintenance
83            .retirements
84            .push(retirements::Record::Close {
85                slot: close.into_slot(),
86            });
87    }
88
89    pub(in crate::driver) fn pop_deferred_retirement(self) -> Option<retirements::Record<'d>> {
90        self.0.shared.maintenance.retirements.pop(self.0)
91    }
92
93    pub(crate) fn retire_fixed_release(self, released: ready::FixedRelease<'d>) {
94        let slot = released.slot();
95        match self.0.files().fixed_owner(slot) {
96            driver::FixedOwner::Accepted => self.defer_descriptor(released.into_slot(), None),
97            driver::FixedOwner::Reserved => {
98                self.defer_fixed_slot(fixed::Retirement::from_release(released));
99            }
100            driver::FixedOwner::Outbound(outbound) => {
101                if !self.0.outbound().is_unopened(outbound, slot) {
102                    self.defer_descriptor(released.into_slot(), Some(outbound));
103                    return;
104                }
105                if let Some(slots) = self
106                    .0
107                    .outbound()
108                    .release_outbound_slot(outbound, released.into_slot())
109                {
110                    self.defer_outbound_slots(slots);
111                }
112            }
113        }
114    }
115}
116
117const _: () = assert!(
118    std::mem::size_of::<Maintenance<'static>>()
119        == std::mem::size_of::<driver::Reference<'static>>()
120);