mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-02 11:06:14 +00:00
refactor: can use multiple ids inpu in find path
This commit is contained in:
parent
15c60aece0
commit
780cf84610
2 changed files with 36 additions and 23 deletions
|
@ -82,7 +82,7 @@ pub(crate) trait Dag {
|
|||
trait DagUtils: Dag {
|
||||
fn find_common_ancestor(&self, a_id: ID, b_id: ID) -> SmallVec<[ID; 2]>;
|
||||
fn get_vv(&self, id: ID) -> VersionVector;
|
||||
fn find_path(&self, from: ID, to: ID) -> VersionVectorDiff;
|
||||
fn find_path(&self, from: &[ID], to: &[ID]) -> VersionVectorDiff;
|
||||
fn iter(&self) -> DagIterator<'_, Self::Node>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -108,7 +108,7 @@ impl<T: Dag> DagUtils for T {
|
|||
///
|
||||
#[inline]
|
||||
fn find_common_ancestor(&self, a_id: ID, b_id: ID) -> SmallVec<[ID; 2]> {
|
||||
find_common_ancestor(&|id| self.get(id), a_id, b_id)
|
||||
find_common_ancestor(&|id| self.get(id), &[a_id], &[b_id])
|
||||
}
|
||||
|
||||
/// TODO: we probably need cache to speedup this
|
||||
|
@ -118,7 +118,7 @@ impl<T: Dag> DagUtils for T {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn find_path(&self, from: ID, to: ID) -> VersionVectorDiff {
|
||||
fn find_path(&self, from: &[ID], to: &[ID]) -> VersionVectorDiff {
|
||||
let mut ans = VersionVectorDiff::default();
|
||||
_find_common_ancestor(
|
||||
&|v| self.get(v),
|
||||
|
@ -285,7 +285,7 @@ impl<'a> OrdIdSpan<'a> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn find_common_ancestor<'a, F, D>(get: &'a F, a_id: ID, b_id: ID) -> SmallVec<[ID; 2]>
|
||||
fn find_common_ancestor<'a, F, D>(get: &'a F, a_id: &[ID], b_id: &[ID]) -> SmallVec<[ID; 2]>
|
||||
where
|
||||
D: DagNode + 'a,
|
||||
F: Fn(ID) -> Option<&'a D>,
|
||||
|
@ -299,8 +299,8 @@ where
|
|||
/// - deep whether keep searching until the min of non-shared node is found
|
||||
fn _find_common_ancestor<'a, F, D, G>(
|
||||
get: &'a F,
|
||||
a_id: ID,
|
||||
b_id: ID,
|
||||
a_ids: &[ID],
|
||||
b_ids: &[ID],
|
||||
notify: &mut G,
|
||||
deep: bool,
|
||||
) -> FxHashMap<ClientID, Counter>
|
||||
|
@ -311,8 +311,12 @@ where
|
|||
{
|
||||
let mut ans: FxHashMap<ClientID, Counter> = Default::default();
|
||||
let mut queue: BinaryHeap<(OrdIdSpan, NodeType)> = BinaryHeap::new();
|
||||
queue.push((OrdIdSpan::from_dag_node(a_id, get).unwrap(), NodeType::A));
|
||||
queue.push((OrdIdSpan::from_dag_node(b_id, get).unwrap(), NodeType::B));
|
||||
for id in a_ids {
|
||||
queue.push((OrdIdSpan::from_dag_node(*id, get).unwrap(), NodeType::A));
|
||||
}
|
||||
for id in b_ids {
|
||||
queue.push((OrdIdSpan::from_dag_node(*id, get).unwrap(), NodeType::B));
|
||||
}
|
||||
let mut visited: HashMap<ClientID, (Counter, NodeType), _> = FxHashMap::default();
|
||||
// invariants in this method:
|
||||
//
|
||||
|
@ -323,8 +327,8 @@ where
|
|||
// - we may visit nodes that are before the common ancestors
|
||||
|
||||
// type count in the queue. if both are zero, we can stop
|
||||
let mut a_count = 1;
|
||||
let mut b_count = 1;
|
||||
let mut a_count = a_ids.len();
|
||||
let mut b_count = b_ids.len();
|
||||
let mut min = None;
|
||||
while let Some((node, mut node_type)) = queue.pop() {
|
||||
match node_type {
|
||||
|
|
|
@ -441,7 +441,7 @@ mod find_path {
|
|||
a.push(1);
|
||||
b.push(1);
|
||||
a.merge(&b);
|
||||
let actual = a.find_path(ID::new(0, 0), ID::new(1, 0));
|
||||
let actual = a.find_path(&[ID::new(0, 0)], &[ID::new(1, 0)]);
|
||||
assert_eq!(
|
||||
actual,
|
||||
VersionVectorDiff {
|
||||
|
@ -463,7 +463,7 @@ mod find_path {
|
|||
// 0 - 1
|
||||
a.push(1);
|
||||
a.merge(&b);
|
||||
let actual = a.find_path(ID::new(0, 1), ID::new(1, 0));
|
||||
let actual = a.find_path(&[ID::new(0, 1)], &[ID::new(1, 0)]);
|
||||
assert_eq!(
|
||||
actual,
|
||||
VersionVectorDiff {
|
||||
|
@ -480,23 +480,23 @@ mod find_path {
|
|||
a.push(2);
|
||||
b.push(1);
|
||||
b.merge(&a);
|
||||
b.push(1);
|
||||
b.push(2);
|
||||
a.push(2);
|
||||
b.merge(&a);
|
||||
// println!("{}", b.mermaid());
|
||||
let actual = b.find_path(ID::new(0, 3), ID::new(1, 1));
|
||||
let actual = b.find_path(&[ID::new(0, 3)], &[ID::new(1, 2)]);
|
||||
assert_eq!(
|
||||
actual,
|
||||
VersionVectorDiff {
|
||||
to_left: fx_map!(0 => CounterSpan { from: 2, to: 4 }),
|
||||
to_right: fx_map!(1 => CounterSpan { from: 0, to: 2 })
|
||||
to_right: fx_map!(1 => CounterSpan { from: 0, to: 3 })
|
||||
}
|
||||
);
|
||||
let actual = b.find_path(ID::new(1, 1), ID::new(0, 3));
|
||||
let actual = b.find_path(&[ID::new(1, 1), ID::new(1, 2)], &[ID::new(0, 3)]);
|
||||
assert_eq!(
|
||||
actual,
|
||||
VersionVectorDiff {
|
||||
to_left: fx_map!(1 => CounterSpan { from: 0, to: 2 }),
|
||||
to_left: fx_map!(1 => CounterSpan { from: 0, to: 3 }),
|
||||
to_right: fx_map!(0 => CounterSpan { from: 2, to: 4 })
|
||||
}
|
||||
);
|
||||
|
@ -528,17 +528,18 @@ mod find_path {
|
|||
}
|
||||
|
||||
// println!("{}", a.mermaid());
|
||||
for (i, (node, vv)) in nodes.iter().enumerate() {
|
||||
let mut vec: Vec<_> = nodes.iter().enumerate().collect();
|
||||
for &(i, (node, vv)) in vec.iter() {
|
||||
if i > 3 {
|
||||
break;
|
||||
}
|
||||
|
||||
for (j, (other_node, other_vv)) in nodes.iter().enumerate() {
|
||||
if i == j {
|
||||
for &(j, (other_node, other_vv)) in vec.iter() {
|
||||
if i >= j {
|
||||
continue;
|
||||
}
|
||||
|
||||
let actual = a.find_path(node.id, other_node.id);
|
||||
let actual = a.find_path(&[node.id], &[other_node.id]);
|
||||
let expected = vv.clone() - other_vv.clone();
|
||||
prop_assert_eq!(
|
||||
actual,
|
||||
|
@ -549,6 +550,14 @@ mod find_path {
|
|||
node.id,
|
||||
other_node.id
|
||||
);
|
||||
|
||||
for k in j + 1..nodes.len() {
|
||||
let mut vv = vv.clone();
|
||||
vv.merge(other_vv);
|
||||
let actual = a.find_path(&[node.id, other_node.id], &[vec[k].1 .0.id]);
|
||||
let expected = vv.clone() - vec[k].1 .1.clone();
|
||||
prop_assert_eq!(actual, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,14 +618,14 @@ mod find_path {
|
|||
proptest! {
|
||||
#[test]
|
||||
fn proptest_path(
|
||||
interactions in prop::collection::vec(gen_interaction(5), 0..50 * PROPTEST_FACTOR_10),
|
||||
interactions in prop::collection::vec(gen_interaction(5), 0..10 * PROPTEST_FACTOR_10),
|
||||
) {
|
||||
test_find_path(5, interactions)?;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proptest_path_large(
|
||||
interactions in prop::collection::vec(gen_interaction(10), 0..10 * PROPTEST_FACTOR_10 * PROPTEST_FACTOR_10 + 10),
|
||||
interactions in prop::collection::vec(gen_interaction(10), 0..5 * PROPTEST_FACTOR_10 * PROPTEST_FACTOR_10 + 10),
|
||||
) {
|
||||
test_find_path(10, interactions)?;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue