removed recursion in load_causal_past

master
Niko PLP 1 month ago
parent 5155dc208b
commit a983205baa
  1. 89
      ng-repo/src/branch.rs
  2. 37
      ng-repo/src/repo.rs
  3. 18
      ng-verifier/src/verifier.rs

@ -180,15 +180,17 @@ impl Branch {
/// optionally collecting the missing objects/blocks that couldn't be found locally on the way, /// optionally collecting the missing objects/blocks that couldn't be found locally on the way,
/// and also optionally, collecting the commits of `theirs` found on the way /// and also optionally, collecting the commits of `theirs` found on the way
pub fn load_causal_past( pub fn load_causal_past(
cobj: &Object, recursor: &mut Vec<(ObjectId, Option<ObjectId>)>,
store: &Store, store: &Store,
theirs: &HashSet<ObjectId>, theirs: &HashSet<ObjectId>,
visited: &mut HashMap<ObjectId, DagNode>, visited: &mut HashMap<ObjectId, DagNode>,
missing: &mut Option<&mut HashSet<ObjectId>>, missing: &mut Option<&mut HashSet<ObjectId>>,
future: Option<ObjectId>,
theirs_found: &mut Option<&mut HashSet<ObjectId>>, theirs_found: &mut Option<&mut HashSet<ObjectId>>,
theirs_filter: &Option<Filter>, theirs_filter: &Option<Filter>,
) -> Result<(), ObjectParseError> { ) -> Result<(), ObjectParseError> {
while let Some((id, future)) = recursor.pop() {
match Object::load(id, None, store) {
Ok(cobj) => {
let id = cobj.id(); let id = cobj.id();
// check if this commit object is present in theirs or has already been visited in the current walk // check if this commit object is present in theirs or has already been visited in the current walk
@ -215,29 +217,42 @@ impl Branch {
let pasts = cobj.acks_and_nacks(); let pasts = cobj.acks_and_nacks();
new_node_to_insert.past.extend(pasts.iter().cloned()); new_node_to_insert.past.extend(pasts.iter().cloned());
visited.insert(id, new_node_to_insert); visited.insert(id, new_node_to_insert);
for past_id in pasts { recursor.extend(pasts.into_iter().map(|past_id| (past_id, Some(id))));
match Object::load(past_id, None, store) { // for past_id in pasts {
Ok(o) => { // match Object::load(past_id, None, store) {
Self::load_causal_past( // Ok(o) => {
&o, // Self::load_causal_past(
store, // recursor,
theirs, // store,
visited, // theirs,
missing, // visited,
Some(id), // missing,
theirs_found, // theirs_found,
theirs_filter, // theirs_filter,
)?; // )?;
// }
// Err(ObjectParseError::MissingBlocks(blocks)) => {
// missing.as_mut().map(|m| m.extend(blocks));
// }
// Err(e) => return Err(e),
// }
// }
}
} else if theirs_found.is_some() {
theirs_found.as_mut().unwrap().insert(id);
}
} }
Err(ObjectParseError::MissingBlocks(blocks)) => { Err(ObjectParseError::MissingBlocks(blocks)) => {
if future.is_some() {
missing.as_mut().map(|m| m.extend(blocks)); missing.as_mut().map(|m| m.extend(blocks));
} }
Err(e) => return Err(e), }
Err(e) => {
if future.is_some() {
return Err(e);
} }
} }
} }
} else if theirs_found.is_some() {
theirs_found.as_mut().unwrap().insert(id);
} }
Ok(()) Ok(())
} }
@ -260,22 +275,20 @@ impl Branch {
// their commits // their commits
let mut theirs: HashMap<ObjectId, DagNode> = HashMap::new(); let mut theirs: HashMap<ObjectId, DagNode> = HashMap::new();
//
let mut recursor: Vec<(ObjectId, Option<ObjectId>)> =
known_heads.iter().map(|h| (h.clone(), None)).collect();
// collect causal past of known_heads // collect causal past of known_heads
for id in known_heads { // we silently discard any load error on the known_heads as the responder might not know them (yet).
if let Ok(cobj) = Object::load(*id, None, store) {
Self::load_causal_past( Self::load_causal_past(
&cobj, &mut recursor,
store, store,
&HashSet::new(), &HashSet::new(),
&mut theirs, &mut theirs,
&mut None, &mut None,
None,
&mut None, &mut None,
&None, &None,
)?; )?;
}
// we silently discard any load error on the known_heads as the responder might not know them (yet).
}
// log_debug!("their causal past \n{}", Dag(&theirs)); // log_debug!("their causal past \n{}", Dag(&theirs));
@ -291,23 +304,35 @@ impl Branch {
None None
}; };
let mut recursor: Vec<(ObjectId, Option<ObjectId>)> =
target_heads.map(|h| (h.clone(), None)).collect();
// collect all commits reachable from target_heads // collect all commits reachable from target_heads
// up to the root or until encountering a commit from theirs // up to the root or until encountering a commit from theirs
for id in target_heads { // we silently discard any load error on the target_heads as they can be wrong if the requester is confused about what the responder has locally.
if let Ok(cobj) = Object::load(id, None, store) {
Self::load_causal_past( Self::load_causal_past(
&cobj, &mut recursor,
store, store,
&theirs, &theirs,
&mut visited, &mut visited,
&mut None, &mut None,
None,
&mut None, &mut None,
&filter, &filter,
)?; )?;
} // for id in target_heads {
// we silently discard any load error on the target_heads as they can be wrong if the requester is confused about what the responder has locally. // if let Ok(cobj) = Object::load(id, None, store) {
} // Self::load_causal_past(
// &cobj,
// store,
// &theirs,
// &mut visited,
// &mut None,
// None,
// &mut None,
// &filter,
// )?;
// }
// }
// log_debug!("what we have here \n{}", Dag(&visited)); // log_debug!("what we have here \n{}", Dag(&visited));

