use uqa_core::memory::BudgetedVec;
use crate::mvcc::overlay::run::SpilledRunWriter;
use crate::mvcc::{PrivateRecordRevision, VersionResult};
use crate::read_control::StorageReadControl;
use super::{PreparedRecordCommit, PreparedRecordWrite};
enum Target {
Resident(BudgetedVec<PreparedRecordWrite>),
Spilled {
writer: Box<SpilledRunWriter>,
identity: PrivateRecordRevision,
},
}
pub(in crate::mvcc) struct PreparedWritesBuilder {
target: Target,
}
impl PreparedWritesBuilder {
pub(in crate::mvcc) fn like(
original: &PreparedRecordCommit,
control: &StorageReadControl,
) -> VersionResult<Self> {
let target = match &original.writes {
super::writes::PreparedWrites::Resident(writes) => {
let mut derived = BudgetedVec::new(control.memory());
derived.reserve(writes.len())?;
Target::Resident(derived)
}
super::writes::PreparedWrites::Spilled(run) => Target::Spilled {
writer: Box::new(SpilledRunWriter::new(
run.len(),
run.entry_bytes(),
control.memory(),
)?),
identity: PrivateRecordRevision::allocate()?,
},
};
Ok(Self { target })
}
pub(in crate::mvcc) fn push(
&mut self,
write: PreparedRecordWrite,
control: &StorageReadControl,
) -> VersionResult<()> {
match &mut self.target {
Target::Resident(writes) => writes.push(write).map_err(Into::into),
Target::Spilled { writer, identity } => writer.push(
write.key(),
write.expected(),
write.kind(),
*identity,
write.value(),
control,
),
}
}
pub(in crate::mvcc) fn finish(
self,
control: &StorageReadControl,
) -> VersionResult<PreparedRecordCommit> {
match self.target {
Target::Resident(writes) => PreparedRecordCommit::from_unique_owned(writes, control),
Target::Spilled { writer, .. } => match writer.finish()? {
Some(run) => PreparedRecordCommit::from_spilled_run(run, control),
None => PreparedRecordCommit::from_unique_owned(
BudgetedVec::new(control.memory()),
control,
),
},
}
}
}