///|
/// A deterministic preflight for a pattern of present and erased shards.
/// It does not read shard bytes or make an integrity assertion.
pub struct RepairPlan {
required : Int
available : Int
selected_indices : Array[Int]
missing_data_indices : Array[Int]
missing_parity_indices : Array[Int]
}
///|
pub fn RepairPlan::required(self : RepairPlan) -> Int {
self.required
}
///|
pub fn RepairPlan::available(self : RepairPlan) -> Int {
self.available
}
///|
pub fn RepairPlan::recoverable(self : RepairPlan) -> Bool {
self.available >= self.required
}
///|
pub fn RepairPlan::minimum_additional_shards(self : RepairPlan) -> Int {
if self.recoverable() {
0
} else {
self.required - self.available
}
}
///|
pub fn RepairPlan::needs_decode(self : RepairPlan) -> Bool {
self.missing_data_indices.length() > 0
}
///|
pub fn RepairPlan::selected_indices(self : RepairPlan) -> Array[Int] {
let result : Array[Int] = []
for index in self.selected_indices {
result.push(index)
}
result
}
///|
pub fn RepairPlan::missing_data_indices(self : RepairPlan) -> Array[Int] {
let result : Array[Int] = []
for index in self.missing_data_indices {
result.push(index)
}
result
}
///|
pub fn RepairPlan::missing_parity_indices(self : RepairPlan) -> Array[Int] {
let result : Array[Int] = []
for index in self.missing_parity_indices {
result.push(index)
}
result
}
///|
/// Report the first `k` present shards chosen by deterministic index order.
/// Storage adapters can fetch additional shards before allocating decode work.
pub fn Codec::plan(
self : Codec,
present : Array[Bool],
) -> RepairPlan raise ErasureError {
if present.length() != self.total_count() {
raise InvalidShardCount(
expected=self.total_count(),
actual=present.length(),
)
}
let selected_indices : Array[Int] = []
let missing_data_indices : Array[Int] = []
let missing_parity_indices : Array[Int] = []
let mut available = 0
for index = 0; index < present.length(); index = index + 1 {
if present[index] {
available = available + 1
if selected_indices.length() < self.data_count() {
selected_indices.push(index)
}
} else if index < self.data_count() {
missing_data_indices.push(index)
} else {
missing_parity_indices.push(index)
}
}
{
required: self.data_count(),
available,
selected_indices,
missing_data_indices,
missing_parity_indices,
}
}