diff --git a/crates/loro-internal/fuzz/Cargo.lock b/crates/loro-internal/fuzz/Cargo.lock index baed6a8c..5006cbf7 100644 --- a/crates/loro-internal/fuzz/Cargo.lock +++ b/crates/loro-internal/fuzz/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "arbitrary" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d47fbf90d5149a107494b15a7dc8d69b351be2db3bb9691740e88ec17fd880" +checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" dependencies = [ "derive_arbitrary", ] @@ -107,6 +107,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +[[package]] +name = "compact-bytes" +version = "0.1.0" +dependencies = [ + "append-only-bytes", + "fxhash", + "linked-hash-map", +] + [[package]] name = "crdt-list" version = "0.4.0" @@ -167,13 +176,13 @@ checksum = "364ff57c5031fee39b026dcdfdc9c7dc1d1d79451bfdacba90f040524b766254" [[package]] name = "derive_arbitrary" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903dff04948f22033ca30232ab8eca2c3fc4c913a8b6a34ee5199699814817f" +checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.105", + "syn 2.0.25", ] [[package]] @@ -194,6 +203,18 @@ dependencies = [ "syn 1.0.105", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.25", +] + [[package]] name = "enum_dispatch" version = "0.3.11" @@ -352,6 +373,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "lock_api" version = "0.4.9" @@ -371,6 +398,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loro-common" +version = "0.1.0" +dependencies = [ + "arbitrary", + "enum-as-inner 0.6.0", + "fxhash", + "rle", + "serde", + "string_cache", + "thiserror", +] + [[package]] name = "loro-internal" version = "0.1.0" @@ -378,15 +418,18 @@ dependencies = [ "append-only-bytes", "arbitrary", "arref", + "compact-bytes", "crdt-list", "debug-log", - "enum-as-inner", + "enum-as-inner 0.5.1", "enum_dispatch", "fxhash", "generic-btree", "im", "itertools", "jumprope", + "loro-common", + "loro-preload", "num", "postcard", "rand", @@ -412,6 +455,15 @@ dependencies = [ "loro-internal", ] +[[package]] +name = "loro-preload" +version = "0.1.0" +dependencies = [ + "loro-common", + "serde", + "serde_columnar", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" @@ -709,7 +761,7 @@ dependencies = [ "bumpalo", "crdt-list", "debug-log", - "enum-as-inner", + "enum-as-inner 0.5.1", "fxhash", "heapless", "num", @@ -871,9 +923,9 @@ checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd" [[package]] name = "string_cache" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", @@ -937,22 +989,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.105", + "syn 2.0.25", ] [[package]] diff --git a/crates/loro-internal/src/dag/iter.rs b/crates/loro-internal/src/dag/iter.rs index df7e83d6..cdd6dbc6 100644 --- a/crates/loro-internal/src/dag/iter.rs +++ b/crates/loro-internal/src/dag/iter.rs @@ -197,6 +197,7 @@ pub(crate) struct IterReturn<'a, T> { impl<'a, T: DagNode, D: Dag> DagCausalIter<'a, D> { pub fn new(dag: &'a D, from: Frontiers, target: IdSpanVector) -> Self { + debug_dbg!(&from, &target); let mut in_degrees: FxHashMap = FxHashMap::default(); let mut succ: BTreeMap = BTreeMap::default(); let mut stack = Vec::new(); diff --git a/crates/loro-internal/src/fuzz.rs b/crates/loro-internal/src/fuzz.rs index e6ebda5f..2193d49a 100644 --- a/crates/loro-internal/src/fuzz.rs +++ b/crates/loro-internal/src/fuzz.rs @@ -313,12 +313,18 @@ fn check_synced_refactored(sites: &mut [LoroApp]) { debug_log::group!("checking {} with {}", i, j); let (a, b) = array_mut_ref!(sites, [i, j]); { - debug_log::group!("Import {}", i); - a.import(&b.export_from(&a.vv_cloned())).unwrap(); - debug_log::group_end!(); + if (i + j) % 2 == 1 { + debug_log::group!("Import {}'s Snapshot to {}", j, i); + a.import(&b.export_snapshot()).unwrap(); + debug_log::group_end!(); + } else { + debug_log::group!("Import {} to {}", j, i); + a.import(&b.export_from(&a.vv_cloned())).unwrap(); + debug_log::group_end!(); + } } { - debug_log::group!("Import {}", j); + debug_log::group!("Import {} to {}", i, j); b.import(&a.export_from(&b.vv_cloned())).unwrap(); debug_log::group_end!(); } @@ -1222,6 +1228,30 @@ mod test { ); } + #[test] + fn snapshot() { + test_multi_sites_refactored( + 8, + &mut [ + Ins { + content: 32818, + pos: 0, + site: 1, + }, + Ins { + content: 12850, + pos: 0, + site: 3, + }, + Ins { + content: 13621, + pos: 3, + site: 1, + }, + ], + ) + } + #[test] fn mini_r() { minify_error(8, vec![], test_multi_sites_refactored, normalize) diff --git a/crates/loro-internal/src/refactor/diff_calc.rs b/crates/loro-internal/src/refactor/diff_calc.rs index a56113d1..9c7fcd6b 100644 --- a/crates/loro-internal/src/refactor/diff_calc.rs +++ b/crates/loro-internal/src/refactor/diff_calc.rs @@ -1,5 +1,6 @@ use std::{cmp::Ordering, collections::BinaryHeap}; +use debug_log::debug_dbg; use enum_dispatch::enum_dispatch; use fxhash::{FxHashMap, FxHashSet}; @@ -59,10 +60,10 @@ impl DiffCalculator { let (lca, iter) = oplog.iter_from_lca_causally(before, before_frontiers, after, after_frontiers); for (change, vv) in iter { + let mut visited = FxHashSet::default(); for op in change.ops.iter() { - let container_id = arena.get_container_id(op.container).unwrap(); let calculator = self.calculators.entry(op.container).or_insert_with(|| { - let mut new = match container_id.container_type() { + let mut new = match op.container.get_type() { crate::ContainerType::Text => { ContainerDiffCalculator::Text(TextDiffCalculator::default()) } @@ -77,7 +78,17 @@ impl DiffCalculator { new }); - calculator.apply_change(oplog, RichOp::new_by_change(change, op), &vv.borrow()); + if visited.contains(&op.container) { + // don't checkout if we have already checked out this container in this round + calculator.apply_change(oplog, RichOp::new_by_change(change, op), None); + } else { + calculator.apply_change( + oplog, + RichOp::new_by_change(change, op), + Some(&vv.borrow()), + ); + visited.insert(op.container); + } } } @@ -103,7 +114,12 @@ impl DiffCalculator { #[enum_dispatch] pub trait DiffCalculatorTrait { fn start_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector); - fn apply_change(&mut self, oplog: &OpLog, op: crate::op::RichOp, vv: &crate::VersionVector); + fn apply_change( + &mut self, + oplog: &OpLog, + op: crate::op::RichOp, + vv: Option<&crate::VersionVector>, + ); fn stop_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector); fn calculate_diff( &mut self, @@ -176,7 +192,7 @@ impl DiffCalculatorTrait for MapDiffCalculator { &mut self, oplog: &super::oplog::OpLog, op: crate::op::RichOp, - _vv: &crate::VersionVector, + _vv: Option<&crate::VersionVector>, ) { let map = op.op().content.as_map().unwrap(); let value = oplog.arena.get_value(map.value as usize); @@ -252,8 +268,15 @@ impl DiffCalculatorTrait for ListDiffCalculator { self.tracker.checkout(vv); } - fn apply_change(&mut self, _oplog: &OpLog, op: crate::op::RichOp, vv: &crate::VersionVector) { - self.tracker.checkout(vv); + fn apply_change( + &mut self, + _oplog: &OpLog, + op: crate::op::RichOp, + vv: Option<&crate::VersionVector>, + ) { + if let Some(vv) = vv { + self.tracker.checkout(vv); + } self.tracker.track_apply(&op); } @@ -293,9 +316,13 @@ impl DiffCalculatorTrait for TextDiffCalculator { &mut self, _oplog: &super::oplog::OpLog, op: crate::op::RichOp, - vv: &crate::VersionVector, + vv: Option<&crate::VersionVector>, ) { - self.tracker.checkout(vv); + if let Some(vv) = vv { + self.tracker.checkout(vv); + } + + debug_dbg!(&op, self.tracker.len()); self.tracker.track_apply(&op); } diff --git a/crates/loro-internal/src/refactor/loro.rs b/crates/loro-internal/src/refactor/loro.rs index 988fa4ce..e2ffea0e 100644 --- a/crates/loro-internal/src/refactor/loro.rs +++ b/crates/loro-internal/src/refactor/loro.rs @@ -157,8 +157,6 @@ impl LoroApp { } else { let app = LoroApp::new(); decode_app_snapshot(&app, &input[1..])?; - dbg!(&app.oplog.lock().unwrap()); - dbg!(&app.state.lock().unwrap().states); let oplog = self.oplog.lock().unwrap(); let updates = app.export_from(oplog.vv()); drop(oplog); diff --git a/crates/loro-internal/src/refactor/oplog.rs b/crates/loro-internal/src/refactor/oplog.rs index f5f7115c..37c7800e 100644 --- a/crates/loro-internal/src/refactor/oplog.rs +++ b/crates/loro-internal/src/refactor/oplog.rs @@ -448,7 +448,7 @@ impl OpLog { } inner_vv.extend_to_include_end_id(change.id); - // debug_log::debug_dbg!(&change, &inner_vv); + debug_log::debug_dbg!(&change, &inner_vv); Some((change, vv.clone())) } else { debug_log::group_end!();