use super::*;
use eredu_core::execution_control::SnapshotEstimate;
use std::sync::Arc;
pub trait ReplicatedTextSnapshotMechanisms<A, B>: ReplicatedTextSessionMechanisms<A, B>
where
B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
A: LayeredArchitecture<B, Self::State>,
Self::State: RuntimeState<B>,
Self::ResidentPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>,
Self::BoundedPolicy: LayerwisePolicy<B, A::Unit, Error = Self::PolicyError>,
{
fn estimate_snapshot_state(&self, state: &Self::State) -> Option<SnapshotEstimate>;
fn estimate_snapshot_growth(
&self,
_state: &Self::State,
_additional_input_tokens: u64,
) -> Option<u64> {
None
}
fn copy_snapshot_state(
&mut self,
state: &Self::State,
context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
) -> Result<Self::State, Self::Error>;
}
pub struct ReplicatedTextControlState<S> {
owner: Arc<()>,
state: S,
prompt_input_identity: Option<PreparedInputCacheIdentity>,
next_commit_epoch: DistributedCommitEpoch,
last_commit_outcome: Option<DistributedCommitOutcome>,
}
impl<A, B, M, D> ReplicatedTextSession<A, B, M, D>
where
B: SubmissionBackend<Executor = <<B as NeuralBackend>::Tensor as Tensor>::Context>,
M: ReplicatedTextSnapshotMechanisms<A, B>,
A: LayeredArchitecture<B, M::State>,
D: ReplicatedTextExecutionStrategy<A, B, M::State, M::ResidentPolicy, M::BoundedPolicy>,
A::Error: std::fmt::Display,
M::PolicyError: std::fmt::Display,
M::Error: std::fmt::Display,
{
pub fn estimate_control_state(&self) -> Option<SnapshotEstimate> {
self.estimate_control_state_parts(
&self.state,
self.committed_prompt_input_identity.as_ref(),
)
}
pub fn estimate_control_state_copy(
&self,
saved: &ReplicatedTextControlState<M::State>,
) -> Result<
Option<SnapshotEstimate>,
ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>,
> {
self.validate_control_state(saved)?;
Ok(self.estimate_control_state_parts(&saved.state, saved.prompt_input_identity.as_ref()))
}
pub fn estimate_control_state_growth(
&self,
saved: &ReplicatedTextControlState<M::State>,
additional_input_tokens: u64,
) -> Result<Option<u64>, ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>> {
self.validate_control_state(saved)?;
Ok(self
.mechanisms
.estimate_snapshot_growth(&saved.state, additional_input_tokens))
}
fn estimate_control_state_parts(
&self,
state: &M::State,
input: Option<&PreparedInputCacheIdentity>,
) -> Option<SnapshotEstimate> {
let native = self.mechanisms.estimate_snapshot_state(state)?;
let metadata = u64::try_from(std::mem::size_of::<ReplicatedTextControlState<()>>())
.ok()?
.checked_add(match input {
Some(input) => input.logical_metadata_bytes()?,
None => 0,
})?;
Some(SnapshotEstimate {
retained_bytes: native.retained_bytes.checked_add(metadata)?,
copy_bytes: native.copy_bytes.checked_add(metadata)?,
})
}
pub fn capture_control_state(
&mut self,
context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
) -> Result<
ReplicatedTextControlState<M::State>,
ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>,
> {
self.ensure_commit_resolved()?;
let state = self
.mechanisms
.copy_snapshot_state(&self.state, context)
.map_err(ReplicatedTextSessionError::Mechanism)?;
self.validate_control_geometry(&state)?;
Ok(ReplicatedTextControlState {
owner: Arc::clone(&self.control_identity),
state,
prompt_input_identity: self.committed_prompt_input_identity.clone(),
next_commit_epoch: self.next_commit_epoch,
last_commit_outcome: self.last_commit_outcome,
})
}
pub fn copy_control_state(
&mut self,
saved: &ReplicatedTextControlState<M::State>,
context: &<<B as NeuralBackend>::Tensor as Tensor>::Context,
) -> Result<
ReplicatedTextControlState<M::State>,
ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>,
> {
self.validate_control_state(saved)?;
let state = self
.mechanisms
.copy_snapshot_state(&saved.state, context)
.map_err(ReplicatedTextSessionError::Mechanism)?;
self.validate_control_geometry(&state)?;
Ok(ReplicatedTextControlState {
owner: Arc::clone(&self.control_identity),
state,
prompt_input_identity: saved.prompt_input_identity.clone(),
next_commit_epoch: saved.next_commit_epoch,
last_commit_outcome: saved.last_commit_outcome,
})
}
fn validate_control_geometry(
&self,
state: &M::State,
) -> Result<(), ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>> {
match self.selected_state.state() {
Some(selected) => validate_realized_state(state, selected),
None => Err(ReplicatedTextSessionError::Contract(
"ordinary control requires a selected stateful text execution".into(),
)),
}
}
pub fn validate_control_state(
&self,
saved: &ReplicatedTextControlState<M::State>,
) -> Result<(), ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>> {
self.ensure_commit_resolved()?;
if !Arc::ptr_eq(&self.control_identity, &saved.owner) {
return Err(ReplicatedTextSessionError::Contract(
"control state belongs to a different executable".into(),
));
}
self.validate_control_geometry(&saved.state)
}
pub fn exchange_control_state(
&mut self,
slot: &mut ReplicatedTextControlState<M::State>,
) -> Result<(), ReplicatedTextSessionError<A::Error, M::PolicyError, M::Error>> {
self.validate_control_state(slot)?;
std::mem::swap(&mut self.state, &mut slot.state);
std::mem::swap(
&mut self.committed_prompt_input_identity,
&mut slot.prompt_input_identity,
);
std::mem::swap(&mut self.next_commit_epoch, &mut slot.next_commit_epoch);
std::mem::swap(&mut self.last_commit_outcome, &mut slot.last_commit_outcome);
Ok(())
}
}