Skip to main content

ferrum_interfaces/vnext/execution/sequence_checkpoint/
ranges.rs

1use std::collections::BTreeMap;
2use std::ops::Range;
3
4use super::*;
5use crate::vnext::{CheckpointBackingRequest, CheckpointBackingRequests};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
8pub struct SequenceCheckpointCopyRange {
9    source: Range<u64>,
10    checkpoint_offset: u64,
11}
12
13impl SequenceCheckpointCopyRange {
14    pub fn source(&self) -> Range<u64> {
15        self.source.clone()
16    }
17    pub fn checkpoint_offset(&self) -> u64 {
18        self.checkpoint_offset
19    }
20    pub fn length_bytes(&self) -> u64 {
21        self.source.end - self.source.start
22    }
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
26pub struct SequenceCheckpointResourceRanges {
27    resource_id: ResourceId,
28    logical_bytes: u64,
29    ranges: Vec<SequenceCheckpointCopyRange>,
30}
31
32impl SequenceCheckpointResourceRanges {
33    pub fn resource_id(&self) -> &ResourceId {
34        &self.resource_id
35    }
36    pub fn logical_bytes(&self) -> u64 {
37        self.logical_bytes
38    }
39    pub fn ranges(&self) -> &[SequenceCheckpointCopyRange] {
40        &self.ranges
41    }
42}
43
44/// Compact bytes to allocate and copy, derived from a trusted layout. Source
45/// ranges must still be checked against the actual session backing under its
46/// state-transfer guard. This is not a completed-boundary or submit authority.
47#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
48pub struct SequenceCheckpointBytePlan {
49    plan_hash: PlanHash,
50    layout_fingerprint: String,
51    boundary: u64,
52    logical_bytes: u64,
53    resources: Vec<SequenceCheckpointResourceRanges>,
54}
55
56impl SequenceCheckpointBytePlan {
57    pub fn plan_hash(&self) -> &PlanHash {
58        &self.plan_hash
59    }
60    pub fn layout_fingerprint(&self) -> &str {
61        &self.layout_fingerprint
62    }
63    pub fn boundary(&self) -> u64 {
64        self.boundary
65    }
66    pub fn logical_bytes(&self) -> u64 {
67        self.logical_bytes
68    }
69    pub fn resources(&self) -> &[SequenceCheckpointResourceRanges] {
70        &self.resources
71    }
72
73    pub(crate) fn backing_requests(&self) -> Result<CheckpointBackingRequests, VNextError> {
74        CheckpointBackingRequests::new(
75            self.plan_hash.clone(),
76            self.resources
77                .iter()
78                .map(|resource| {
79                    CheckpointBackingRequest::new(
80                        resource.resource_id.clone(),
81                        resource.logical_bytes,
82                    )
83                })
84                .collect::<Result<Vec<_>, _>>()?,
85        )
86    }
87}
88
89impl SequenceCheckpointState {
90    fn source_range(&self, boundary: u64) -> Result<Range<u64>, VNextError> {
91        let length = match self.layout {
92            ProviderCheckpointStateLayout::ContiguousBoundaryValue => {
93                self.tensor.minimum_storage_bytes()?
94            }
95            ProviderCheckpointStateLayout::TokenMajorPrefix => self
96                .tensor
97                .minimum_storage_bytes()?
98                .checked_mul(boundary)
99                .ok_or_else(|| invalid_plan("checkpoint prefix byte length overflows u64"))?,
100        };
101        let end = self
102            .offset_bytes
103            .checked_add(length)
104            .ok_or_else(|| invalid_plan("checkpoint byte end overflows u64"))?;
105        let capacity = self.descriptor.evaluate_logical_request_bytes_for_shape(
106            self.descriptor.demand().theoretical_maximum_shape(),
107        )?;
108        if length == 0 || end > capacity {
109            return Err(invalid_plan(
110                "checkpoint state range exceeds its proven resource capacity",
111            ));
112        }
113        Ok(self.offset_bytes..end)
114    }
115
116    fn maximum_source_range(&self) -> Result<Range<u64>, VNextError> {
117        match self.layout {
118            ProviderCheckpointStateLayout::ContiguousBoundaryValue => self.source_range(1),
119            ProviderCheckpointStateLayout::TokenMajorPrefix => {
120                let capacity = self.descriptor.evaluate_logical_request_bytes_for_shape(
121                    self.descriptor.demand().theoretical_maximum_shape(),
122                )?;
123                self.source_range(capacity / self.tensor.minimum_storage_bytes()?)
124            }
125        }
126    }
127}
128
129impl SequenceCheckpointLayout {
130    pub(super) fn validate_aliases(&self) -> Result<(), VNextError> {
131        let mut groups = BTreeMap::<&ResourceId, Vec<&SequenceCheckpointState>>::new();
132        for state in &self.data.states {
133            groups.entry(&state.resource_id).or_default().push(state);
134        }
135        for states in groups.values() {
136            let mut ranges = states
137                .iter()
138                .map(|state| Ok((state.maximum_source_range()?, *state)))
139                .collect::<Result<Vec<_>, VNextError>>()?;
140            ranges.sort_by_key(|(range, _)| (range.start, range.end));
141            for pair in ranges.windows(2) {
142                let (left_range, left) = &pair[0];
143                let (right_range, right) = &pair[1];
144                if left_range.end > right_range.start
145                    && !(left_range == right_range
146                        && left.tensor == right.tensor
147                        && left.layout == right.layout
148                        && left.semantics == right.semantics
149                        && left.storage == right.storage
150                        && left.initialization == right.initialization)
151                {
152                    return Err(invalid_plan(
153                        "checkpoint state aliases do not prove identical content and ABI",
154                    ));
155                }
156            }
157        }
158        Ok(())
159    }
160
161    // Only the owning ExecutionPlan entrypoint may attach a plan hash. Resource
162    // and completion code must not relabel another plan's trusted layout.
163    pub(super) fn byte_plan(
164        &self,
165        plan_hash: PlanHash,
166        boundary: u64,
167    ) -> Result<SequenceCheckpointBytePlan, VNextError> {
168        if boundary == 0 {
169            return Err(invalid_plan(
170                "checkpoint requires a positive completed boundary",
171            ));
172        }
173        let mut groups = BTreeMap::<ResourceId, Vec<Range<u64>>>::new();
174        for state in &self.data.states {
175            groups
176                .entry(state.resource_id.clone())
177                .or_default()
178                .push(state.source_range(boundary)?);
179        }
180        let mut total = 0_u64;
181        let mut resources = Vec::new();
182        for (resource_id, mut ranges) in groups {
183            ranges.sort_by_key(|range| (range.start, range.end));
184            let mut merged: Vec<Range<u64>> = Vec::new();
185            for range in ranges {
186                if let Some(previous) = merged
187                    .last_mut()
188                    .filter(|previous| range.start <= previous.end)
189                {
190                    previous.end = previous.end.max(range.end);
191                } else {
192                    merged.push(range);
193                }
194            }
195            let mut logical_bytes = 0_u64;
196            let ranges = merged
197                .into_iter()
198                .map(|source| {
199                    let checkpoint_offset = logical_bytes;
200                    logical_bytes = logical_bytes
201                        .checked_add(source.end - source.start)
202                        .ok_or_else(|| {
203                            invalid_plan("compact checkpoint resource size overflows u64")
204                        })?;
205                    Ok(SequenceCheckpointCopyRange {
206                        source,
207                        checkpoint_offset,
208                    })
209                })
210                .collect::<Result<Vec<_>, VNextError>>()?;
211            total = total
212                .checked_add(logical_bytes)
213                .ok_or_else(|| invalid_plan("checkpoint total bytes overflow u64"))?;
214            resources.push(SequenceCheckpointResourceRanges {
215                resource_id,
216                logical_bytes,
217                ranges,
218            });
219        }
220        Ok(SequenceCheckpointBytePlan {
221            plan_hash,
222            layout_fingerprint: self.fingerprint()?,
223            boundary,
224            logical_bytes: total,
225            resources,
226        })
227    }
228}