pub(crate) fn repair_up<T: GraphMutTxnT + TreeTxnT>(
txn: &mut T,
channel: &mut T::Graph,
root: Position<ChangeId>,
) -> Result<(), LocalApplyError<T>> {
info!("repair_zombies {:?}", root);
let mut stack = vec![root.inode_vertex()];
let mut visited = BTreeSet::new();
let mut add = Vec::new();
while let Some(elt) = stack.pop() {
if !visited.insert(elt) {
continue;
}
let mut is_alive = false;
let mut is_dead = false;
for e in iter_adjacent(
txn,
channel,
elt,
EdgeFlags::PARENT | EdgeFlags::FOLDER,
EdgeFlags::all(),
)? {
let e = e?;
let deleted = e.flag().contains(EdgeFlags::DELETED);
if e.flag().contains(EdgeFlags::PARENT | EdgeFlags::FOLDER) {
is_alive |= !deleted;
is_dead |= deleted;
}
}
if is_dead && !is_alive {
for e in iter_adjacent(
txn,
channel,
elt,
EdgeFlags::PARENT | EdgeFlags::FOLDER,
EdgeFlags::all(),
)? {
let e = e?;
if e.flag()
.contains(EdgeFlags::PARENT | EdgeFlags::DELETED | EdgeFlags::FOLDER)
{
let parent = txn.find_block_end(channel, e.dest())?;
add.push((*parent, elt));
stack.push(*parent)
}
}
for (a, b) in add.drain(..) {
put_graph_with_rev(
txn,
channel,
EdgeFlags::PSEUDO | EdgeFlags::FOLDER,
a,
b,
ChangeId::ROOT,
)?;
}
}
}
Ok(())
}