#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Holding {
Indirection,
OwnedCell,
BorrowedCell,
}
impl Holding {
pub fn owns(self) -> bool {
self != Self::BorrowedCell
}
}
pub type RecoveredRef = (
crate::UserKey,
crate::blob_tree::handle::BlobIndirection,
Holding,
);
pub fn collect_indirections(entries: &[crate::InternalValue]) -> crate::Result<Vec<RecoveredRef>> {
use crate::coding::Decode;
let mut out = Vec::new();
for entry in entries {
if entry.key.value_type == crate::ValueType::Indirection {
let mut cursor = &entry.value[..];
out.push((
entry.key.user_key.clone(),
crate::blob_tree::handle::BlobIndirection::decode_from(&mut cursor)?,
Holding::Indirection,
));
} else if entry.key.value_type == crate::ValueType::CellRow {
for (ind, owned) in crate::blob_tree::field_row::row_refs(&entry.value)? {
let holding = if owned {
Holding::OwnedCell
} else {
Holding::BorrowedCell
};
out.push((entry.key.user_key.clone(), ind, holding));
}
}
}
Ok(out)
}
pub fn fold_blob_links(
derived: &mut crate::HashMap<crate::vlog::BlobFileId, crate::table::writer::LinkedFile>,
owned_cells: &mut Vec<(crate::vlog::BlobFileId, u64)>,
refs: &[RecoveredRef],
) {
for (key, ind, holding) in refs {
if *holding == Holding::OwnedCell {
owned_cells.push((ind.vhandle.blob_file_id, ind.vhandle.offset));
}
let (len, bytes, on_disk_bytes) = if holding.owns() {
(1, u64::from(ind.size), u64::from(ind.vhandle.on_disk_size))
} else {
(0, 0, 0)
};
derived
.entry(ind.vhandle.blob_file_id)
.and_modify(|link| {
link.bytes += bytes;
link.on_disk_bytes += on_disk_bytes;
link.len += len;
link.last_key.clone_from(key);
})
.or_insert_with(|| crate::table::writer::LinkedFile {
blob_file_id: ind.vhandle.blob_file_id,
bytes,
on_disk_bytes,
len,
first_key: key.clone(),
last_key: key.clone(),
});
}
}