mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-02 11:06:14 +00:00
chore: bk
This commit is contained in:
parent
352ddc1c11
commit
e2dc6382d0
7 changed files with 105 additions and 23 deletions
7
crates/loro-core/fuzz/Cargo.lock
generated
7
crates/loro-core/fuzz/Cargo.lock
generated
|
@ -46,6 +46,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -257,6 +263,7 @@ name = "loro-core"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"bit-vec",
|
||||
"colored",
|
||||
"crdt-list",
|
||||
"enum-as-inner",
|
||||
|
|
|
@ -167,11 +167,8 @@ impl Container for TextContainer {
|
|||
// stage 1
|
||||
// TODO: need a better mechanism to track the head (KEEP IT IN TRACKER?)
|
||||
let path = store.find_path(&head, &latest_head);
|
||||
dbg!(&path);
|
||||
debug_log!("path={:?}", &path.right);
|
||||
for iter in store.iter_partial(&head, path.right) {
|
||||
dbg!(&iter);
|
||||
self.tracker.retreat(&iter.retreat);
|
||||
self.tracker.forward(&iter.forward);
|
||||
// TODO: avoid this clone
|
||||
let change = iter
|
||||
.data
|
||||
|
@ -182,6 +179,8 @@ impl Container for TextContainer {
|
|||
format!("{:?}", &iter.forward).red(),
|
||||
format!("{:#?}", &change).blue(),
|
||||
);
|
||||
self.tracker.retreat(&iter.retreat);
|
||||
self.tracker.forward(&iter.forward);
|
||||
for op in change.ops.iter() {
|
||||
if op.container == self.id {
|
||||
// TODO: convert op to local
|
||||
|
|
|
@ -247,7 +247,6 @@ impl Tracker {
|
|||
slice.clone(),
|
||||
);
|
||||
debug_log!("INSERT YSPAN={}", format!("{:#?}", &yspan).red());
|
||||
dbg!(&self.content);
|
||||
// SAFETY: we know this is safe because in [YataImpl::insert_after] there is no access to shared elements
|
||||
unsafe { crdt_list::yata::integrate::<YataImpl>(self, yspan) };
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
//!
|
||||
use std::{
|
||||
collections::{BinaryHeap, HashMap},
|
||||
fmt::Debug,
|
||||
time::Instant,
|
||||
fmt::{format, Debug},
|
||||
};
|
||||
|
||||
use bit_vec::BitVec;
|
||||
use colored::Colorize;
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use rle::{HasLength, Sliceable};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -23,6 +23,7 @@ mod test;
|
|||
|
||||
use crate::{
|
||||
change::Lamport,
|
||||
debug_log,
|
||||
id::{ClientID, Counter, ID},
|
||||
span::{HasId, HasIdSpan, HasLamport, HasLamportSpan, IdSpan},
|
||||
version::{IdSpanVector, VersionVector, VersionVectorDiff},
|
||||
|
@ -113,12 +114,16 @@ impl<T: Dag + ?Sized> DagUtils for T {
|
|||
|
||||
fn find_path(&self, from: &[ID], to: &[ID]) -> VersionVectorDiff {
|
||||
let mut ans = VersionVectorDiff::default();
|
||||
debug_log!(
|
||||
"{}",
|
||||
format!("FINDPATH from={:?} to={:?}", from, to).green()
|
||||
);
|
||||
_find_common_ancestor(
|
||||
&|v| self.get(v),
|
||||
from,
|
||||
to,
|
||||
&mut |span, node_type| {
|
||||
// dbg!(span, node_type);
|
||||
dbg!(span, node_type);
|
||||
match node_type {
|
||||
NodeType::A => ans.merge_left(span),
|
||||
NodeType::B => ans.merge_right(span),
|
||||
|
@ -131,6 +136,7 @@ impl<T: Dag + ?Sized> DagUtils for T {
|
|||
true,
|
||||
);
|
||||
|
||||
// dbg!(from, to, &ans);
|
||||
ans
|
||||
}
|
||||
|
||||
|
@ -291,6 +297,10 @@ where
|
|||
D: DagNode + 'a,
|
||||
F: Fn(ID) -> Option<&'a D>,
|
||||
{
|
||||
if a_id.is_empty() || b_id.is_empty() {
|
||||
return smallvec::smallvec![];
|
||||
}
|
||||
|
||||
let mut ids = Vec::with_capacity(a_id.len() + b_id.len());
|
||||
for id in a_id {
|
||||
ids.push(*id);
|
||||
|
@ -484,7 +494,7 @@ fn update_frontier(frontier: &mut Vec<ID>, new_node_id: ID, new_node_deps: &[ID]
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: BitVec may be too slow here
|
||||
// TODO: need bench, BitVec may be slow here
|
||||
fn _find_common_ancestor_new<'a, F, D>(get: &'a F, ids: &[ID]) -> FxHashMap<ClientID, Counter>
|
||||
where
|
||||
D: DagNode + 'a,
|
||||
|
@ -522,6 +532,7 @@ where
|
|||
if this_node.id_span() == other_node.id_span() {
|
||||
if other_map.all() {
|
||||
shared_num -= 1;
|
||||
is_shared = true;
|
||||
}
|
||||
|
||||
if !is_shared && this_map.or(other_map) && this_map.all() {
|
||||
|
@ -542,6 +553,7 @@ where
|
|||
is_shared = true;
|
||||
} else if !is_shared && visited_map.or(&this_map) && visited_map.all() {
|
||||
ans.insert(this_node.id.client_id, this_node.id_last().counter);
|
||||
this_map.set_all();
|
||||
is_shared = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -575,14 +587,13 @@ where
|
|||
|
||||
if is_shared {
|
||||
shared_num += this_node.deps.len()
|
||||
}
|
||||
|
||||
if !is_shared {
|
||||
} else {
|
||||
if queue.is_empty() {
|
||||
ans.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: simplify this logic
|
||||
if this_node.deps.is_empty() {
|
||||
if this_node.len == 1 {
|
||||
ans.clear();
|
||||
|
|
|
@ -271,13 +271,18 @@ impl<'a, T: DagNode + 'a, D: Dag<Node = T>> Iterator for DagPartialIter<'a, D> {
|
|||
});
|
||||
}
|
||||
|
||||
dbg!(&node);
|
||||
let deps: SmallVec<[_; 2]> = if slice_from == 0 {
|
||||
println!("000");
|
||||
node.deps().iter().copied().collect()
|
||||
} else {
|
||||
println!("111");
|
||||
smallvec::smallvec![node.id_start().inc(slice_from - 1)]
|
||||
};
|
||||
dbg!(&self.frontier, &deps);
|
||||
let path = self.dag.find_path(&self.frontier, &deps);
|
||||
dbg!(&self.frontier);
|
||||
dbg!(&deps);
|
||||
dbg!(&path);
|
||||
// NOTE: we expect user to update the tracker, to apply node, after visiting the node
|
||||
self.frontier = smallvec::smallvec![node.id_start().inc(slice_end - 1)];
|
||||
Some(IterReturn {
|
||||
|
|
|
@ -747,22 +747,16 @@ mod find_common_ancestors {
|
|||
let mut a2 = TestDag::new(2);
|
||||
|
||||
a0.push(3);
|
||||
a1.merge(&a0);
|
||||
a2.merge(&a0);
|
||||
a1.push(3);
|
||||
a2.push(2);
|
||||
a2.merge(&a0);
|
||||
a2.push(1);
|
||||
a1.merge(&a2);
|
||||
a2.push(1);
|
||||
a1.push(1);
|
||||
a1.merge(&a2);
|
||||
a1.push(1);
|
||||
a1.nodes
|
||||
.get_mut(&1)
|
||||
.unwrap()
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.deps
|
||||
.push(ID::new(0, 1));
|
||||
a0.push(1);
|
||||
a1.merge(&a2);
|
||||
a1.merge(&a0);
|
||||
|
@ -771,7 +765,7 @@ mod find_common_ancestors {
|
|||
a1.find_common_ancestor(&[ID::new(0, 3)], &[ID::new(1, 4)])
|
||||
.first()
|
||||
.copied(),
|
||||
None
|
||||
Some(ID::new(0, 2))
|
||||
);
|
||||
assert_eq!(
|
||||
a1.find_common_ancestor(&[ID::new(2, 3)], &[ID::new(1, 3)])
|
||||
|
@ -870,6 +864,31 @@ mod find_common_ancestors_proptest {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1() {
|
||||
test_single_common_ancestor(
|
||||
2,
|
||||
vec![
|
||||
Interaction {
|
||||
dag_idx: 1,
|
||||
merge_with: None,
|
||||
len: 1,
|
||||
},
|
||||
Interaction {
|
||||
dag_idx: 0,
|
||||
merge_with: None,
|
||||
len: 1,
|
||||
},
|
||||
],
|
||||
vec![Interaction {
|
||||
dag_idx: 0,
|
||||
merge_with: None,
|
||||
len: 1,
|
||||
}],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn test_single_common_ancestor(
|
||||
dag_num: i32,
|
||||
mut before_merge_insertion: Vec<Interaction>,
|
||||
|
@ -911,10 +930,11 @@ mod find_common_ancestors_proptest {
|
|||
let (dag0, dag1) = array_mut_ref!(&mut dags, [0, 1]);
|
||||
dag1.push(1);
|
||||
dag0.merge(dag1);
|
||||
// println!("{}", dag0.mermaid());
|
||||
let a = dags[0].nodes.get(&0).unwrap().last().unwrap().id_last();
|
||||
let b = dags[1].nodes.get(&1).unwrap().last().unwrap().id_last();
|
||||
let actual = dags[0].find_common_ancestor(&[a], &[b]);
|
||||
prop_assert_eq!(actual.first().copied().unwrap(), expected);
|
||||
prop_assert_eq!(&*actual, &[expected]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -306,6 +306,47 @@ mod test {
|
|||
|
||||
use super::Action::*;
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_11() {
|
||||
test_multi_sites(
|
||||
2,
|
||||
vec![
|
||||
Ins {
|
||||
content: "?\0\u{1}\0\u{18}\0".into(),
|
||||
pos: 727894294070016698,
|
||||
site: 248,
|
||||
},
|
||||
Ins {
|
||||
content: "\u{10}".into(),
|
||||
pos: 16153481340371206368,
|
||||
site: 33,
|
||||
},
|
||||
Sync { from: 177, to: 0 },
|
||||
Ins {
|
||||
content: "\n".into(),
|
||||
pos: 9189030930189130488,
|
||||
site: 0,
|
||||
},
|
||||
Ins {
|
||||
content: "\u{13}\u{b}\u{1}\0\n\0\n".into(),
|
||||
pos: 9655420767302589176,
|
||||
site: 127,
|
||||
},
|
||||
Sync { from: 10, to: 19 },
|
||||
Ins {
|
||||
content: "\0".into(),
|
||||
pos: 1374708439171007232,
|
||||
site: 19,
|
||||
},
|
||||
Ins {
|
||||
content: "\0".into(),
|
||||
pos: 93,
|
||||
site: 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_10() {
|
||||
test_multi_sites(
|
||||
|
|
Loading…
Reference in a new issue