use super::{
RangeIndexInconsistency, RangeIndexInsertError, RangeIndexMoveError, RangeIndexRemoveError,
SecondaryIndexInconsistency, SecondaryIndexInsertError, SecondaryIndexMoveError,
SecondaryIndexRemoveError, StableSlotInsertError,
};
use crate::storage::warp_table::query::SelectionMembershipInconsistency;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum StableMembershipInsertFailure {
Full {
maximum_rows: usize,
},
Inconsistent {
reason: SelectionMembershipInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SecondaryIndexInsertFailure<SecondaryKey> {
AlreadyPresent {
secondary_key: SecondaryKey,
},
Full {
secondary_key: SecondaryKey,
maximum_distinct_keys: usize,
},
Inconsistent {
secondary_key: SecondaryKey,
reason: SecondaryIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SecondaryIndexRemoveFailure<SecondaryKey> {
Inconsistent {
secondary_key: SecondaryKey,
reason: SecondaryIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SecondaryIndexMoveFailure<SecondaryKey> {
SourceBucketAbsent {
source: SecondaryKey,
target: SecondaryKey,
},
SourceMembershipAbsent {
source: SecondaryKey,
target: SecondaryKey,
},
TargetMembershipAlreadyPresent {
source: SecondaryKey,
target: SecondaryKey,
},
Full {
source: SecondaryKey,
target: SecondaryKey,
maximum_distinct_keys: usize,
},
Inconsistent {
source: SecondaryKey,
target: SecondaryKey,
reason: SecondaryIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RangeIndexInsertFailure<Key> {
Full {
key: Key,
maximum_rows: usize,
},
AlreadyPresent {
key: Key,
},
OrderedWordOutsideWidth {
key: Key,
ordered_word: u64,
bits: u32,
},
Inconsistent {
key: Key,
reason: RangeIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RangeIndexRemoveFailure<Key> {
OrderedWordOutsideWidth {
key: Key,
ordered_word: u64,
bits: u32,
},
Inconsistent {
key: Key,
reason: RangeIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RangeIndexMoveFailure<Key> {
SourceOrderedWordOutsideWidth {
source: Key,
target: Key,
ordered_word: u64,
bits: u32,
},
TargetOrderedWordOutsideWidth {
source: Key,
target: Key,
ordered_word: u64,
bits: u32,
},
Inconsistent {
source: Key,
target: Key,
reason: RangeIndexInconsistency,
},
}
impl From<StableSlotInsertError> for StableMembershipInsertFailure {
fn from(reason: StableSlotInsertError) -> Self {
match reason {
StableSlotInsertError::Full { maximum_rows } => Self::Full { maximum_rows },
StableSlotInsertError::Inconsistent { reason } => Self::Inconsistent {
reason: reason.into(),
},
}
}
}
impl<SecondaryKey> From<SecondaryIndexInsertError<SecondaryKey>>
for SecondaryIndexInsertFailure<SecondaryKey>
{
fn from(reason: SecondaryIndexInsertError<SecondaryKey>) -> Self {
match reason {
SecondaryIndexInsertError::AlreadyPresent { secondary_key, .. } => {
Self::AlreadyPresent { secondary_key }
}
SecondaryIndexInsertError::Full {
secondary_key,
maximum_distinct_keys,
..
} => Self::Full {
secondary_key,
maximum_distinct_keys,
},
SecondaryIndexInsertError::Inconsistent {
secondary_key,
reason,
..
} => Self::Inconsistent {
secondary_key,
reason,
},
}
}
}
impl<SecondaryKey> From<SecondaryIndexRemoveError<SecondaryKey>>
for SecondaryIndexRemoveFailure<SecondaryKey>
{
fn from(reason: SecondaryIndexRemoveError<SecondaryKey>) -> Self {
match reason {
SecondaryIndexRemoveError::Inconsistent {
secondary_key,
reason,
..
} => Self::Inconsistent {
secondary_key,
reason,
},
}
}
}
impl<SecondaryKey> From<SecondaryIndexMoveError<SecondaryKey>>
for SecondaryIndexMoveFailure<SecondaryKey>
{
fn from(reason: SecondaryIndexMoveError<SecondaryKey>) -> Self {
match reason {
SecondaryIndexMoveError::SourceBucketAbsent { source, target, .. } => {
Self::SourceBucketAbsent { source, target }
}
SecondaryIndexMoveError::SourceSlotAbsent { source, target, .. } => {
Self::SourceMembershipAbsent { source, target }
}
SecondaryIndexMoveError::TargetSlotAlreadyPresent { source, target, .. } => {
Self::TargetMembershipAlreadyPresent { source, target }
}
SecondaryIndexMoveError::Full {
source,
target,
maximum_distinct_keys,
..
} => Self::Full {
source,
target,
maximum_distinct_keys,
},
SecondaryIndexMoveError::Inconsistent {
source,
target,
reason,
..
} => Self::Inconsistent {
source,
target,
reason,
},
}
}
}
impl<Key> From<RangeIndexInsertError<Key>> for RangeIndexInsertFailure<Key> {
fn from(reason: RangeIndexInsertError<Key>) -> Self {
match reason {
RangeIndexInsertError::Full {
key, maximum_rows, ..
} => Self::Full { key, maximum_rows },
RangeIndexInsertError::AlreadyPresent { key, .. } => Self::AlreadyPresent { key },
RangeIndexInsertError::OrderedWordOutsideWidth {
key,
ordered_word,
bits,
} => Self::OrderedWordOutsideWidth {
key,
ordered_word,
bits,
},
RangeIndexInsertError::Inconsistent { key, reason, .. } => {
Self::Inconsistent { key, reason }
}
}
}
}
impl<Key> From<RangeIndexRemoveError<Key>> for RangeIndexRemoveFailure<Key> {
fn from(reason: RangeIndexRemoveError<Key>) -> Self {
match reason {
RangeIndexRemoveError::OrderedWordOutsideWidth {
key,
ordered_word,
bits,
} => Self::OrderedWordOutsideWidth {
key,
ordered_word,
bits,
},
RangeIndexRemoveError::Inconsistent { key, reason, .. } => {
Self::Inconsistent { key, reason }
}
}
}
}
impl<Key> From<RangeIndexMoveError<Key>> for RangeIndexMoveFailure<Key> {
fn from(reason: RangeIndexMoveError<Key>) -> Self {
match reason {
RangeIndexMoveError::SourceOrderedWordOutsideWidth {
source,
target,
ordered_word,
bits,
} => Self::SourceOrderedWordOutsideWidth {
source,
target,
ordered_word,
bits,
},
RangeIndexMoveError::TargetOrderedWordOutsideWidth {
source,
target,
ordered_word,
bits,
} => Self::TargetOrderedWordOutsideWidth {
source,
target,
ordered_word,
bits,
},
RangeIndexMoveError::Inconsistent {
source,
target,
reason,
..
} => Self::Inconsistent {
source,
target,
reason,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::storage::warp_table::secondary_index::{StableSlot, StableSlotsInconsistency};
const SLOT: StableSlot = StableSlot::new(7);
const INCONSISTENCY: SecondaryIndexInconsistency =
SecondaryIndexInconsistency::SlotSetUnavailable { row: 3 };
const RANGE_INCONSISTENCY: RangeIndexInconsistency = RangeIndexInconsistency::MemberAbsent;
#[test]
fn stable_membership_failures_hide_slots_without_losing_the_reason() {
assert_eq!(
StableMembershipInsertFailure::from(StableSlotInsertError::Full { maximum_rows: 5 }),
StableMembershipInsertFailure::Full { maximum_rows: 5 }
);
assert_eq!(
StableMembershipInsertFailure::from(StableSlotInsertError::Inconsistent {
reason: StableSlotsInconsistency::SlotUnavailable { slot: SLOT },
}),
StableMembershipInsertFailure::Inconsistent {
reason: SelectionMembershipInconsistency::MembershipUnavailable,
}
);
}
#[test]
fn secondary_insert_and_remove_failures_retain_public_facts() {
for (source, expected) in [
(
SecondaryIndexInsertError::AlreadyPresent {
secondary_key: 2_u8,
slot: SLOT,
},
SecondaryIndexInsertFailure::AlreadyPresent { secondary_key: 2 },
),
(
SecondaryIndexInsertError::Full {
secondary_key: 2,
slot: SLOT,
maximum_distinct_keys: 5,
},
SecondaryIndexInsertFailure::Full {
secondary_key: 2,
maximum_distinct_keys: 5,
},
),
(
SecondaryIndexInsertError::Inconsistent {
secondary_key: 2,
slot: SLOT,
reason: INCONSISTENCY,
},
SecondaryIndexInsertFailure::Inconsistent {
secondary_key: 2,
reason: INCONSISTENCY,
},
),
] {
assert_eq!(SecondaryIndexInsertFailure::from(source), expected);
}
assert_eq!(
SecondaryIndexRemoveFailure::from(SecondaryIndexRemoveError::Inconsistent {
secondary_key: 2_u8,
slot: SLOT,
reason: INCONSISTENCY,
}),
SecondaryIndexRemoveFailure::Inconsistent {
secondary_key: 2,
reason: INCONSISTENCY,
}
);
}
#[test]
fn secondary_move_failures_retain_keys_capacity_and_reason() {
let failures = [
SecondaryIndexMoveFailure::from(SecondaryIndexMoveError::SourceBucketAbsent {
source: 1_u8,
target: 2,
slot: SLOT,
}),
SecondaryIndexMoveFailure::from(SecondaryIndexMoveError::SourceSlotAbsent {
source: 1,
target: 2,
slot: SLOT,
}),
SecondaryIndexMoveFailure::from(SecondaryIndexMoveError::TargetSlotAlreadyPresent {
source: 1,
target: 2,
slot: SLOT,
}),
SecondaryIndexMoveFailure::from(SecondaryIndexMoveError::Full {
source: 1,
target: 2,
slot: SLOT,
maximum_distinct_keys: 5,
}),
SecondaryIndexMoveFailure::from(SecondaryIndexMoveError::Inconsistent {
source: 1,
target: 2,
slot: SLOT,
reason: INCONSISTENCY,
}),
];
assert_eq!(
failures,
[
SecondaryIndexMoveFailure::SourceBucketAbsent {
source: 1,
target: 2
},
SecondaryIndexMoveFailure::SourceMembershipAbsent {
source: 1,
target: 2
},
SecondaryIndexMoveFailure::TargetMembershipAlreadyPresent {
source: 1,
target: 2,
},
SecondaryIndexMoveFailure::Full {
source: 1,
target: 2,
maximum_distinct_keys: 5,
},
SecondaryIndexMoveFailure::Inconsistent {
source: 1,
target: 2,
reason: INCONSISTENCY,
},
]
);
}
#[test]
fn range_insert_and_remove_failures_hide_slots_without_losing_public_facts() {
let insert_failures = [
RangeIndexInsertFailure::from(RangeIndexInsertError::Full {
key: 2_u8,
slot: SLOT,
maximum_rows: 5,
}),
RangeIndexInsertFailure::from(RangeIndexInsertError::AlreadyPresent {
key: 2,
slot: SLOT,
}),
RangeIndexInsertFailure::from(RangeIndexInsertError::OrderedWordOutsideWidth {
key: 2,
ordered_word: 258,
bits: 8,
}),
RangeIndexInsertFailure::from(RangeIndexInsertError::Inconsistent {
key: 2,
slot: SLOT,
reason: RANGE_INCONSISTENCY,
}),
];
assert_eq!(
insert_failures,
[
RangeIndexInsertFailure::Full {
key: 2,
maximum_rows: 5,
},
RangeIndexInsertFailure::AlreadyPresent { key: 2 },
RangeIndexInsertFailure::OrderedWordOutsideWidth {
key: 2,
ordered_word: 258,
bits: 8,
},
RangeIndexInsertFailure::Inconsistent {
key: 2,
reason: RANGE_INCONSISTENCY,
},
]
);
assert_eq!(
RangeIndexRemoveFailure::from(RangeIndexRemoveError::OrderedWordOutsideWidth {
key: 2_u8,
ordered_word: 258,
bits: 8,
}),
RangeIndexRemoveFailure::OrderedWordOutsideWidth {
key: 2,
ordered_word: 258,
bits: 8,
}
);
assert_eq!(
RangeIndexRemoveFailure::from(RangeIndexRemoveError::Inconsistent {
key: 2_u8,
slot: SLOT,
reason: RANGE_INCONSISTENCY,
}),
RangeIndexRemoveFailure::Inconsistent {
key: 2,
reason: RANGE_INCONSISTENCY,
}
);
}
#[test]
fn range_move_failures_retain_endpoints_word_width_and_reason() {
let failures = [
RangeIndexMoveFailure::from(RangeIndexMoveError::SourceOrderedWordOutsideWidth {
source: 1_u8,
target: 2,
ordered_word: 257,
bits: 8,
}),
RangeIndexMoveFailure::from(RangeIndexMoveError::TargetOrderedWordOutsideWidth {
source: 1,
target: 2,
ordered_word: 258,
bits: 8,
}),
RangeIndexMoveFailure::from(RangeIndexMoveError::Inconsistent {
source: 1,
target: 2,
slot: SLOT,
reason: RANGE_INCONSISTENCY,
}),
];
assert_eq!(
failures,
[
RangeIndexMoveFailure::SourceOrderedWordOutsideWidth {
source: 1,
target: 2,
ordered_word: 257,
bits: 8,
},
RangeIndexMoveFailure::TargetOrderedWordOutsideWidth {
source: 1,
target: 2,
ordered_word: 258,
bits: 8,
},
RangeIndexMoveFailure::Inconsistent {
source: 1,
target: 2,
reason: RANGE_INCONSISTENCY,
},
]
);
}
}