use std::collections::{HashSet, VecDeque};
use super::transaction::{TxId, VersionedEntry, TX_ID_COMMITTED};
pub fn vacuum_versions(
versions: &mut VecDeque<VersionedEntry>,
watermark: TxId,
committed: &HashSet<TxId>,
) -> usize {
let mut removed = 0usize;
let mut keep: VecDeque<VersionedEntry> = VecDeque::new();
let mut latest_live_kept_at_watermark = false;
let mut temp: Vec<VersionedEntry> = versions.drain(..).collect();
temp.reverse();
for entry in temp {
let creator_committed =
entry.created_tx_id == TX_ID_COMMITTED || committed.contains(&entry.created_tx_id);
let creator_old = entry.created_tx_id <= watermark && creator_committed;
let deleter_committed_and_old = entry
.deleted_tx_id
.map(|d| d <= watermark && committed.contains(&d))
.unwrap_or(false);
if creator_old && deleter_committed_and_old {
removed += 1;
continue;
}
if creator_old && entry.deleted_tx_id.is_none() && latest_live_kept_at_watermark {
removed += 1;
continue;
}
if entry.deleted_tx_id.is_none() && creator_committed && creator_old {
latest_live_kept_at_watermark = true;
}
keep.push_back(entry);
}
let mut restored: Vec<VersionedEntry> = keep.into_iter().collect();
restored.reverse();
*versions = restored.into();
removed
}