fix: yata id spans generate bug

This commit is contained in:
Zixuan Chen 2022-10-11 18:18:14 +08:00
parent bc980c5b02
commit 280382c39c
7 changed files with 106 additions and 21 deletions

View file

@ -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);
}

View file

@ -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,
));
}

View file

@ -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,
},
],
)
}
}

View file

@ -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 {

View file

@ -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>(

View file

@ -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)

View file

@ -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)