@ -191,11 +191,12 @@ impl Repo {
fn load_causal_past( fn load_causal_past(
&self, &self,
cobj: &Commit, recursor: &mut Vec<(BlockRef, Option<ObjectId>)>,
visited: &mut HashMap<ObjectId, (HashSet<ObjectId>, CommitInfo)>, visited: &mut HashMap<ObjectId, (HashSet<ObjectId>, CommitInfo)>,
future: Option<ObjectId>,
) -> Result<Option<ObjectId>, VerifierError> { ) -> Result<Option<ObjectId>, VerifierError> {
let mut root = None; let mut root = None;
while let Some((next_ref, future)) = recursor.pop() {
if let Ok(cobj) = Commit::load(next_ref, &self.store, true) {
let id = cobj.id().unwrap(); let id = cobj.id().unwrap();
if let Some((future_set, _)) = visited.get_mut(&id) { if let Some((future_set, _)) = visited.get_mut(&id) {
// we update the future // we update the future
@ -269,13 +270,16 @@ impl Repo {
y: 0, y: 0,
}; };
visited.insert(id, (future.map_or([].into(), |f| [f].into()), commit_info)); visited.insert(id, (future.map_or([].into(), |f| [f].into()), commit_info));
if real_acks.is_empty() { if real_acks.is_empty() && root.is_none() {
root = Some(next_future); root = Some(next_future);
} }
for past_ref in real_acks { recursor.extend(real_acks.into_iter().map(|br| (br, Some(next_future))));
let o = Commit::load(past_ref, &self.store, true)?; // for past_ref in real_acks {
if let Some(r) = self.load_causal_past(&o, visited, Some(next_future))? { // let o = Commit::load(past_ref, &self.store, true)?;
root = Some(r); // if let Some(r) = self.load_causal_past(&o, visited, Some(next_future))? {
// root = Some(r);
// }
// }
} }
} }
} }
@ -458,15 +462,22 @@ impl Repo {
// } // }
let mut visited = HashMap::new(); let mut visited = HashMap::new();
let mut root = None; let mut root = None;
for id in heads { let mut recursor: Vec<(BlockRef, Option<ObjectId>)> =
if let Ok(cobj) = Commit::load(id.clone(), &self.store, true) { heads.iter().map(|h| (h.clone(), None)).collect();
let r = self.load_causal_past(&cobj, &mut visited, None)?; let r = self.load_causal_past(&mut recursor, &mut visited)?;
//log_debug!("ROOT? {:?}", r.map(|rr| rr.to_string()));
if r.is_some() { if r.is_some() {
root = r; root = r;
} }
} // for id in heads {
} // if let Ok(cobj) = Commit::load(id.clone(), &self.store, true) {
// let r = self.load_causal_past(&cobj, &mut visited, None)?;
// //log_debug!("ROOT? {:?}", r.map(|rr| rr.to_string()));
// if r.is_some() {
// root = r;
// }
// }
// }
// for h in visited.keys() { // for h in visited.keys() {
// log_debug!("VISITED {}", h); // log_debug!("VISITED {}", h);
// } // }

@ -1609,21 +1609,25 @@ impl Verifier {
let mut theirs_found = HashSet::new(); let mut theirs_found = HashSet::new();
let mut visited = HashMap::new(); let mut visited = HashMap::new();
for our in ours_set.iter() {
//log_info!("OUR HEADS {}", our); let mut recursor: Vec<(ObjectId, Option<ObjectId>)> =
if let Ok(cobj) = Object::load(*our, None, &repo.store) { ours_set.iter().map(|h| (h.clone(), None)).collect();
let _ = Branch::load_causal_past( let _ = Branch::load_causal_past(
&cobj, &mut recursor,
&repo.store, &repo.store,
&theirs, &theirs,
&mut visited, &mut visited,
&mut None, &mut None,
None,
&mut Some(&mut theirs_found), &mut Some(&mut theirs_found),
&None, &None,
); );
} // for our in ours_set.iter() {
} // //log_info!("OUR HEADS {}", our);
// if let Ok(cobj) = Object::load(*our, None, &repo.store) {
// let _ =
// }
// }
let theirs_not_found: Vec<ObjectId> = let theirs_not_found: Vec<ObjectId> =
theirs.difference(&theirs_found).cloned().collect(); theirs.difference(&theirs_found).cloned().collect();

Loading…
Cancel
Save