use std::sync::Arc;
use super::dirty::DirtyPool;
#[cfg(feature = "readiness")]
use super::readiness::SharedReadiness;
use crate::distribution::DistributionConfig;
use crate::io::RingConfig;
#[derive(Clone)]
pub(super) enum DirtyChoice {
FromConfig,
Disabled,
Owned(usize),
Shared(Arc<DirtyPool>),
}
#[cfg(feature = "readiness")]
#[derive(Clone)]
pub(super) enum ReadinessChoice {
FromConfig,
Disabled,
Owned,
Shared(SharedReadiness),
}
#[derive(Clone)]
pub(super) enum FileRingChoice {
FromConfig,
Disabled,
Owned,
Shared(SharedIoRing),
}
#[derive(Clone)]
pub(super) enum StandardRingChoice {
FromConfig,
Disabled,
Owned,
}
#[derive(Clone)]
pub(super) enum GenericRingChoice {
FromConfig,
Disabled,
Owned(RingConfig),
Shared(SharedIoRing),
}
#[derive(Clone)]
pub(super) enum DistributionChoice {
FromConfig,
Disabled,
Owned(DistributionConfig),
}
#[derive(Clone)]
pub struct SharedIoRing {
service: &'static str,
config: RingConfig,
}
impl std::fmt::Debug for SharedIoRing {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SharedIoRing")
.field("service", &self.service)
.finish_non_exhaustive()
}
}
impl SharedIoRing {
#[must_use]
pub fn file(config: RingConfig) -> Self {
Self {
service: super::inventory::FILE_IO_RING,
config,
}
}
#[must_use]
pub fn generic(config: RingConfig) -> Self {
Self {
service: super::inventory::GENERIC_IO_RING,
config,
}
}
pub(super) fn service(&self) -> &'static str {
self.service
}
#[must_use]
pub fn config(&self) -> RingConfig {
self.config
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum WithServicesError {
SharedRingRoutingDeferred {
service: &'static str,
},
SharedRingKindMismatch {
slot: &'static str,
handle: &'static str,
},
}
impl std::fmt::Display for WithServicesError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SharedRingRoutingDeferred { service } => write!(
f,
"shared {service} injection is refused this release: cross-scheduler \
completion routing lands with the §3.9 routing gate in commit 6"
),
Self::SharedRingKindMismatch { slot, handle } => write!(
f,
"a shared-ring handle built for {handle} was passed to the {slot} \
slot; build the handle with the matching SharedIoRing constructor"
),
}
}
}
impl std::error::Error for WithServicesError {}
#[derive(Clone)]
pub struct SchedulerServices {
pub(super) dirty_cpu: DirtyChoice,
pub(super) dirty_io: DirtyChoice,
pub(super) file_io: FileRingChoice,
pub(super) standard_io: StandardRingChoice,
pub(super) generic_io: GenericRingChoice,
pub(super) distribution: DistributionChoice,
#[cfg(feature = "readiness")]
pub(super) readiness: ReadinessChoice,
}
impl SchedulerServices {
#[must_use]
pub fn from_config() -> Self {
Self {
dirty_cpu: DirtyChoice::FromConfig,
dirty_io: DirtyChoice::FromConfig,
file_io: FileRingChoice::FromConfig,
standard_io: StandardRingChoice::FromConfig,
generic_io: GenericRingChoice::FromConfig,
distribution: DistributionChoice::FromConfig,
#[cfg(feature = "readiness")]
readiness: ReadinessChoice::FromConfig,
}
}
#[must_use]
pub fn full_runtime() -> Self {
Self {
distribution: DistributionChoice::Owned(DistributionConfig::default()),
#[cfg(feature = "readiness")]
readiness: ReadinessChoice::Owned,
..Self::from_config()
}
}
#[must_use]
pub fn minimal() -> Self {
Self {
dirty_cpu: DirtyChoice::Disabled,
dirty_io: DirtyChoice::Disabled,
file_io: FileRingChoice::Disabled,
standard_io: StandardRingChoice::Disabled,
generic_io: GenericRingChoice::Disabled,
distribution: DistributionChoice::Disabled,
#[cfg(feature = "readiness")]
readiness: ReadinessChoice::Disabled,
}
}
#[must_use]
pub fn disable_dirty_cpu(mut self) -> Self {
self.dirty_cpu = DirtyChoice::Disabled;
self
}
#[must_use]
pub fn owned_dirty_cpu(mut self, workers: usize) -> Self {
self.dirty_cpu = DirtyChoice::Owned(workers);
self
}
#[must_use]
pub fn shared_dirty_cpu(mut self, pool: Arc<DirtyPool>) -> Self {
self.dirty_cpu = DirtyChoice::Shared(pool);
self
}
#[must_use]
pub fn disable_dirty_io(mut self) -> Self {
self.dirty_io = DirtyChoice::Disabled;
self
}
#[must_use]
pub fn owned_dirty_io(mut self, workers: usize) -> Self {
self.dirty_io = DirtyChoice::Owned(workers);
self
}
#[must_use]
pub fn shared_dirty_io(mut self, pool: Arc<DirtyPool>) -> Self {
self.dirty_io = DirtyChoice::Shared(pool);
self
}
#[must_use]
pub fn disable_file_io(mut self) -> Self {
self.file_io = FileRingChoice::Disabled;
self
}
#[must_use]
pub fn owned_file_io(mut self) -> Self {
self.file_io = FileRingChoice::Owned;
self
}
#[must_use]
pub fn shared_file_io(mut self, ring: SharedIoRing) -> Self {
self.file_io = FileRingChoice::Shared(ring);
self
}
#[must_use]
pub fn disable_standard_io(mut self) -> Self {
self.standard_io = StandardRingChoice::Disabled;
self
}
#[must_use]
pub fn owned_standard_io(mut self) -> Self {
self.standard_io = StandardRingChoice::Owned;
self
}
#[must_use]
pub fn disable_generic_io(mut self) -> Self {
self.generic_io = GenericRingChoice::Disabled;
self
}
#[must_use]
pub fn owned_generic_io(mut self, config: RingConfig) -> Self {
self.generic_io = GenericRingChoice::Owned(config);
self
}
#[must_use]
pub fn shared_generic_io(mut self, ring: SharedIoRing) -> Self {
self.generic_io = GenericRingChoice::Shared(ring);
self
}
#[must_use]
pub fn disable_distribution(mut self) -> Self {
self.distribution = DistributionChoice::Disabled;
self
}
#[must_use]
pub fn owned_distribution(mut self, config: DistributionConfig) -> Self {
self.distribution = DistributionChoice::Owned(config);
self
}
#[cfg(feature = "readiness")]
#[must_use]
pub fn disable_readiness(mut self) -> Self {
self.readiness = ReadinessChoice::Disabled;
self
}
#[cfg(feature = "readiness")]
#[must_use]
pub fn owned_readiness(mut self) -> Self {
self.readiness = ReadinessChoice::Owned;
self
}
#[cfg(feature = "readiness")]
#[must_use]
pub fn shared_readiness(mut self, service: SharedReadiness) -> Self {
self.readiness = ReadinessChoice::Shared(service);
self
}
pub fn validate(&self) -> Result<(), WithServicesError> {
if let FileRingChoice::Shared(ring) = &self.file_io {
if ring.service() != super::inventory::FILE_IO_RING {
return Err(WithServicesError::SharedRingKindMismatch {
slot: super::inventory::FILE_IO_RING,
handle: ring.service(),
});
}
return Err(WithServicesError::SharedRingRoutingDeferred {
service: super::inventory::FILE_IO_RING,
});
}
if let GenericRingChoice::Shared(ring) = &self.generic_io {
if ring.service() != super::inventory::GENERIC_IO_RING {
return Err(WithServicesError::SharedRingKindMismatch {
slot: super::inventory::GENERIC_IO_RING,
handle: ring.service(),
});
}
return Err(WithServicesError::SharedRingRoutingDeferred {
service: super::inventory::GENERIC_IO_RING,
});
}
Ok(())
}
}
impl Default for SchedulerServices {
fn default() -> Self {
Self::from_config()
}
}