3CFU4DQNHPPJC2B63RSVAVGHTQZT3RT5CCHHYC4ZM6DQ4GVQULSQC
ZDK3GNDBWXJ2OXFDYB72ZCEBGLBF4MKE5K3PVHDZATHJ7HJIDPRQC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
6YMDOZIB5LVYLFIDGN2WNT5JTHEAMS4TFPVDEZ3OWXWOKJOC5QDAC
CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC
GHO6DWPILBBTL6CVZKERJBTFL3EY6ZT4YM4E5R4S6YPGVFKFHCVAC
I24UEJQLCH2SOXA4UHIYWTRDCHSOPU7AFTRUOTX7HZIAV4AZKYEQC
WZVCLZKY34KQBQU6YBGJLQCDADBQ67LQVDNRVCMQVY3O3C3EIWSQC
KQTD46KVVWMJ3W6O55BEJLCVTNTDLUH6QT46AEFT7OU2SELXG4IAC
YN63NUZO4LVJ7XPMURDULTXBVJKW5MVCTZ24R7Z52QMHO3HPDUVQC
Atom::EdgeMap(ref newedges) => unapply_edges(
changes,
txn,
T::graph_mut(channel),
change_id,
newedges,
&mut ws,
)?,
Atom::EdgeMap(ref newedges) => {
touched_inodes.insert(newedges.inode);
unapply_edges(
changes,
txn,
T::graph_mut(channel),
change_id,
newedges,
&mut ws,
)?
}
// Check each touched inode for zombieness, and remove files that
// aren't zombies anymore.
for inode in touched_inodes {
// This inode is actually dead if its only alive adjacent
// edges are PSEUDO.
if let Ok(inode) = internal_pos(txn, &inode, change_id) {
let channel = T::graph_mut(channel);
collect_zombies_pseudo(txn, channel, inode, &mut ws)?;
for (v, mut e) in ws.del_edges.drain(..) {
if e.flag().contains(EdgeFlags::PARENT) {
let u = *txn.find_block_end(channel, e.dest())?;
e -= EdgeFlags::PARENT;
del_graph_with_rev(txn, channel, e.flag(), u, v, e.introduced_by())?;
} else {
let w = *txn.find_block(channel, e.dest())?;
del_graph_with_rev(txn, channel, e.flag(), v, w, e.introduced_by())?;
}
}
}
}
ws.del_edges.push((v, *e))
}
}
}
ws.stack.clear();
ws.parents.clear();
Ok(())
}
/// Collect the paths going through `to` whose vertices' adjacent
/// edges are all PSEUDO or DELETED
fn collect_zombies_pseudo<T: GraphTxnT>(
txn: &T,
channel: &T::Graph,
to: Position<ChangeId>,
ws: &mut Workspace,
) -> Result<(), BlockError<T::GraphError>> {
ws.stack.push(*txn.find_block(channel, to)?);
while let Some(v) = ws.stack.pop() {
debug!("remove_zombies, v = {:?}", v);
if !ws.parents.insert(v) {
continue;
}
let del_len = ws.del_edges.len();
let stack_len = ws.stack.len();
for e in iter_adj_all(txn, channel, v)? {
let e = e?;
debug!("e = {:?}", e);
if (e.flag() & (EdgeFlags::PSEUDO | EdgeFlags::DELETED)).is_empty() {
// This isn't a pseudo edge, `v` isn't part
ws.del_edges.truncate(del_len);
ws.stack.truncate(stack_len);
break
}
if e.flag().contains(EdgeFlags::PARENT) {
ws.stack.push(*txn.find_block_end(channel, e.dest())?)
} else {
ws.stack.push(*txn.find_block(channel, e.dest())?)
}
if e.flag().contains(EdgeFlags::PSEUDO) {