use std::sync::Arc;
use super::identity::validate_identifier;
use super::{EngineId, HardwareClassId, IdentityError, IdentityKind, PlacementConstraintError};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Determinism {
Fast,
Reproducible,
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct StorageClass(Arc<str>);
impl StorageClass {
pub fn new(value: impl Into<Arc<str>>) -> Result<Self, IdentityError> {
validate_identifier(value.into(), IdentityKind::StorageClass).map(Self)
}
pub fn as_str(&self) -> &str {
&self.0
}
pub(crate) fn runtime_created(value: impl Into<Arc<str>>) -> Self {
Self(value.into())
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct TransferEndpoint {
engine_id: EngineId,
storage_class: StorageClass,
}
impl TransferEndpoint {
pub fn new(engine_id: EngineId, storage_class: StorageClass) -> Self {
Self {
engine_id,
storage_class,
}
}
pub fn engine_id(&self) -> &EngineId {
&self.engine_id
}
pub fn storage_class(&self) -> &StorageClass {
&self.storage_class
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct LayoutClass(Arc<str>);
impl LayoutClass {
pub fn new(value: impl Into<Arc<str>>) -> Result<Self, IdentityError> {
validate_identifier(value.into(), IdentityKind::LayoutClass).map(Self)
}
pub fn as_str(&self) -> &str {
&self.0
}
pub(crate) fn runtime_created(value: impl Into<Arc<str>>) -> Self {
Self(value.into())
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ProgramPlacementConstraint {
allowed_engines: Arc<[EngineId]>,
storage_class: Option<StorageClass>,
}
impl ProgramPlacementConstraint {
pub fn any() -> Self {
Self {
allowed_engines: Arc::from(Vec::<EngineId>::new()),
storage_class: None,
}
}
pub fn new(
allowed_engines: impl Into<Arc<[EngineId]>>,
storage_class: Option<StorageClass>,
) -> Result<Self, PlacementConstraintError> {
let allowed_engines = allowed_engines.into();
for duplicate_index in 0..allowed_engines.len() {
if let Some(first_index) = (0..duplicate_index).find(|&first_index| {
allowed_engines[first_index] == allowed_engines[duplicate_index]
}) {
return Err(PlacementConstraintError::DuplicateEngine {
engine_id: allowed_engines[duplicate_index].clone(),
first_index,
duplicate_index,
});
}
}
Ok(Self {
allowed_engines,
storage_class,
})
}
pub fn allowed_engines(&self) -> &[EngineId] {
&self.allowed_engines
}
pub fn storage_class(&self) -> Option<&StorageClass> {
self.storage_class.as_ref()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ResolvedProgramPlacement {
engine_id: EngineId,
storage_class: StorageClass,
}
impl ResolvedProgramPlacement {
#[allow(dead_code)]
pub(crate) fn new(engine_id: EngineId, storage_class: StorageClass) -> Self {
Self {
engine_id,
storage_class,
}
}
pub fn engine_id(&self) -> &EngineId {
&self.engine_id
}
pub fn storage_class(&self) -> &StorageClass {
&self.storage_class
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum CacheInFlightBehavior {
#[default]
Wait,
Refuse,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ExecutionPolicy {
determinism: Determinism,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
}
impl ExecutionPolicy {
pub fn new(
determinism: Determinism,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
) -> Self {
Self {
determinism,
hard_workspace_limit_bytes,
planning_seed,
}
}
pub fn determinism(&self) -> Determinism {
self.determinism
}
pub fn hard_workspace_limit_bytes(&self) -> Option<usize> {
self.hard_workspace_limit_bytes
}
pub fn planning_seed(&self) -> u64 {
self.planning_seed
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PrepareOptions {
placement: Option<ProgramPlacementConstraint>,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: Option<u64>,
cache_in_flight: CacheInFlightBehavior,
}
impl PrepareOptions {
pub fn new() -> Self {
Self::default()
}
pub fn with_placement(mut self, placement: ProgramPlacementConstraint) -> Self {
self.placement = Some(placement);
self
}
pub fn with_hard_workspace_limit_bytes(mut self, limit: Option<usize>) -> Self {
self.hard_workspace_limit_bytes = limit;
self
}
pub fn with_planning_seed(mut self, seed: u64) -> Self {
self.planning_seed = Some(seed);
self
}
pub fn with_cache_in_flight(mut self, behavior: CacheInFlightBehavior) -> Self {
self.cache_in_flight = behavior;
self
}
pub fn placement(&self) -> Option<&ProgramPlacementConstraint> {
self.placement.as_ref()
}
pub fn hard_workspace_limit_bytes(&self) -> Option<usize> {
self.hard_workspace_limit_bytes
}
pub fn planning_seed(&self) -> Option<u64> {
self.planning_seed
}
pub fn cache_in_flight(&self) -> CacheInFlightBehavior {
self.cache_in_flight
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PrepareOptionsKey {
resolved_placement: ResolvedProgramPlacement,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
}
impl PrepareOptionsKey {
#[allow(dead_code)]
pub(crate) fn from_resolved(
resolved_placement: ResolvedProgramPlacement,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
) -> Self {
Self {
resolved_placement,
hard_workspace_limit_bytes,
planning_seed,
}
}
pub fn resolved_placement(&self) -> &ResolvedProgramPlacement {
&self.resolved_placement
}
pub fn hard_workspace_limit_bytes(&self) -> Option<usize> {
self.hard_workspace_limit_bytes
}
pub fn planning_seed(&self) -> u64 {
self.planning_seed
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ResolvedPlanningConfig {
determinism: Determinism,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
hardware_class: HardwareClassId,
}
impl ResolvedPlanningConfig {
pub fn resolve(
policy: &ExecutionPolicy,
options: &PrepareOptions,
hardware_class: HardwareClassId,
) -> Self {
Self {
determinism: policy.determinism(),
hard_workspace_limit_bytes: options
.hard_workspace_limit_bytes()
.or(policy.hard_workspace_limit_bytes()),
planning_seed: options.planning_seed().unwrap_or(policy.planning_seed()),
hardware_class,
}
}
pub fn determinism(&self) -> Determinism {
self.determinism
}
pub fn hard_workspace_limit_bytes(&self) -> Option<usize> {
self.hard_workspace_limit_bytes
}
pub fn planning_seed(&self) -> u64 {
self.planning_seed
}
pub fn hardware_class(&self) -> &HardwareClassId {
&self.hardware_class
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ResolvedPlanningKey {
determinism: Determinism,
hard_workspace_limit_bytes: Option<usize>,
planning_seed: u64,
hardware_class: HardwareClassId,
}
impl ResolvedPlanningKey {
#[allow(dead_code)]
pub(crate) fn from_config(config: &ResolvedPlanningConfig) -> Self {
Self {
determinism: config.determinism(),
hard_workspace_limit_bytes: config.hard_workspace_limit_bytes(),
planning_seed: config.planning_seed(),
hardware_class: config.hardware_class().clone(),
}
}
pub fn determinism(&self) -> Determinism {
self.determinism
}
pub fn hard_workspace_limit_bytes(&self) -> Option<usize> {
self.hard_workspace_limit_bytes
}
pub fn planning_seed(&self) -> u64 {
self.planning_seed
}
pub fn hardware_class(&self) -> &HardwareClassId {
&self.hardware_class
}
}