mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-28 17:41:49 +00:00
fix: yata id spans generate bug
This commit is contained in:
parent
bc980c5b02
commit
280382c39c
7 changed files with 106 additions and 21 deletions
|
@ -118,7 +118,12 @@ impl Tracker {
|
|||
.id_to_cursor
|
||||
.get_range(span.min_id().into(), span.max_id().into())
|
||||
{
|
||||
let cursor = marker.as_cursor(span_start).unwrap().unwrap();
|
||||
let m = marker.as_cursor(span_start);
|
||||
if m.is_none() {
|
||||
println!("XXX ID {:?} {:?}", span_start, span.max_id());
|
||||
let m = marker.as_cursor(span_start);
|
||||
}
|
||||
let cursor = m.unwrap().unwrap();
|
||||
span_start = span_start.inc(cursor.len as Counter);
|
||||
cursors.push(cursor);
|
||||
}
|
||||
|
|
|
@ -144,10 +144,12 @@ impl ContentMap {
|
|||
pub fn get_id_spans(&self, pos: usize, len: usize) -> RleVec<IdSpan> {
|
||||
let mut ans = RleVec::new();
|
||||
for cursor in self.iter_range(pos, Some(pos + len)) {
|
||||
let id = cursor.id;
|
||||
let cursor = cursor.unwrap();
|
||||
ans.push(IdSpan::new(
|
||||
cursor.id.client_id,
|
||||
cursor.id.counter,
|
||||
cursor.id.counter + cursor.len as Counter,
|
||||
id.client_id,
|
||||
id.counter + (cursor.offset as i32),
|
||||
id.counter + (cursor.offset + cursor.len) as i32,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -183,7 +183,7 @@ pub mod fuzz {
|
|||
use crate::{
|
||||
container::text::tracker::{y_span::StatusChange, Tracker},
|
||||
id::{ClientID, ID},
|
||||
span::IdSpan,
|
||||
span::{self, IdSpan},
|
||||
};
|
||||
|
||||
use super::YataImpl;
|
||||
|
@ -251,12 +251,13 @@ pub mod fuzz {
|
|||
}
|
||||
|
||||
pos %= container.content.len();
|
||||
len = std::cmp::min(len, container.content.len() - pos);
|
||||
len = std::cmp::min(len % 10 + 1, container.content.len() - pos);
|
||||
if len == 0 {
|
||||
return RleVec::new();
|
||||
}
|
||||
|
||||
container.content.get_id_spans(pos, len)
|
||||
let spans = container.content.get_id_spans(pos, len);
|
||||
spans
|
||||
}
|
||||
|
||||
fn integrate_delete_op(container: &mut Self::Container, op: Self::DeleteOp) {
|
||||
|
@ -264,13 +265,13 @@ pub mod fuzz {
|
|||
}
|
||||
|
||||
fn can_apply_del_op(container: &Self::Container, op: &Self::DeleteOp) -> bool {
|
||||
op.iter().all(|x| container.vv.includes(x.max_id()))
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
use Action::*;
|
||||
#[test]
|
||||
fn issue_0() {
|
||||
use Action::*;
|
||||
crdt_list::test::test_with_actions::<YataImpl>(
|
||||
5,
|
||||
&[
|
||||
|
@ -289,4 +290,57 @@ pub mod fuzz {
|
|||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1() {
|
||||
crdt_list::test::test_with_actions::<YataImpl>(
|
||||
5,
|
||||
&[
|
||||
NewOp {
|
||||
client_id: 72057319153112726,
|
||||
pos: 18446743116487664383,
|
||||
},
|
||||
Delete {
|
||||
client_id: 18446742978492891135,
|
||||
pos: 18446744073709551615,
|
||||
len: 18446744073695461375,
|
||||
},
|
||||
Delete {
|
||||
client_id: 65535,
|
||||
pos: 281178623508480,
|
||||
len: 18446742974197923840,
|
||||
},
|
||||
Delete {
|
||||
client_id: 13107135066100727807,
|
||||
pos: 532050712311190,
|
||||
len: 18446744073701163007,
|
||||
},
|
||||
NewOp {
|
||||
client_id: 35184372089087,
|
||||
pos: 18446462598732840960,
|
||||
},
|
||||
Sync {
|
||||
from: 18446744073692774400,
|
||||
to: 16565899692026626047,
|
||||
},
|
||||
Delete {
|
||||
client_id: 18446462606851290549,
|
||||
pos: 18446744073709551487,
|
||||
len: 9910603680803979263,
|
||||
},
|
||||
NewOp {
|
||||
client_id: 9910603678816504201,
|
||||
pos: 9910603678816504201,
|
||||
},
|
||||
NewOp {
|
||||
client_id: 9910603678816504201,
|
||||
pos: 9910603678816504201,
|
||||
},
|
||||
NewOp {
|
||||
client_id: 9910603678816504201,
|
||||
pos: 18446744073701788041,
|
||||
},
|
||||
],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,15 @@ pub const ROOT_ID: ID = ID {
|
|||
counter: i32::MAX,
|
||||
};
|
||||
|
||||
impl From<u128> for ID {
|
||||
fn from(id: u128) -> Self {
|
||||
ID {
|
||||
client_id: (id >> 64) as ClientID,
|
||||
counter: id as Counter,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ID {
|
||||
#[inline]
|
||||
pub fn new(client_id: u64, counter: Counter) -> Self {
|
||||
|
|
|
@ -256,10 +256,8 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut internal_updates_map: HashMap<
|
||||
NonNull<_>,
|
||||
Vec<(usize, Vec<&'_ mut Node<'_, T, A>>)>,
|
||||
> = Default::default();
|
||||
let mut internal_updates_map: HashMap<NonNull<_>, Vec<(usize, Vec<_>)>> =
|
||||
Default::default();
|
||||
for (mut leaf, updates) in updates_map {
|
||||
// SAFETY: we has the exclusive reference to the tree and the cursor is valid
|
||||
let leaf = unsafe { leaf.as_mut() };
|
||||
|
@ -295,6 +293,11 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
{
|
||||
self.debug_check();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_update<U, F>(
|
||||
|
|
|
@ -243,8 +243,10 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
|
|||
last_end = index + 1;
|
||||
}
|
||||
|
||||
let self_ptr: NonNull<_> = self.into();
|
||||
let result = if new_children.len() <= A::MAX_CHILDREN_NUM {
|
||||
for child in new_children {
|
||||
child.set_parent(self_ptr);
|
||||
self.children.push(child);
|
||||
}
|
||||
|
||||
|
@ -252,19 +254,24 @@ impl<'a, T: Rle, A: RleTreeTrait<T>> InternalNode<'a, T, A> {
|
|||
Ok(())
|
||||
} else {
|
||||
for child in new_children.drain(0..A::MAX_CHILDREN_NUM) {
|
||||
child.set_parent(self_ptr);
|
||||
self.children.push(child);
|
||||
}
|
||||
|
||||
A::update_cache_internal(self);
|
||||
let mut ans_vec = Vec::new();
|
||||
while !new_children.is_empty() {
|
||||
let mut new_leaf = InternalNode::new(self.bump, self.parent);
|
||||
let new_internal_node = self
|
||||
.bump
|
||||
.alloc(Node::Internal(InternalNode::new(self.bump, self.parent)));
|
||||
let new_internal = new_internal_node.as_internal_mut().unwrap();
|
||||
for child in new_children.drain(0..A::MAX_CHILDREN_NUM) {
|
||||
new_leaf.children.push(child);
|
||||
child.set_parent(new_internal.into());
|
||||
new_internal.children.push(child);
|
||||
}
|
||||
|
||||
A::update_cache_internal(&mut new_leaf);
|
||||
ans_vec.push(self.bump.alloc(Node::Internal(new_leaf)));
|
||||
A::update_cache_internal(new_internal);
|
||||
ans_vec.push(new_internal_node);
|
||||
}
|
||||
|
||||
Err(ans_vec)
|
||||
|
|
|
@ -423,6 +423,7 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
|||
let mut new_children: Vec<&mut T> = Vec::new();
|
||||
let mut self_children = std::mem::replace(&mut self.children, BumpVec::new_in(self.bump));
|
||||
let mut last_end = 0;
|
||||
// append element to the new_children list
|
||||
for (index, replace) in updates {
|
||||
let should_pop = index - last_end < self_children.len();
|
||||
for child in self_children.drain(0..index - last_end + 1) {
|
||||
|
@ -430,6 +431,7 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
|||
}
|
||||
|
||||
if should_pop {
|
||||
// ignore original element at index
|
||||
new_children.pop();
|
||||
}
|
||||
|
||||
|
@ -466,14 +468,17 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
|
|||
A::update_cache_leaf(self);
|
||||
let mut leaf_vec = Vec::new();
|
||||
while !new_children.is_empty() {
|
||||
let mut new_leaf = LeafNode::new(self.bump, self.parent);
|
||||
let new_leaf_node = self
|
||||
.bump
|
||||
.alloc(Node::Leaf(LeafNode::new(self.bump, self.parent)));
|
||||
let new_leaf = new_leaf_node.as_leaf_mut().unwrap();
|
||||
for child in new_children.drain(0..A::MAX_CHILDREN_NUM) {
|
||||
notify(child, &mut new_leaf);
|
||||
notify(child, new_leaf);
|
||||
new_leaf.children.push(child);
|
||||
}
|
||||
|
||||
A::update_cache_leaf(&mut new_leaf);
|
||||
leaf_vec.push(self.bump.alloc(Node::Leaf(new_leaf)));
|
||||
A::update_cache_leaf(new_leaf);
|
||||
leaf_vec.push(new_leaf_node);
|
||||
}
|
||||
|
||||
Err(leaf_vec)
|
||||
|
|
Loading…
Reference in a new issue