diff --git a/Cargo.toml b/Cargo.toml index 5e1c56d6..c66a4d73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,2 @@ [workspace] members = ["crates/*"] - - -[profile.release] -lto = true -opt-level = 3 diff --git a/crates/loro-core/src/container/manager.rs b/crates/loro-core/src/container/manager.rs index 4fb59775..e398a29b 100644 --- a/crates/loro-core/src/container/manager.rs +++ b/crates/loro-core/src/container/manager.rs @@ -3,7 +3,10 @@ use std::ptr::NonNull; use enum_as_inner::EnumAsInner; use fxhash::FxHashMap; -use crate::{log_store::LogStoreRef, LogStore}; +use crate::{ + log_store::{LogStoreRef, LogStoreWeakRef}, + LogStore, +}; use super::{ map::MapContainer, text::text_container::TextContainer, Container, ContainerID, ContainerType, @@ -80,7 +83,7 @@ impl ContainerManager { &mut self, id: ContainerID, container_type: ContainerType, - log_store: LogStoreRef, + log_store: LogStoreWeakRef, ) -> ContainerInstance { match container_type { ContainerType::Map => ContainerInstance::Map(Box::new(MapContainer::new(id))), @@ -109,7 +112,7 @@ impl ContainerManager { pub fn get_or_create( &mut self, id: &ContainerID, - log_store: LogStoreRef, + log_store: LogStoreWeakRef, ) -> &mut ContainerInstance { if !self.containers.contains_key(id) { let container = self.create(id.clone(), id.container_type(), log_store); diff --git a/crates/loro-core/src/container/text/text_container.rs b/crates/loro-core/src/container/text/text_container.rs index 04d710f6..83b92364 100644 --- a/crates/loro-core/src/container/text/text_container.rs +++ b/crates/loro-core/src/container/text/text_container.rs @@ -5,7 +5,7 @@ use crate::{ container::{list::list_op::ListOp, Container, ContainerID, ContainerType}, dag::{Dag, DagUtils}, id::ID, - log_store::LogStoreRef, + log_store::LogStoreWeakRef, op::{InsertContent, Op, OpContent, OpProxy}, smstring::SmString, span::{HasIdSpan, IdSpan}, @@ -28,7 +28,7 @@ struct DagNode { #[derive(Debug)] pub struct TextContainer { id: ContainerID, - log_store: LogStoreRef, + log_store: LogStoreWeakRef, state: RleTree, raw_str: StringPool, tracker: Tracker, @@ -36,7 +36,7 @@ pub struct TextContainer { } impl TextContainer { - pub fn new(id: ContainerID, log_store: LogStoreRef) -> Self { + pub fn new(id: ContainerID, log_store: LogStoreWeakRef) -> Self { Self { id, log_store, @@ -48,7 +48,7 @@ impl TextContainer { } pub fn insert(&mut self, pos: usize, text: &str) -> Option { - let id = if let Ok(mut store) = self.log_store.write() { + let id = if let Ok(mut store) = self.log_store.upgrade().unwrap().write() { let id = store.next_id(); let slice = ListSlice::from_range(self.raw_str.alloc(text)); self.state.insert(pos, slice.clone()); @@ -69,7 +69,7 @@ impl TextContainer { } pub fn delete(&mut self, pos: usize, len: usize) -> Option { - let id = if let Ok(mut store) = self.log_store.write() { + let id = if let Ok(mut store) = self.log_store.upgrade().unwrap().write() { let id = store.next_id(); let op = Op::new( id, diff --git a/crates/loro-core/src/fuzz.rs b/crates/loro-core/src/fuzz.rs index 8b9baf04..912d73a2 100644 --- a/crates/loro-core/src/fuzz.rs +++ b/crates/loro-core/src/fuzz.rs @@ -87,22 +87,19 @@ impl Actionable for String { } } Action::Del { pos, len } => { - if self.len() == 0 { + if self.is_empty() { *len = 0; + *pos = 0; return; } - let mut changed = false; while !self.is_char_boundary(*pos) { *pos = (*pos + 1) % self.len(); - changed = true; } - if changed { - *len = 1; - while !self.is_char_boundary(*pos + *len) { - *len += 1; - } + *len = (*len).min(self.len() - (*pos)); + while !self.is_char_boundary(*pos + *len) { + *len += 1; } } } @@ -131,7 +128,7 @@ impl Actionable for TextContainer { } pub fn test_single_client(mut actions: Vec) { - let mut store = LoroCore::new(Default::default(), None); + let mut store = LoroCore::new(Default::default(), Some(1)); let mut text_container = store.get_text_container("haha".into()); let mut ground_truth = String::new(); let mut applied = Vec::new(); @@ -159,30 +156,238 @@ mod test { #[test] fn test() { - test_single_client(vec![ + test_single_client(vec! [ Ins { - content: "璤\u{13}\u{13}\u{13}".into(), - pos: 243, + content: "\u{16}\u{16}\u{16}\u{16}\u{16}#####BBBBSSSSSSSSS".into(), + pos: 60797853338129363, }, Ins { - content: "\0\0\0\0?\0\0\0".into(), - pos: 11240984669950312448, + content: "\u{13}T0\u{18}5\u{13}".into(), + pos: 1369375761697341439, }, Ins { - content: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0".into(), - pos: 129, + content: "\0\0\0SS".into(), + pos: 280733345338323, + }, + Ins { + content: "**".into(), + pos: 5444570, + }, + Ins { + content: "\u{13}".into(), + pos: 5692550972993381338, + }, + Ins { + content: "OOOOOOOOOOOOOOBBBBBBBBBBBBBBBBB#\0\0####".into(), + pos: 138028458976, }, Ins { content: "".into(), - pos: 91344728162323, + pos: 267263250998051, }, Ins { content: "".into(), - pos: 6148914691236517150, + pos: 4774378554966147091, }, - Del { - pos: 12460594852558187539, - len: 1430476722683303114, + Ins { + content: "BBBBB#\0\0######## \0\0\0######".into(), + pos: 3038287259207217298, + }, + Ins { + content: "".into(), + pos: 16645325113485036074, + }, + Ins { + content: "".into(), + pos: 23362835702677503, + }, + Ins { + content: "S".into(), + pos: 280733345338323, + }, + Ins { + content: "*UUU".into(), + pos: 2761092332, + }, + Ins { + content: "\u{5ec}".into(), + pos: 15332975680940594378, + }, + Ins { + content: "".into(), + pos: 3038287259199214554, + }, + Ins { + content: "PPPPPPPPPPPPP\u{13}".into(), + pos: 6004374254117322995, + }, + Ins { + content: "SSSSSS".into(), + pos: 48379484722131, + }, + Ins { + content: ",\0\0\0UUUU".into(), + pos: 2761092332, + }, + Ins { + content: "\u{5ec}".into(), + pos: 15332975680940594378, + }, + Ins { + content: "".into(), + pos: 3038287259199214554, + }, + Ins { + content: "".into(), + pos: 5787213827046133840, + }, + Ins { + content: "PPPPPPPPPPPPPPPP*****".into(), + pos: 2762368, + }, + Ins { + content: "".into(), + pos: 0, + }, + Ins { + content: "".into(), + pos: 0, + }, + Ins { + content: "".into(), + pos: 3038287259199220266, + }, + Ins { + content: "*\0\u{13}EEEEEEEEEEEEEEEEEEEEEEEE".into(), + pos: 4179340455027348442, + }, + Ins { + content: "\0UUUU".into(), + pos: 2761092332, + }, + Ins { + content: "\u{5ec}".into(), + pos: 15332976539934053578, + }, + Ins { + content: "ڨ\0\0\0*******************".into(), + pos: 3038287259199220352, + }, + Ins { + content: "*&*****".into(), + pos: 6004234345560396434, + }, + Ins { + content: "".into(), + pos: 3038287259199220307, + }, + Ins { + content: "******".into(), + pos: 3038287259889816210, + }, + Ins { + content: "*****".into(), + pos: 11350616413819538, + }, + Ins { + content: "".into(), + pos: 6004234345560363859, + }, + Ins { + content: "S".into(), + pos: 60797853338129363, + }, + Ins { + content: "\u{13}T3\u{18}5\u{13}".into(), + pos: 1369375761697341439, + }, + Ins { + content: "\0\0\0SS".into(), + pos: 280733345338323, + }, + Ins { + content: "*UUU".into(), + pos: 2761092332, + }, + Ins { + content: "\u{5ec}".into(), + pos: 15332975680940594378, + }, + Ins { + content: "".into(), + pos: 3038287259199214554, + }, + Ins { + content: "".into(), + pos: 5787213827046133840, + }, + Ins { + content: "".into(), + pos: 5787213827046133840, + }, + Ins { + content: "PPPP*****".into(), + pos: 2762368, + }, + Ins { + content: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0******".into(), + pos: 3038287259199220266, + }, + Ins { + content: "EEEEEEEEEEEEEEEEEEEEEEE".into(), + pos: 4179340455027348442, + }, + Ins { + content: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 ,\0\0\0UUUU".into(), + pos: 2761092332, + }, + Ins { + content: "\u{5ec}".into(), + pos: 14483766535198004426, + }, + Ins { + content: "".into(), + pos: 3038240898625886739, + }, + Ins { + content: "*************".into(), + pos: 3038287259199220352, + }, + Ins { + content: "*&*****".into(), + pos: 6004234345560396434, + }, + Ins { + content: "S*********\0*******".into(), + pos: 3038287259889816210, + }, + Ins { + content: "*****".into(), + pos: 11350616413819538, + }, + Ins { + content: "SSSSSSSSSSSSS".into(), + pos: 60797853338129363, + }, + Ins { + content: "\u{13}T4\u{18}5\u{13}".into(), + pos: 1369375761697341439, + }, + Ins { + content: "\0\0\0SS".into(), + pos: 3834029289772372947, + }, + Ins { + content: "55555555555555555555555555555555555555555555555555555555555555555555555555555555555".into(), + pos: 280603991029045, + }, + Ins { + content: "".into(), + pos: 356815350314, + }, + Ins { + content: "\u{13}\0\u{13}".into(), + pos: 1369095330717705178, }, ]) } diff --git a/crates/loro-core/src/log_store.rs b/crates/loro-core/src/log_store.rs index edfefa4f..60b355de 100644 --- a/crates/loro-core/src/log_store.rs +++ b/crates/loro-core/src/log_store.rs @@ -267,7 +267,7 @@ impl LogStore { #[inline] fn apply_remote_op(&mut self, change: &Change, op: &Op) { let mut container = self.container.write().unwrap(); - let container = container.get_or_create(op.container(), self.to_self.upgrade().unwrap()); + let container = container.get_or_create(op.container(), self.to_self.clone()); container.apply(&OpProxy::new(change, op, None), self); } diff --git a/crates/loro-core/src/loro.rs b/crates/loro-core/src/loro.rs index 3327547e..b99f7130 100644 --- a/crates/loro-core/src/loro.rs +++ b/crates/loro-core/src/loro.rs @@ -50,7 +50,7 @@ impl LoroCore { a.map_mut(|x| { x.get_or_create( &ContainerID::new_root(name, container), - self.log_store.clone(), + Arc::downgrade(&self.log_store), ) }) } @@ -63,7 +63,7 @@ impl LoroCore { a.map_mut(|x| { x.get_or_create( &ContainerID::new_root(name, ContainerType::Map), - self.log_store.clone(), + Arc::downgrade(&self.log_store), ) .as_map_mut() .unwrap() @@ -78,7 +78,7 @@ impl LoroCore { a.map_mut(|x| { x.get_or_create( &ContainerID::new_root(name, ContainerType::Text), - self.log_store.clone(), + Arc::downgrade(&self.log_store), ) .as_text_mut() .unwrap()