1use self::block_encode::{
2 decode_block, decode_cids, decode_header, encode_block, ChangesBlockHeader,
3};
4use super::{loro_dag::AppDagNodeInner, AppDagNode};
5use crate::sync::Mutex;
6use crate::{
7 arena::SharedArena,
8 change::Change,
9 estimated_size::EstimatedSize,
10 kv_store::KvStore,
11 op::Op,
12 parent::register_container_and_parent_link,
13 version::{Frontiers, ImVersionVector},
14 InternalString, VersionVector,
15};
16use block_encode::decode_block_range;
17use bytes::Bytes;
18use itertools::Itertools;
19use loro_common::{
20 ContainerID, Counter, HasCounterSpan, HasId, HasIdSpan, HasLamportSpan, IdLp, IdSpan, Lamport,
21 LoroError, LoroResult, PeerID, ID,
22};
23use loro_kv_store::{mem_store::MemKvConfig, MemKvStore};
24use once_cell::sync::OnceCell;
25use rle::{HasLength, Mergable, RlePush, RleVec, Sliceable};
26use rustc_hash::FxHashSet;
27use std::sync::atomic::AtomicI64;
28#[cfg(test)]
29use std::sync::atomic::AtomicUsize;
30use std::{
31 cmp::Ordering,
32 collections::{BTreeMap, VecDeque},
33 ops::{Bound, Deref},
34 sync::Arc,
35};
36use tracing::{info_span, warn};
37mod block_encode;
38mod block_meta_encode;
39pub(super) mod iter;
40
41#[cfg(not(test))]
42const MAX_BLOCK_SIZE: usize = 1024 * 4;
43#[cfg(test)]
44const MAX_BLOCK_SIZE: usize = 128;
45const MAX_ROOT_HISTORY_NAME_BYTES: usize = 256 * 1024;
46
47#[derive(Debug, Clone)]
67pub struct ChangeStore {
68 inner: Arc<Mutex<ChangeStoreInner>>,
69 arena: SharedArena,
70 external_kv: Arc<Mutex<dyn KvStore>>,
75 external_vv: Arc<Mutex<VersionVector>>,
77 merge_interval: Arc<AtomicI64>,
78 root_history_names: Arc<Mutex<RootHistoryNamesState>>,
79 #[cfg(test)]
80 root_history_scan_count: Arc<AtomicUsize>,
81}
82
83#[derive(Debug, Default)]
87enum RootHistoryNamesState {
88 #[default]
89 Uninitialized,
90 Valid {
91 names: FxHashSet<InternalString>,
92 name_bytes: usize,
93 },
94 Invalid,
95}
96
97fn record_root_name(
99 names: &mut FxHashSet<InternalString>,
100 name_bytes: &mut usize,
101 cid: &ContainerID,
102) -> bool {
103 let ContainerID::Root { name, .. } = cid else {
104 return true;
105 };
106 if cid.is_mergeable() || names.contains(name) {
107 return true;
108 }
109
110 let Some(new_bytes) = name_bytes.checked_add(name.len()) else {
111 return false;
112 };
113 if new_bytes > MAX_ROOT_HISTORY_NAME_BYTES {
114 return false;
115 }
116
117 names.insert(name.clone());
118 *name_bytes = new_bytes;
119 true
120}
121
122#[derive(Debug, Clone)]
123struct ChangeStoreInner {
124 start_vv: ImVersionVector,
127 start_frontiers: Frontiers,
129 mem_parsed_kv: BTreeMap<ID, Arc<ChangesBlock>>,
131}
132
133#[derive(Debug)]
134pub(crate) struct ChangeStoreRollback {
135 old_vv: VersionVector,
136 blocks_before_mutation: BTreeMap<ID, Arc<ChangesBlock>>,
137}
138
139impl ChangeStoreRollback {
140 pub(crate) fn new(old_vv: VersionVector) -> Self {
141 Self {
142 old_vv,
143 blocks_before_mutation: BTreeMap::new(),
144 }
145 }
146
147 fn record_block_before_mutation(&mut self, id: ID, block: Arc<ChangesBlock>) {
148 let old_end = self.old_vv.get(&id.peer).copied().unwrap_or(0);
149 if id.counter >= old_end {
150 return;
151 }
152
153 self.blocks_before_mutation.entry(id).or_insert(block);
154 }
155}
156
157#[derive(Debug, Clone)]
158pub(crate) struct ChangesBlock {
159 peer: PeerID,
160 counter_range: (Counter, Counter),
161 lamport_range: (Lamport, Lamport),
162 estimated_size: usize,
164 flushed: bool,
165 content: ChangesBlockContent,
166}
167
168#[derive(Clone)]
169pub(crate) enum ChangesBlockContent {
170 Changes(Arc<Vec<Change>>),
171 Bytes(ChangesBlockBytes),
172 Both(Arc<Vec<Change>>, ChangesBlockBytes),
173}
174
175#[derive(Clone)]
177pub(crate) struct ChangesBlockBytes {
178 bytes: Bytes,
179 header: OnceCell<Arc<ChangesBlockHeader>>,
180}
181
182pub const START_VV_KEY: &[u8] = b"sv";
183pub const START_FRONTIERS_KEY: &[u8] = b"sf";
184pub const VV_KEY: &[u8] = b"vv";
185pub const FRONTIERS_KEY: &[u8] = b"fr";
186
187impl ChangeStore {
188 pub fn new_mem(a: &SharedArena, merge_interval: Arc<AtomicI64>) -> Self {
189 Self {
190 inner: Arc::new(Mutex::new(ChangeStoreInner {
191 start_vv: ImVersionVector::new(),
192 start_frontiers: Frontiers::default(),
193 mem_parsed_kv: BTreeMap::new(),
194 })),
195 arena: a.clone(),
196 external_vv: Arc::new(Mutex::new(VersionVector::new())),
197 external_kv: Arc::new(Mutex::new(MemKvStore::new(MemKvConfig::default()))),
198 merge_interval,
200 root_history_names: Arc::new(Mutex::new(RootHistoryNamesState::Uninitialized)),
201 #[cfg(test)]
202 root_history_scan_count: Arc::new(AtomicUsize::new(0)),
203 }
204 }
205
206 #[cfg(test)]
207 fn new_for_test() -> Self {
208 Self::new_mem(&SharedArena::new(), Arc::new(AtomicI64::new(0)))
209 }
210
211 pub(super) fn encode_all(&self, vv: &VersionVector, frontiers: &Frontiers) -> Bytes {
212 self.flush_and_compact(vv, frontiers);
213 let mut kv = self.external_kv.lock();
214 kv.export_all()
215 }
216
217 #[tracing::instrument(skip(self), level = "debug")]
218 pub(super) fn export_from(
219 &self,
220 start_vv: &VersionVector,
221 start_frontiers: &Frontiers,
222 latest_vv: &VersionVector,
223 latest_frontiers: &Frontiers,
224 ) -> Bytes {
225 let new_store = ChangeStore::new_mem(&self.arena, self.merge_interval.clone());
226 for span in latest_vv.sub_iter(start_vv) {
227 for c in self.iter_changes(span) {
230 let start = ((start_vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
231 as usize)
232 .min(c.atom_len());
233 let end = ((latest_vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
234 as usize)
235 .min(c.atom_len());
236
237 if start == end {
238 continue;
239 }
240
241 let ch = c.slice(start, end);
242 new_store.insert_change(ch, false, false);
243 }
244 }
245
246 loro_common::debug!(
247 "start_vv={:?} start_frontiers={:?}",
248 &start_vv,
249 start_frontiers
250 );
251 new_store.encode_from(start_vv, start_frontiers, latest_vv, latest_frontiers)
252 }
253
254 pub(super) fn export_blocks_in_range<W: std::io::Write>(&self, spans: &[IdSpan], w: &mut W) {
255 let new_store = ChangeStore::new_mem(&self.arena, self.merge_interval.clone());
256 for span in spans {
257 let mut span = *span;
258 span.normalize_();
259 if span.counter.end <= 0 {
260 continue;
261 }
262
263 span.counter.start = span.counter.start.max(0);
264 span.counter.end = span.counter.end.max(0);
265 if span.counter.start >= span.counter.end {
266 continue;
267 }
268
269 for c in self.iter_changes(span) {
272 let start = ((span.counter.start - c.id.counter).max(0) as usize).min(c.atom_len());
273 let end = ((span.counter.end - c.id.counter).max(0) as usize).min(c.atom_len());
274 if start == end {
275 continue;
276 }
277
278 let ch = c.slice(start, end);
279 new_store.insert_change(ch, false, false);
280 }
281 }
282
283 encode_blocks_in_store(new_store, &self.arena, w);
284 }
285
286 fn encode_from(
287 &self,
288 start_vv: &VersionVector,
289 start_frontiers: &Frontiers,
290 latest_vv: &VersionVector,
291 latest_frontiers: &Frontiers,
292 ) -> Bytes {
293 {
294 let mut store = self.external_kv.lock();
295 store.set(START_VV_KEY, start_vv.encode().into());
296 store.set(START_FRONTIERS_KEY, start_frontiers.encode().into());
297 let mut inner = self.inner.lock();
298 inner.start_frontiers = start_frontiers.clone();
299 inner.start_vv = ImVersionVector::from_vv(start_vv);
300 }
301 self.flush_and_compact(latest_vv, latest_frontiers);
302 self.external_kv.lock().export_all()
303 }
304
305 pub(crate) fn decode_snapshot_for_updates(
306 bytes: Bytes,
307 arena: &SharedArena,
308 self_vv: &VersionVector,
309 ) -> Result<Vec<Change>, LoroError> {
310 let change_store = ChangeStore::new_mem(arena, Arc::new(AtomicI64::new(0)));
311 let _ = change_store.import_all(bytes)?;
312 let mut changes = Vec::new();
313 change_store.visit_all_changes(&mut |c| {
314 let cnt_threshold = self_vv.get(&c.id.peer).copied().unwrap_or(0);
315 if c.id.counter >= cnt_threshold {
316 changes.push(c.clone());
317 return;
318 }
319
320 let change_end = c.ctr_end();
321 if change_end > cnt_threshold {
322 changes.push(c.slice((cnt_threshold - c.id.counter) as usize, c.atom_len()));
323 }
324 });
325
326 Ok(changes)
327 }
328
329 pub(crate) fn decode_block_bytes(
330 bytes: Bytes,
331 arena: &SharedArena,
332 self_vv: &VersionVector,
333 ) -> LoroResult<Vec<Change>> {
334 let mut ans = ChangesBlockBytes::new(bytes).parse(arena)?;
335 if ans.is_empty() {
336 return Ok(ans);
337 }
338
339 let start = self_vv.get(&ans[0].peer()).copied().unwrap_or(0);
340 ans.retain_mut(|c| {
341 if c.id.counter >= start {
342 true
343 } else if c.ctr_end() > start {
344 *c = c.slice((start - c.id.counter) as usize, c.atom_len());
345 true
346 } else {
347 false
348 }
349 });
350
351 Ok(ans)
352 }
353
354 pub(crate) fn rollback_import(&self, rollback: ChangeStoreRollback) {
355 let mut inner = self.inner.lock();
358 inner.mem_parsed_kv.retain(|id, _| {
359 let old_end = rollback.old_vv.get(&id.peer).copied().unwrap_or(0);
360 id.counter < old_end
361 });
362
363 for (id, block) in rollback.blocks_before_mutation {
364 inner.mem_parsed_kv.insert(id, block);
365 }
366 }
367
368 pub fn get_dag_nodes_that_contains(&self, id: ID) -> Option<Vec<AppDagNode>> {
369 let block = self.get_block_that_contains(id)?;
370 Some(block.content.iter_dag_nodes())
371 }
372
373 pub fn get_last_dag_nodes_for_peer(&self, peer: PeerID) -> Option<Vec<AppDagNode>> {
374 let block = self.get_the_last_block_of_peer(peer)?;
375 Some(block.content.iter_dag_nodes())
376 }
377
378 pub fn visit_all_changes(&self, f: &mut dyn FnMut(&Change)) {
379 self.ensure_block_loaded_in_range(Bound::Unbounded, Bound::Unbounded);
380 let mut inner = self.inner.lock();
381 for (id, block) in inner.mem_parsed_kv.iter_mut() {
382 if let Err(err) = block.ensure_changes(&self.arena) {
383 warn!(block_id = ?id, ?err, "failed to parse change block");
384 continue;
385 }
386 for c in block.content.try_changes().unwrap() {
387 f(c);
388 }
389 }
390 }
391
392 fn build_root_history_names(&self) -> RootHistoryNamesState {
393 let mut names = FxHashSet::default();
394 let mut name_bytes = 0;
395
396 {
397 let external = self.external_kv.lock();
398 for (key, bytes) in external.scan(Bound::Unbounded, Bound::Unbounded) {
399 if key.len() != 12 {
400 continue;
401 }
402 let header = match decode_header(&bytes)
403 .and_then(|header| decode_cids(&bytes, Some(header)))
404 {
405 Ok(header) => header,
406 Err(_) => return RootHistoryNamesState::Invalid,
407 };
408 let Some(cids) = header.cids.get() else {
409 return RootHistoryNamesState::Invalid;
410 };
411 for cid in cids.iter() {
412 if !record_root_name(&mut names, &mut name_bytes, cid) {
413 return RootHistoryNamesState::Invalid;
414 }
415 }
416 }
417 }
418
419 let inner = self.inner.lock();
420 for block in inner.mem_parsed_kv.values() {
421 match &block.content {
422 ChangesBlockContent::Changes(changes) | ChangesBlockContent::Both(changes, _) => {
423 for change in changes.iter() {
424 for op in change.ops.iter() {
425 let Some(cid) = self.arena.idx_to_id(op.container) else {
426 return RootHistoryNamesState::Invalid;
427 };
428 if !record_root_name(&mut names, &mut name_bytes, &cid) {
429 return RootHistoryNamesState::Invalid;
430 }
431 }
432 }
433 }
434 ChangesBlockContent::Bytes(bytes) => {
435 let header = bytes.header.get().map(|header| header.as_ref().clone());
436 let header = match decode_cids(&bytes.bytes, header) {
437 Ok(header) => header,
438 Err(_) => return RootHistoryNamesState::Invalid,
439 };
440 let Some(cids) = header.cids.get() else {
441 return RootHistoryNamesState::Invalid;
442 };
443 for cid in cids.iter() {
444 if !record_root_name(&mut names, &mut name_bytes, cid) {
445 return RootHistoryNamesState::Invalid;
446 }
447 }
448 }
449 }
450 }
451
452 RootHistoryNamesState::Valid { names, name_bytes }
453 }
454
455 fn record_change_in_root_history_names(&self, change: &Change) {
456 let mut cached = self.root_history_names.lock();
457 let RootHistoryNamesState::Valid { names, name_bytes } = &mut *cached else {
458 return;
459 };
460
461 for op in change.ops.iter() {
462 let recorded = self
463 .arena
464 .idx_to_id(op.container)
465 .is_some_and(|cid| record_root_name(names, name_bytes, &cid));
466 if !recorded {
467 *cached = RootHistoryNamesState::Invalid;
468 return;
469 }
470 }
471 }
472
473 pub(crate) fn old_history_may_touch_root_names(
481 &self,
482 names: &FxHashSet<InternalString>,
483 ) -> bool {
484 if names.is_empty() {
485 return false;
486 }
487
488 let mut cached = self.root_history_names.lock();
489 if matches!(*cached, RootHistoryNamesState::Uninitialized) {
490 #[cfg(test)]
491 self.root_history_scan_count
492 .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
493 *cached = self.build_root_history_names();
494 }
495
496 match &*cached {
497 RootHistoryNamesState::Valid {
498 names: history_names,
499 ..
500 } => names.iter().any(|name| history_names.contains(name)),
501 RootHistoryNamesState::Invalid | RootHistoryNamesState::Uninitialized => true,
502 }
503 }
504
505 #[cfg(test)]
506 pub(crate) fn root_history_scan_count_for_test(&self) -> usize {
507 self.root_history_scan_count
508 .load(std::sync::atomic::Ordering::Relaxed)
509 }
510
511 pub(crate) fn iter_blocks(&self, id_span: IdSpan) -> Vec<(Arc<ChangesBlock>, usize, usize)> {
512 if id_span.counter.start == id_span.counter.end {
513 return vec![];
514 }
515
516 assert!(id_span.counter.start < id_span.counter.end);
517 self.ensure_block_loaded_in_range(
518 Bound::Included(id_span.id_start()),
519 Bound::Excluded(id_span.id_end()),
520 );
521 let mut inner = self.inner.lock();
522 let next_back = inner.mem_parsed_kv.range(..=id_span.id_start()).next_back();
523 match next_back {
524 None => {
525 return vec![];
526 }
527 Some(next_back) => {
528 if next_back.0.peer != id_span.peer {
529 return vec![];
530 }
531 }
532 }
533 let start_counter = next_back.map(|(id, _)| id.counter).unwrap_or(0);
534 let ans = inner
535 .mem_parsed_kv
536 .range_mut(
537 ID::new(id_span.peer, start_counter)..ID::new(id_span.peer, id_span.counter.end),
538 )
539 .filter_map(|(_id, block)| {
540 if block.counter_range.1 < id_span.counter.start {
541 return None;
542 }
543
544 if let Err(err) = block.ensure_changes(&self.arena) {
545 warn!(block_id = ?_id, ?err, "failed to parse change block");
546 return None;
547 }
548 let changes = block.content.try_changes().unwrap();
549 let start;
550 let end;
551 if id_span.counter.start <= block.counter_range.0
552 && id_span.counter.end >= block.counter_range.1
553 {
554 start = 0;
555 end = changes.len();
556 } else {
557 start = block
558 .get_change_index_by_counter(id_span.counter.start)
559 .unwrap_or_else(|x| x);
560
561 match block.get_change_index_by_counter(id_span.counter.end - 1) {
562 Ok(e) => {
563 end = e + 1;
564 }
565 Err(0) => return None,
566 Err(e) => {
567 end = e;
568 }
569 }
570 }
571 if start == end {
572 return None;
573 }
574
575 Some((block.clone(), start, end))
576 })
577 .collect_vec();
579
580 ans
581 }
582
583 pub fn iter_changes(&self, id_span: IdSpan) -> impl Iterator<Item = BlockChangeRef> + '_ {
584 let v = self.iter_blocks(id_span);
585 #[cfg(debug_assertions)]
586 {
587 if !v.is_empty() {
588 assert_eq!(v[0].0.peer, id_span.peer);
589 assert_eq!(v.last().unwrap().0.peer, id_span.peer);
590 {
591 let (block, start, _end) = v.first().unwrap();
593 let changes = block.content.try_changes().unwrap();
594 assert!(changes[*start].id.counter <= id_span.counter.start);
595 }
596 {
597 let (block, _start, end) = v.last().unwrap();
599 let changes = block.content.try_changes().unwrap();
600 assert!(changes[*end - 1].ctr_end() >= id_span.counter.end);
601 assert!(changes[*end - 1].id.counter < id_span.counter.end);
602 }
603 }
604 }
605
606 v.into_iter().flat_map(move |(block, start, end)| {
607 (start..end).map(move |i| BlockChangeRef {
608 change_index: i,
609 block: block.clone(),
610 })
611 })
612 }
613
614 #[allow(dead_code)]
615 pub(crate) fn get_blocks_in_range(&self, id_span: IdSpan) -> VecDeque<Arc<ChangesBlock>> {
616 let mut inner = self.inner.lock();
617 let start_counter = inner
618 .mem_parsed_kv
619 .range(..=id_span.id_start())
620 .next_back()
621 .map(|(id, _)| id.counter)
622 .unwrap_or(0);
623 let vec = inner
624 .mem_parsed_kv
625 .range_mut(
626 ID::new(id_span.peer, start_counter)..ID::new(id_span.peer, id_span.counter.end),
627 )
628 .filter_map(|(_id, block)| {
629 if block.counter_range.1 < id_span.counter.start {
630 return None;
631 }
632
633 if let Err(err) = block.ensure_changes(&self.arena) {
634 warn!(block_id = ?_id, ?err, "failed to parse change block");
635 return None;
636 }
637 Some(block.clone())
638 })
639 .collect();
641 vec
642 }
643
644 pub(crate) fn get_block_that_contains(&self, id: ID) -> Option<Arc<ChangesBlock>> {
645 self.ensure_block_loaded_in_range(Bound::Included(id), Bound::Included(id));
646 let inner = self.inner.lock();
647 let block = inner
648 .mem_parsed_kv
649 .range(..=id)
650 .next_back()
651 .filter(|(_, block)| {
652 block.peer == id.peer
653 && block.counter_range.0 <= id.counter
654 && id.counter < block.counter_range.1
655 })
656 .map(|(_, block)| block.clone());
657
658 block
659 }
660
661 pub(crate) fn get_the_last_block_of_peer(&self, peer: PeerID) -> Option<Arc<ChangesBlock>> {
662 let end_id = ID::new(peer, Counter::MAX);
663 self.ensure_id_lte(end_id);
664 let inner = self.inner.lock();
665 let block = inner
666 .mem_parsed_kv
667 .range(..=end_id)
668 .next_back()
669 .filter(|(_, block)| block.peer == peer)
670 .map(|(_, block)| block.clone());
671
672 block
673 }
674
675 pub fn change_num(&self) -> usize {
676 self.ensure_block_loaded_in_range(Bound::Unbounded, Bound::Unbounded);
677 let mut inner = self.inner.lock();
678 inner
679 .mem_parsed_kv
680 .iter_mut()
681 .map(|(_, block)| block.change_num())
682 .sum()
683 }
684
685 pub fn fork(
686 &self,
687 arena: SharedArena,
688 merge_interval: Arc<AtomicI64>,
689 vv: &VersionVector,
690 frontiers: &Frontiers,
691 ) -> Self {
692 self.flush_and_compact(vv, frontiers);
693 let inner = self.inner.lock();
694 Self {
695 inner: Arc::new(Mutex::new(ChangeStoreInner {
696 start_vv: inner.start_vv.clone(),
697 start_frontiers: inner.start_frontiers.clone(),
698 mem_parsed_kv: BTreeMap::new(),
699 })),
700 arena,
701 external_vv: Arc::new(Mutex::new(self.external_vv.lock().clone())),
702 external_kv: self.external_kv.lock().clone_store(),
703 merge_interval,
704 root_history_names: Arc::new(Mutex::new(RootHistoryNamesState::Uninitialized)),
705 #[cfg(test)]
706 root_history_scan_count: Arc::new(AtomicUsize::new(0)),
707 }
708 }
709
710 pub fn kv_size(&self) -> usize {
711 self.external_kv
712 .lock()
713 .scan(Bound::Unbounded, Bound::Unbounded)
714 .map(|(k, v)| k.len() + v.len())
715 .sum()
716 }
717
718 pub(crate) fn export_blocks_from<W: std::io::Write>(
719 &self,
720 start_vv: &VersionVector,
721 shallow_since_vv: &ImVersionVector,
722 latest_vv: &VersionVector,
723 w: &mut W,
724 ) {
725 let new_store = ChangeStore::new_mem(&self.arena, self.merge_interval.clone());
726 for mut span in latest_vv.sub_iter(start_vv) {
727 let counter_lower_bound = shallow_since_vv.get(&span.peer).copied().unwrap_or(0);
728 span.counter.start = span.counter.start.max(counter_lower_bound);
729 span.counter.end = span.counter.end.max(counter_lower_bound);
730 if span.counter.start >= span.counter.end {
731 continue;
732 }
733
734 for c in self.iter_changes(span) {
737 let start = ((start_vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
738 as usize)
739 .min(c.atom_len());
740 let end = ((latest_vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
741 as usize)
742 .min(c.atom_len());
743
744 assert_ne!(start, end);
745 let ch = c.slice(start, end);
746 new_store.insert_change(ch, false, false);
747 }
748 }
749
750 let arena = &self.arena;
751 encode_blocks_in_store(new_store, arena, w);
752 }
753
754 pub(crate) fn fork_changes_up_to(
755 &self,
756 start_vv: &ImVersionVector,
757 frontiers: &Frontiers,
758 vv: &VersionVector,
759 ) -> Bytes {
760 let new_store = ChangeStore::new_mem(&self.arena, self.merge_interval.clone());
761 for mut span in vv.sub_iter_im(start_vv) {
762 let counter_lower_bound = start_vv.get(&span.peer).copied().unwrap_or(0);
763 span.counter.start = span.counter.start.max(counter_lower_bound);
764 span.counter.end = span.counter.end.max(counter_lower_bound);
765 if span.counter.start >= span.counter.end {
766 continue;
767 }
768
769 for c in self.iter_changes(span) {
772 let start = ((start_vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
773 as usize)
774 .min(c.atom_len());
775 let end = ((vv.get(&c.id.peer).copied().unwrap_or(0) - c.id.counter).max(0)
776 as usize)
777 .min(c.atom_len());
778
779 assert_ne!(start, end);
780 let ch = c.slice(start, end);
781 new_store.insert_change(ch, false, false);
782 }
783 }
784
785 new_store.encode_all(vv, frontiers)
786 }
787}
788
789fn encode_blocks_in_store<W: std::io::Write>(
790 new_store: ChangeStore,
791 arena: &SharedArena,
792 w: &mut W,
793) {
794 let mut inner = new_store.inner.lock();
795 for (_id, block) in inner.mem_parsed_kv.iter_mut() {
796 let bytes = block.to_bytes(arena);
797 leb128::write::unsigned(w, bytes.bytes.len() as u64).unwrap();
798 w.write_all(&bytes.bytes).unwrap();
799 }
800}
801
802mod mut_external_kv {
803 use super::*;
806
807 impl ChangeStore {
808 #[tracing::instrument(skip_all, level = "debug", name = "change_store import_all")]
809 pub(crate) fn import_all(&self, bytes: Bytes) -> Result<BatchDecodeInfo, LoroError> {
810 let mut kv_store = self.external_kv.lock();
811 assert!(
812 kv_store.len() <= 2,
814 "kv store should be empty when using decode_all"
815 );
816 kv_store
820 .import_all(bytes)
821 .map_err(|e| LoroError::DecodeError(e.into_boxed_str()))?;
822 drop(kv_store);
823 *self.root_history_names.lock() = RootHistoryNamesState::Uninitialized;
824 let vv_bytes = self.external_kv.lock().get(VV_KEY).unwrap_or_default();
825 let vv = VersionVector::decode(&vv_bytes)
826 .map_err(|_| LoroError::DecodeDataCorruptionError)?;
827 let start_vv_bytes = self
828 .external_kv
829 .lock()
830 .get(START_VV_KEY)
831 .unwrap_or_default();
832 let start_vv = if start_vv_bytes.is_empty() {
833 Default::default()
834 } else {
835 VersionVector::decode(&start_vv_bytes)
836 .map_err(|_| LoroError::DecodeDataCorruptionError)?
837 };
838
839 #[cfg(test)]
840 {
841 for (peer, cnt) in vv.iter() {
843 self.get_change(ID::new(*peer, *cnt - 1))
844 .ok_or(LoroError::DecodeDataCorruptionError)?;
845 }
846 }
847
848 *self.external_vv.lock() = vv.clone();
849 let frontiers_bytes = self
850 .external_kv
851 .lock()
852 .get(FRONTIERS_KEY)
853 .unwrap_or_default();
854 let frontiers = Frontiers::decode(&frontiers_bytes)
855 .map_err(|_| LoroError::DecodeDataCorruptionError)?;
856 let start_frontiers = self
857 .external_kv
858 .lock()
859 .get(START_FRONTIERS_KEY)
860 .unwrap_or_default();
861 let start_frontiers = if start_frontiers.is_empty() {
862 Default::default()
863 } else {
864 Frontiers::decode(&start_frontiers)
865 .map_err(|_| LoroError::DecodeDataCorruptionError)?
866 };
867
868 let mut max_lamport = None;
869 let mut max_timestamp = 0;
870 for id in frontiers.iter() {
871 let c = self
872 .get_change(id)
873 .ok_or(LoroError::DecodeDataCorruptionError)?;
874 debug_assert_ne!(c.atom_len(), 0);
875 let l = c.lamport_last();
876 if let Some(x) = max_lamport {
877 if l > x {
878 max_lamport = Some(l);
879 }
880 } else {
881 max_lamport = Some(l);
882 }
883
884 let t = c.timestamp;
885 if t > max_timestamp {
886 max_timestamp = t;
887 }
888 }
889
890 Ok(BatchDecodeInfo {
891 vv,
892 frontiers,
893 start_version: if start_vv.is_empty() {
894 None
895 } else {
896 let mut inner = self.inner.lock();
897 inner.start_frontiers = start_frontiers.clone();
898 inner.start_vv = ImVersionVector::from_vv(&start_vv);
899 Some((start_vv, start_frontiers))
900 },
901 })
902 }
903
904 pub(crate) fn flush_and_compact(&self, vv: &VersionVector, frontiers: &Frontiers) {
906 let mut inner = self.inner.lock();
907 let mut store = self.external_kv.lock();
908 let mut external_vv = self.external_vv.lock();
909 for (id, block) in inner.mem_parsed_kv.iter_mut() {
910 if !block.flushed {
911 let id_bytes = id.to_bytes();
912 let counter_start = external_vv.get(&id.peer).copied().unwrap_or(0);
913 assert!(
914 counter_start < block.counter_range.1,
915 "Peer={} Block Counter Range={:?}, counter_start={}",
916 id.peer,
917 &block.counter_range,
918 counter_start
919 );
920 if counter_start > block.counter_range.0 {
921 assert!(store.get(&id_bytes).is_some());
922 }
923 external_vv.insert(id.peer, block.counter_range.1);
924 let bytes = block.to_bytes(&self.arena);
925 store.set(&id_bytes, bytes.bytes);
926 Arc::make_mut(block).flushed = true;
927 }
928 }
929
930 if inner.start_vv.is_empty() {
931 assert_eq!(&*external_vv, vv);
932 } else {
933 #[cfg(debug_assertions)]
934 {
935 }
937 }
938 let vv_bytes = vv.encode();
939 let frontiers_bytes = frontiers.encode();
940 store.set(VV_KEY, vv_bytes.into());
941 store.set(FRONTIERS_KEY, frontiers_bytes.into());
942 }
943 }
944}
945
946mod mut_inner_kv {
947 use super::*;
951 impl ChangeStore {
952 pub fn insert_change(&self, change: Change, split_when_exceeds: bool, is_local: bool) {
957 self.insert_change_inner(change, split_when_exceeds, is_local, None);
958 }
959
960 pub(crate) fn insert_change_with_rollback(
961 &self,
962 change: Change,
963 split_when_exceeds: bool,
964 is_local: bool,
965 rollback: &mut ChangeStoreRollback,
966 ) {
967 self.insert_change_inner(change, split_when_exceeds, is_local, Some(rollback));
968 }
969
970 fn insert_change_inner(
971 &self,
972 mut change: Change,
973 split_when_exceeds: bool,
974 is_local: bool,
975 mut rollback: Option<&mut ChangeStoreRollback>,
976 ) {
977 self.record_change_in_root_history_names(&change);
978
979 #[cfg(debug_assertions)]
980 {
981 let vv = self.external_vv.lock();
982 assert!(vv.get(&change.id.peer).copied().unwrap_or(0) <= change.id.counter);
983 }
984
985 let s = info_span!("change_store insert_change", id = ?change.id);
986 let _e = s.enter();
987 let estimated_size = change.estimate_storage_size();
988 if estimated_size > MAX_BLOCK_SIZE && split_when_exceeds {
989 self.split_change_then_insert(change, rollback.as_deref_mut());
990 return;
991 }
992
993 let id = change.id;
994 let mut inner = self.inner.lock();
995
996 if let Some((_id, block)) = inner.mem_parsed_kv.range_mut(..id).next_back() {
998 if block.peer == change.id.peer {
999 if block.counter_range.1 != change.id.counter {
1000 panic!("counter should be continuous")
1001 }
1002
1003 if let Some(rollback) = &mut rollback {
1004 rollback.record_block_before_mutation(*_id, block.clone());
1005 }
1006
1007 match block.push_change(
1008 change,
1009 estimated_size,
1010 if is_local {
1011 self.merge_interval
1014 .load(std::sync::atomic::Ordering::Acquire)
1015 } else {
1016 0
1017 },
1018 &self.arena,
1019 ) {
1020 Ok(_) => {
1021 drop(inner);
1022 debug_assert!(self.get_change(id).is_some());
1023 return;
1024 }
1025 Err(c) => change = c,
1026 }
1027 }
1028 }
1029
1030 inner
1031 .mem_parsed_kv
1032 .insert(id, Arc::new(ChangesBlock::new(change, &self.arena)));
1033 drop(inner);
1034 debug_assert!(self.get_change(id).is_some());
1035 }
1036
1037 pub fn get_change(&self, id: ID) -> Option<BlockChangeRef> {
1038 let block = self.get_parsed_block(id)?;
1039 Some(BlockChangeRef {
1040 change_index: block.get_change_index_by_counter(id.counter).unwrap(),
1041 block: block.clone(),
1042 })
1043 }
1044
1045 pub fn get_change_by_lamport_lte(&self, idlp: IdLp) -> Option<BlockChangeRef> {
1049 let mut inner = self.inner.lock();
1052 let mut iter = inner
1053 .mem_parsed_kv
1054 .range_mut(ID::new(idlp.peer, 0)..ID::new(idlp.peer, i32::MAX));
1055
1056 let mut lower_bound = 0;
1058 let mut upper_bound = i32::MAX;
1059 let mut is_binary_searching = false;
1060 let mut binary_search_steps = 0;
1066 loop {
1067 if is_binary_searching {
1068 binary_search_steps += 1;
1069 if binary_search_steps > 128 {
1070 warn!(
1071 "get_change_by_lamport_lte binary search did not converge; \
1072 falling back to kv scan"
1073 );
1074 break;
1075 }
1076 }
1077 match iter.next_back() {
1078 Some((&id, block)) => {
1079 if block.lamport_range.0 <= idlp.lamport
1080 && (!is_binary_searching || idlp.lamport < block.lamport_range.1)
1081 {
1082 if !is_binary_searching
1083 && upper_bound != i32::MAX
1084 && upper_bound != block.counter_range.1
1085 {
1086 warn!(
1087 "There is a hole between the last block and the current block"
1088 );
1089 break;
1092 }
1093
1094 if let Err(err) = block.ensure_changes(&self.arena) {
1096 warn!(block_id = ?id, ?err, "failed to parse change block");
1097 return None;
1098 }
1099 let index = block.get_change_index_by_lamport_lte(idlp.lamport)?;
1100 return Some(BlockChangeRef {
1101 change_index: index,
1102 block: block.clone(),
1103 });
1104 }
1105
1106 if is_binary_searching {
1107 let mid_bound = (lower_bound + upper_bound) / 2;
1108 if block.lamport_range.1 <= idlp.lamport {
1109 lower_bound = mid_bound;
1111 } else {
1112 debug_assert!(
1113 idlp.lamport < block.lamport_range.0,
1114 "{} {:?}",
1115 idlp,
1116 &block.lamport_range
1117 );
1118 upper_bound = mid_bound;
1120 }
1121
1122 let mid_bound = (lower_bound + upper_bound) / 2;
1123 iter = inner
1124 .mem_parsed_kv
1125 .range_mut(ID::new(idlp.peer, 0)..ID::new(idlp.peer, mid_bound));
1126 } else {
1127 if block.lamport_range.0 - idlp.lamport > MAX_BLOCK_SIZE as Lamport * 8
1129 {
1130 upper_bound = id.counter;
1132 let mid_bound = (lower_bound + upper_bound) / 2;
1133 iter = inner.mem_parsed_kv.range_mut(
1134 ID::new(idlp.peer, 0)..ID::new(idlp.peer, mid_bound),
1135 );
1136 is_binary_searching = true;
1137 }
1138
1139 upper_bound = id.counter;
1140 }
1141 }
1142 None => {
1143 if !is_binary_searching {
1144 break;
1145 }
1146
1147 let mid_bound = (lower_bound + upper_bound) / 2;
1148 lower_bound = mid_bound;
1149 if upper_bound - lower_bound <= MAX_BLOCK_SIZE as i32 {
1150 iter = inner.mem_parsed_kv.range_mut(
1152 ID::new(idlp.peer, lower_bound)..ID::new(idlp.peer, upper_bound),
1153 );
1154 is_binary_searching = false;
1155 } else {
1156 let mid_bound = (lower_bound + upper_bound) / 2;
1157 iter = inner
1158 .mem_parsed_kv
1159 .range_mut(ID::new(idlp.peer, 0)..ID::new(idlp.peer, mid_bound));
1160 }
1161 }
1162 }
1163 }
1164
1165 let counter_end = upper_bound;
1166
1167 let mem_block_id: Option<ID> = inner
1174 .mem_parsed_kv
1175 .range(ID::new(idlp.peer, 0)..ID::new(idlp.peer, counter_end))
1176 .rev()
1177 .find(|(_, block)| block.lamport_range.0 <= idlp.lamport)
1178 .map(|(id, _)| *id);
1179
1180 let external_block = 'block_scan: {
1181 let kv_store = &self.external_kv.lock();
1182 let scan_end = ID::new(idlp.peer, counter_end).to_bytes();
1183 let iter = kv_store
1184 .scan(
1185 Bound::Included(&ID::new(idlp.peer, 0).to_bytes()),
1186 Bound::Excluded(&scan_end),
1187 )
1188 .rev();
1189
1190 for (id, bytes) in iter {
1191 let mut block = ChangesBlockBytes::new(bytes.clone());
1192 let (lamport_start, _lamport_end) = match block.lamport_range() {
1193 Ok(range) => range,
1194 Err(err) => {
1195 let block_id = ID::from_bytes(&id);
1196 warn!(
1197 ?block_id,
1198 ?err,
1199 "failed to decode external change block range"
1200 );
1201 continue;
1202 }
1203 };
1204 if lamport_start <= idlp.lamport {
1205 break 'block_scan Some((ID::from_bytes(&id), bytes));
1206 }
1207 }
1208
1209 None
1210 };
1211
1212 let use_external = match (mem_block_id, &external_block) {
1213 (Some(mem_id), Some((external_id, _))) => external_id.counter > mem_id.counter,
1214 (Some(_), None) => false,
1215 (None, Some(_)) => true,
1216 (None, None) => return None,
1217 };
1218
1219 if !use_external {
1220 let block_id = mem_block_id.unwrap();
1221 let block = inner.mem_parsed_kv.get_mut(&block_id).unwrap();
1222 if let Err(err) = block.ensure_changes(&self.arena) {
1223 warn!(?block_id, ?err, "failed to parse change block");
1224 return None;
1225 }
1226 let block = block.clone();
1227 let index = block.get_change_index_by_lamport_lte(idlp.lamport)?;
1228 return Some(BlockChangeRef {
1229 change_index: index,
1230 block,
1231 });
1232 }
1233
1234 let (block_id, bytes) = external_block.unwrap();
1235 let mut block = match ChangesBlock::from_bytes(bytes) {
1236 Ok(block) => Arc::new(block),
1237 Err(err) => {
1238 warn!(?block_id, ?err, "failed to decode external change block");
1239 return None;
1240 }
1241 };
1242 if let Err(err) = block.ensure_changes(&self.arena) {
1243 warn!(?block_id, ?err, "failed to parse external change block");
1244 return None;
1245 }
1246 inner.mem_parsed_kv.insert(block_id, block.clone());
1247 let index = block.get_change_index_by_lamport_lte(idlp.lamport)?;
1248 Some(BlockChangeRef {
1249 change_index: index,
1250 block,
1251 })
1252 }
1253
1254 fn split_change_then_insert(
1255 &self,
1256 change: Change,
1257 mut rollback: Option<&mut ChangeStoreRollback>,
1258 ) {
1259 let original_len = change.atom_len();
1260 let mut new_change = Change {
1261 ops: RleVec::new(),
1262 deps: change.deps,
1263 id: change.id,
1264 lamport: change.lamport,
1265 timestamp: change.timestamp,
1266 commit_msg: change.commit_msg.clone(),
1267 };
1268
1269 let mut total_len = 0;
1270 let mut estimated_size = new_change.estimate_storage_size();
1271 'outer: for mut op in change.ops.into_iter() {
1272 if op.estimate_storage_size() >= MAX_BLOCK_SIZE - estimated_size {
1273 new_change = self._insert_splitted_change(
1274 new_change,
1275 &mut total_len,
1276 &mut estimated_size,
1277 rollback.as_deref_mut(),
1278 );
1279 }
1280
1281 while let Some(end) =
1282 op.check_whether_slice_content_to_fit_in_size(MAX_BLOCK_SIZE - estimated_size)
1283 {
1284 let new = op.slice(0, end);
1286 new_change.ops.push(new);
1287 new_change = self._insert_splitted_change(
1288 new_change,
1289 &mut total_len,
1290 &mut estimated_size,
1291 rollback.as_deref_mut(),
1292 );
1293
1294 if end < op.atom_len() {
1295 op = op.slice(end, op.atom_len());
1296 } else {
1297 continue 'outer;
1298 }
1299 }
1300
1301 estimated_size += op.estimate_storage_size();
1302 if estimated_size > MAX_BLOCK_SIZE && !new_change.ops.is_empty() {
1303 new_change = self._insert_splitted_change(
1304 new_change,
1305 &mut total_len,
1306 &mut estimated_size,
1307 rollback.as_deref_mut(),
1308 );
1309 new_change.ops.push(op);
1310 } else {
1311 new_change.ops.push(op);
1312 }
1313 }
1314
1315 if !new_change.ops.is_empty() {
1316 total_len += new_change.atom_len();
1317 self.insert_change_inner(new_change, false, false, rollback);
1318 }
1319
1320 assert_eq!(total_len, original_len);
1321 }
1322
1323 fn _insert_splitted_change(
1324 &self,
1325 new_change: Change,
1326 total_len: &mut usize,
1327 estimated_size: &mut usize,
1328 rollback: Option<&mut ChangeStoreRollback>,
1329 ) -> Change {
1330 if new_change.atom_len() == 0 {
1331 return new_change;
1332 }
1333
1334 let ctr_end = new_change.id.counter + new_change.atom_len() as Counter;
1335 let next_lamport = new_change.lamport + new_change.atom_len() as Lamport;
1336 *total_len += new_change.atom_len();
1337 let ans = Change {
1338 ops: RleVec::new(),
1339 deps: ID::new(new_change.id.peer, ctr_end - 1).into(),
1340 id: ID::new(new_change.id.peer, ctr_end),
1341 lamport: next_lamport,
1342 timestamp: new_change.timestamp,
1343 commit_msg: new_change.commit_msg.clone(),
1344 };
1345
1346 self.insert_change_inner(new_change, false, false, rollback);
1347 *estimated_size = ans.estimate_storage_size();
1348 ans
1349 }
1350
1351 fn get_parsed_block(&self, id: ID) -> Option<Arc<ChangesBlock>> {
1352 let mut inner = self.inner.lock();
1353 if let Some((_id, block)) = inner.mem_parsed_kv.range_mut(..=id).next_back() {
1354 if block.peer == id.peer && block.counter_range.1 > id.counter {
1355 if let Err(err) = block.ensure_changes(&self.arena) {
1356 warn!(block_id = ?_id, ?err, "failed to parse cached change block");
1357 return None;
1358 }
1359 return Some(block.clone());
1360 }
1361 }
1362
1363 let store = self.external_kv.lock();
1364 let mut iter = store
1365 .scan(Bound::Unbounded, Bound::Included(&id.to_bytes()))
1366 .filter(|(id, _)| id.len() == 12);
1367
1368 let (b_id, b_bytes) = iter.next_back()?;
1379 let block_id: ID = ID::from_bytes(&b_id[..]);
1380 let block = match ChangesBlock::from_bytes(b_bytes) {
1381 Ok(block) => block,
1382 Err(err) => {
1383 warn!(?block_id, ?err, "failed to decode external change block");
1384 return None;
1385 }
1386 };
1387 if block_id.peer == id.peer
1388 && block_id.counter <= id.counter
1389 && block.counter_range.1 > id.counter
1390 {
1391 let mut arc_block = Arc::new(block);
1392 if let Err(err) = arc_block.ensure_changes(&self.arena) {
1393 warn!(?block_id, ?err, "failed to parse external change block");
1394 return None;
1395 }
1396 inner.mem_parsed_kv.insert(block_id, arc_block.clone());
1397 return Some(arc_block);
1398 }
1399
1400 None
1401 }
1402
1403 pub(super) fn ensure_block_loaded_in_range(&self, start: Bound<ID>, end: Bound<ID>) {
1408 let mut whether_need_scan_backward = match start {
1409 Bound::Included(id) => Some(id),
1410 Bound::Excluded(id) => Some(id.inc(1)),
1411 Bound::Unbounded => None,
1412 };
1413
1414 {
1415 let start = start.map(|id| id.to_bytes());
1416 let end = end.map(|id| id.to_bytes());
1417 let kv = self.external_kv.lock();
1418 let mut inner = self.inner.lock();
1419 for (id, bytes) in kv
1420 .scan(
1421 start.as_ref().map(|x| x.as_slice()),
1422 end.as_ref().map(|x| x.as_slice()),
1423 )
1424 .filter(|(id, _)| id.len() == 12)
1425 {
1426 let id = ID::from_bytes(&id);
1427 if let Some(expected_start_id) = whether_need_scan_backward {
1428 if id == expected_start_id {
1429 whether_need_scan_backward = None;
1430 }
1431 }
1432
1433 if inner.mem_parsed_kv.contains_key(&id) {
1434 continue;
1435 }
1436
1437 let block = match ChangesBlock::from_bytes(bytes.clone()) {
1438 Ok(block) => block,
1439 Err(err) => {
1440 warn!(?id, ?err, "failed to decode external change block");
1441 continue;
1442 }
1443 };
1444 inner.mem_parsed_kv.insert(id, Arc::new(block));
1445 }
1446 }
1447
1448 if let Some(start_id) = whether_need_scan_backward {
1449 self.ensure_id_lte(start_id);
1450 }
1451 }
1452
1453 pub(super) fn ensure_id_lte(&self, id: ID) {
1454 let kv = self.external_kv.lock();
1455 let mut inner = self.inner.lock();
1456 let Some((next_back_id, next_back_bytes)) = kv
1457 .scan(Bound::Unbounded, Bound::Included(&id.to_bytes()))
1458 .rfind(|(id, _)| id.len() == 12)
1459 else {
1460 return;
1461 };
1462
1463 let next_back_id = ID::from_bytes(&next_back_id);
1464 if next_back_id.peer == id.peer {
1465 if inner.mem_parsed_kv.contains_key(&next_back_id) {
1466 return;
1467 }
1468
1469 let block = match ChangesBlock::from_bytes(next_back_bytes) {
1470 Ok(block) => block,
1471 Err(err) => {
1472 warn!(
1473 ?next_back_id,
1474 ?err,
1475 "failed to decode external change block"
1476 );
1477 return;
1478 }
1479 };
1480 inner.mem_parsed_kv.insert(next_back_id, Arc::new(block));
1481 }
1482 }
1483 }
1484}
1485
1486#[must_use]
1487#[derive(Clone, Debug)]
1488pub(crate) struct BatchDecodeInfo {
1489 pub vv: VersionVector,
1490 pub frontiers: Frontiers,
1491 pub start_version: Option<(VersionVector, Frontiers)>,
1492}
1493
1494#[derive(Clone, Debug)]
1495pub struct BlockChangeRef {
1496 block: Arc<ChangesBlock>,
1497 change_index: usize,
1498}
1499
1500impl Deref for BlockChangeRef {
1501 type Target = Change;
1502 fn deref(&self) -> &Change {
1503 &self.block.content.try_changes().unwrap()[self.change_index]
1504 }
1505}
1506
1507impl BlockChangeRef {
1508 pub(crate) fn get_op_with_counter(&self, counter: Counter) -> Option<BlockOpRef> {
1509 if counter >= self.ctr_end() {
1510 return None;
1511 }
1512
1513 let index = self.ops.search_atom_index(counter);
1514 Some(BlockOpRef {
1515 block: self.block.clone(),
1516 change_index: self.change_index,
1517 op_index: index,
1518 })
1519 }
1520}
1521
1522#[derive(Clone, Debug)]
1523pub(crate) struct BlockOpRef {
1524 pub block: Arc<ChangesBlock>,
1525 pub change_index: usize,
1526 pub op_index: usize,
1527}
1528
1529impl Deref for BlockOpRef {
1530 type Target = Op;
1531
1532 fn deref(&self) -> &Op {
1533 &self.block.content.try_changes().unwrap()[self.change_index].ops[self.op_index]
1534 }
1535}
1536
1537impl BlockOpRef {
1538 pub fn lamport(&self) -> Lamport {
1539 let change = &self.block.content.try_changes().unwrap()[self.change_index];
1540 let op = &change.ops[self.op_index];
1541 (op.counter - change.id.counter) as Lamport + change.lamport
1542 }
1543}
1544
1545impl ChangesBlock {
1546 fn from_bytes(bytes: Bytes) -> LoroResult<Self> {
1547 let len = bytes.len();
1548 let bytes = ChangesBlockBytes::new(bytes);
1549 bytes.ensure_header()?;
1550 let header = bytes
1551 .header
1552 .get()
1553 .expect("header should be initialized after ensure_header");
1554 let peer = header.peer;
1555 let counter_range = (
1556 header.counter,
1557 *header.counters.last().ok_or_else(|| {
1558 LoroError::DecodeError("Decode block error: missing counters".into())
1559 })?,
1560 );
1561 let last_change_start = *header
1565 .counters
1566 .len()
1567 .checked_sub(2)
1568 .and_then(|i| header.counters.get(i))
1569 .ok_or_else(|| LoroError::DecodeError("Decode block error: missing counters".into()))?;
1570 let last_change_len = counter_range.1 - last_change_start;
1571 let lamport_range = (
1572 *header.lamports.first().ok_or_else(|| {
1573 LoroError::DecodeError("Decode block error: missing lamports".into())
1574 })?,
1575 header
1576 .lamports
1577 .last()
1578 .ok_or_else(|| {
1579 LoroError::DecodeError("Decode block error: missing lamports".into())
1580 })?
1581 .checked_add(last_change_len as Lamport)
1582 .ok_or_else(|| {
1583 LoroError::DecodeError("Decode block error: lamport overflow".into())
1584 })?,
1585 );
1586 let content = ChangesBlockContent::Bytes(bytes);
1587 Ok(Self {
1588 peer,
1589 estimated_size: len,
1590 counter_range,
1591 lamport_range,
1592 flushed: true,
1593 content,
1594 })
1595 }
1596
1597 #[allow(dead_code)]
1598 pub(crate) fn content(&self) -> &ChangesBlockContent {
1599 &self.content
1600 }
1601
1602 fn new(change: Change, _a: &SharedArena) -> Self {
1603 let atom_len = change.atom_len();
1604 let counter_range = (change.id.counter, change.id.counter + atom_len as Counter);
1605 let lamport_range = (change.lamport, change.lamport + atom_len as Lamport);
1606 let estimated_size = change.estimate_storage_size();
1607 let peer = change.id.peer;
1608 let content = ChangesBlockContent::Changes(Arc::new(vec![change]));
1609 Self {
1610 peer,
1611 counter_range,
1612 lamport_range,
1613 estimated_size,
1614 content,
1615 flushed: false,
1616 }
1617 }
1618
1619 #[allow(unused)]
1620 fn cmp_id(&self, id: ID) -> Ordering {
1621 self.peer.cmp(&id.peer).then_with(|| {
1622 if self.counter_range.0 > id.counter {
1623 Ordering::Greater
1624 } else if self.counter_range.1 <= id.counter {
1625 Ordering::Less
1626 } else {
1627 Ordering::Equal
1628 }
1629 })
1630 }
1631
1632 #[allow(unused)]
1633 fn cmp_idlp(&self, idlp: (PeerID, Lamport)) -> Ordering {
1634 self.peer.cmp(&idlp.0).then_with(|| {
1635 if self.lamport_range.0 > idlp.1 {
1636 Ordering::Greater
1637 } else if self.lamport_range.1 <= idlp.1 {
1638 Ordering::Less
1639 } else {
1640 Ordering::Equal
1641 }
1642 })
1643 }
1644
1645 #[allow(unused)]
1646 fn is_full(&self) -> bool {
1647 self.estimated_size > MAX_BLOCK_SIZE
1648 }
1649
1650 #[allow(clippy::result_large_err)]
1651 fn push_change(
1652 self: &mut Arc<Self>,
1653 change: Change,
1654 new_change_size: usize,
1655 merge_interval: i64,
1656 a: &SharedArena,
1657 ) -> Result<(), Change> {
1658 if self.counter_range.1 != change.id.counter {
1659 return Err(change);
1660 }
1661
1662 let atom_len = change.atom_len();
1663 let next_lamport = change.lamport + atom_len as Lamport;
1664 let next_counter = change.id.counter + atom_len as Counter;
1665
1666 let is_full = new_change_size + self.estimated_size > MAX_BLOCK_SIZE;
1667 let this = Arc::make_mut(self);
1668 let changes = this.content.changes_mut(a).unwrap();
1669 let changes = Arc::make_mut(changes);
1670 match changes.last_mut() {
1671 Some(last)
1672 if last.can_merge_right(&change, merge_interval)
1673 && (!is_full
1674 || (change.ops.len() == 1
1675 && last.ops.last().unwrap().is_mergable(&change.ops[0], &()))) =>
1676 {
1677 for op in change.ops.into_iter() {
1678 let size = op.estimate_storage_size();
1679 if !last.ops.push(op) {
1680 this.estimated_size += size;
1681 }
1682 }
1683 }
1684 _ => {
1685 if is_full {
1686 return Err(change);
1687 } else {
1688 this.estimated_size += new_change_size;
1689 changes.push(change);
1690 }
1691 }
1692 }
1693
1694 this.flushed = false;
1695 this.counter_range.1 = next_counter;
1696 this.lamport_range.1 = next_lamport;
1697 Ok(())
1698 }
1699
1700 fn to_bytes(self: &mut Arc<Self>, a: &SharedArena) -> ChangesBlockBytes {
1701 match &self.content {
1702 ChangesBlockContent::Bytes(bytes) => bytes.clone(),
1703 ChangesBlockContent::Both(_, bytes) => {
1704 let bytes = bytes.clone();
1705 let this = Arc::make_mut(self);
1706 this.content = ChangesBlockContent::Bytes(bytes.clone());
1707 bytes
1708 }
1709 ChangesBlockContent::Changes(changes) => {
1710 let bytes = ChangesBlockBytes::serialize(changes, a);
1711 let this = Arc::make_mut(self);
1712 this.content = ChangesBlockContent::Bytes(bytes.clone());
1713 bytes
1714 }
1715 }
1716 }
1717
1718 fn ensure_changes(self: &mut Arc<Self>, a: &SharedArena) -> LoroResult<()> {
1719 match &self.content {
1720 ChangesBlockContent::Changes(_) => Ok(()),
1721 ChangesBlockContent::Both(_, _) => Ok(()),
1722 ChangesBlockContent::Bytes(bytes) => {
1723 let changes = bytes.parse(a)?;
1724 let b = bytes.clone();
1725 let this = Arc::make_mut(self);
1726 this.content = ChangesBlockContent::Both(Arc::new(changes), b);
1727 Ok(())
1728 }
1729 }
1730 }
1731
1732 fn get_change_index_by_counter(&self, counter: Counter) -> Result<usize, usize> {
1733 let changes = self.content.try_changes().unwrap();
1734 changes.binary_search_by(|c| {
1735 if c.id.counter > counter {
1736 Ordering::Greater
1737 } else if (c.id.counter + c.content_len() as Counter) <= counter {
1738 Ordering::Less
1739 } else {
1740 Ordering::Equal
1741 }
1742 })
1743 }
1744
1745 fn get_change_index_by_lamport_lte(&self, lamport: Lamport) -> Option<usize> {
1746 let changes = self.content.try_changes().unwrap();
1747 let r = changes.binary_search_by(|c| {
1748 if c.lamport > lamport {
1749 Ordering::Greater
1750 } else if (c.lamport + c.content_len() as Lamport) <= lamport {
1751 Ordering::Less
1752 } else {
1753 Ordering::Equal
1754 }
1755 });
1756
1757 match r {
1758 Ok(found) => Some(found),
1759 Err(idx) => {
1760 if idx == 0 {
1761 None
1762 } else {
1763 Some(idx - 1)
1764 }
1765 }
1766 }
1767 }
1768
1769 #[allow(unused)]
1770 fn get_changes(&mut self, a: &SharedArena) -> LoroResult<&Vec<Change>> {
1771 self.content.changes(a)
1772 }
1773
1774 #[allow(unused)]
1775 fn id(&self) -> ID {
1776 ID::new(self.peer, self.counter_range.0)
1777 }
1778
1779 pub fn change_num(&self) -> usize {
1780 match &self.content {
1781 ChangesBlockContent::Changes(c) => c.len(),
1782 ChangesBlockContent::Bytes(b) => b.len_changes(),
1783 ChangesBlockContent::Both(c, _) => c.len(),
1784 }
1785 }
1786}
1787
1788impl ChangesBlockContent {
1789 pub fn iter_dag_nodes(&self) -> Vec<AppDagNode> {
1791 let mut dag_nodes = Vec::new();
1792 match self {
1793 ChangesBlockContent::Changes(c) | ChangesBlockContent::Both(c, _) => {
1794 for change in c.iter() {
1795 let new_node = AppDagNodeInner {
1796 peer: change.id.peer,
1797 cnt: change.id.counter,
1798 lamport: change.lamport,
1799 deps: change.deps.clone(),
1800 vv: OnceCell::new(),
1801 has_succ: false,
1802 len: change.atom_len(),
1803 }
1804 .into();
1805
1806 dag_nodes.push_rle_element(new_node);
1807 }
1808 }
1809 ChangesBlockContent::Bytes(b) => {
1810 b.ensure_header().unwrap();
1811 let header = b.header.get().unwrap();
1812 let n = header.n_changes;
1813 for i in 0..n {
1814 let new_node = AppDagNodeInner {
1815 peer: header.peer,
1816 cnt: header.counters[i],
1817 lamport: header.lamports[i],
1818 deps: header.deps_groups[i].clone(),
1819 vv: OnceCell::new(),
1820 has_succ: false,
1821 len: (header.counters[i + 1] - header.counters[i]) as usize,
1822 }
1823 .into();
1824
1825 dag_nodes.push_rle_element(new_node);
1826 }
1827 }
1828 }
1829
1830 dag_nodes
1831 }
1832
1833 #[allow(unused)]
1834 pub fn changes(&mut self, a: &SharedArena) -> LoroResult<&Vec<Change>> {
1835 match self {
1836 ChangesBlockContent::Changes(changes) => Ok(changes),
1837 ChangesBlockContent::Both(changes, _) => Ok(changes),
1838 ChangesBlockContent::Bytes(bytes) => {
1839 let changes = bytes.parse(a)?;
1840 *self = ChangesBlockContent::Both(Arc::new(changes), bytes.clone());
1841 self.changes(a)
1842 }
1843 }
1844 }
1845
1846 fn changes_mut(&mut self, a: &SharedArena) -> LoroResult<&mut Arc<Vec<Change>>> {
1848 match self {
1849 ChangesBlockContent::Changes(changes) => Ok(changes),
1850 ChangesBlockContent::Both(changes, _) => {
1851 *self = ChangesBlockContent::Changes(std::mem::take(changes));
1852 self.changes_mut(a)
1853 }
1854 ChangesBlockContent::Bytes(bytes) => {
1855 let changes = bytes.parse(a)?;
1856 *self = ChangesBlockContent::Changes(Arc::new(changes));
1857 self.changes_mut(a)
1858 }
1859 }
1860 }
1861
1862 pub(crate) fn try_changes(&self) -> Option<&Vec<Change>> {
1863 match self {
1864 ChangesBlockContent::Changes(changes) => Some(changes),
1865 ChangesBlockContent::Both(changes, _) => Some(changes),
1866 ChangesBlockContent::Bytes(_) => None,
1867 }
1868 }
1869
1870 #[allow(dead_code)]
1871 pub(crate) fn len_changes(&self) -> usize {
1872 match self {
1873 ChangesBlockContent::Changes(changes) => changes.len(),
1874 ChangesBlockContent::Both(changes, _) => changes.len(),
1875 ChangesBlockContent::Bytes(bytes) => bytes.len_changes(),
1876 }
1877 }
1878}
1879
1880impl std::fmt::Debug for ChangesBlockContent {
1881 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1882 match self {
1883 ChangesBlockContent::Changes(changes) => f
1884 .debug_tuple("ChangesBlockContent::Changes")
1885 .field(changes)
1886 .finish(),
1887 ChangesBlockContent::Bytes(_bytes) => {
1888 f.debug_tuple("ChangesBlockContent::Bytes").finish()
1889 }
1890 ChangesBlockContent::Both(changes, _bytes) => f
1891 .debug_tuple("ChangesBlockContent::Both")
1892 .field(changes)
1893 .finish(),
1894 }
1895 }
1896}
1897
1898impl ChangesBlockBytes {
1899 fn new(bytes: Bytes) -> Self {
1900 Self {
1901 header: OnceCell::new(),
1902 bytes,
1903 }
1904 }
1905
1906 fn ensure_header(&self) -> LoroResult<()> {
1907 self.header
1908 .get_or_try_init(|| decode_header(&self.bytes).map(Arc::new))?;
1909 Ok(())
1910 }
1911
1912 fn parse(&self, a: &SharedArena) -> LoroResult<Vec<Change>> {
1913 self.ensure_header()?;
1914 let ans: Vec<Change> = decode_block(&self.bytes, a, self.header.get().map(|h| h.as_ref()))?;
1915 for c in ans.iter() {
1916 register_container_and_parent_link(a, c)
1918 }
1919
1920 Ok(ans)
1921 }
1922
1923 fn serialize(changes: &[Change], a: &SharedArena) -> Self {
1924 let bytes = encode_block(changes, a);
1925 let bytes = ChangesBlockBytes::new(Bytes::from(bytes));
1927 bytes.ensure_header().unwrap();
1928 bytes
1929 }
1930
1931 fn lamport_range(&mut self) -> LoroResult<(Lamport, Lamport)> {
1932 if let Some(header) = self.header.get() {
1933 Ok((header.lamports[0], *header.lamports.last().unwrap()))
1934 } else {
1935 decode_block_range(&self.bytes).map(|(_, lamport_range)| lamport_range)
1936 }
1937 }
1938
1939 fn len_changes(&self) -> usize {
1941 self.ensure_header().unwrap();
1942 self.header.get().unwrap().n_changes
1943 }
1944}
1945
1946#[cfg(test)]
1947mod test {
1948 use crate::cursor::PosType;
1949 use crate::{
1950 loro::ExportMode, oplog::convert_change_to_remote, state::TreeParentId, ListHandler,
1951 LoroDoc, MovableListHandler, TextHandler, TreeHandler,
1952 };
1953
1954 use super::*;
1955
1956 fn test_encode_decode(doc: LoroDoc) {
1957 doc.commit_then_renew();
1958 let oplog = doc.oplog().lock();
1959 let bytes = oplog
1960 .change_store
1961 .encode_all(oplog.vv(), oplog.dag.frontiers());
1962 let store = ChangeStore::new_for_test();
1963 let _ = store.import_all(bytes.clone()).unwrap();
1964 assert_eq!(store.external_kv.lock().export_all(), bytes);
1965 let mut changes_parsed = Vec::new();
1966 let a = store.arena.clone();
1967 store.visit_all_changes(&mut |c| {
1968 changes_parsed.push(convert_change_to_remote(&a, c));
1969 });
1970 let mut changes = Vec::new();
1971 oplog.change_store.visit_all_changes(&mut |c| {
1972 changes.push(convert_change_to_remote(&oplog.arena, c));
1973 });
1974 assert_eq!(changes_parsed, changes);
1975 }
1976
1977 #[test]
1978 fn decoded_block_lamport_range_matches_counter_range() {
1979 let doc = LoroDoc::new_auto_commit();
1986 doc.set_peer_id(1).unwrap();
1987 for i in 0..100 {
1991 let text = doc.get_text(format!("t{i}").as_str());
1992 text.insert(0, &"x".repeat(30), PosType::Unicode).unwrap();
1993 }
1994 doc.commit_then_renew();
1995
1996 let (bytes, end_counter) = {
1997 let oplog = doc.oplog().lock();
1998 let end = oplog.vv().get(&1).copied().unwrap();
1999 let bytes = oplog
2000 .change_store
2001 .encode_all(oplog.vv(), oplog.dag.frontiers());
2002 (bytes, end)
2003 };
2004
2005 let store = ChangeStore::new_for_test();
2006 let _ = store.import_all(bytes).unwrap();
2007 let mut c = 0;
2009 while c < end_counter {
2010 let change = store.get_change(ID::new(1, c)).unwrap();
2011 c = change.id.counter + change.atom_len() as Counter;
2012 }
2013
2014 {
2015 let inner = store.inner.lock();
2016 assert!(
2017 inner.mem_parsed_kv.len() > 1,
2018 "the change should be split into multiple blocks"
2019 );
2020 for (id, block) in inner.mem_parsed_kv.iter() {
2021 assert_eq!(id.counter, block.counter_range.0);
2023 assert_eq!(block.lamport_range.0 as Counter, block.counter_range.0);
2024 assert_eq!(block.lamport_range.1 as Counter, block.counter_range.1);
2025 }
2026 }
2027
2028 for l in (0..end_counter as Lamport).step_by(7) {
2029 let change = store.get_change_by_lamport_lte(IdLp::new(1, l)).unwrap();
2030 assert!(change.lamport <= l);
2031 assert!(l < change.lamport + change.atom_len() as Lamport);
2032 }
2033 }
2034
2035 #[test]
2036 fn lamport_lookup_finds_unflushed_mem_blocks() {
2037 let doc = LoroDoc::new_auto_commit();
2042 doc.set_peer_id(1).unwrap();
2043 let text = doc.get_text("t");
2044 text.insert(0, &"x".repeat(500), PosType::Unicode).unwrap();
2045 doc.commit_then_renew();
2046
2047 let doc2 = LoroDoc::new_auto_commit();
2051 doc2.set_peer_id(2).unwrap();
2052 let text2 = doc2.get_text("t2");
2053 text2
2054 .insert(0, &"y".repeat(3000), PosType::Unicode)
2055 .unwrap();
2056 doc2.commit_then_renew();
2057 doc.import(&doc2.export(ExportMode::all_updates()).unwrap())
2058 .unwrap();
2059
2060 let text = doc.get_text("t");
2061 text.insert(0, &"z".repeat(500), PosType::Unicode).unwrap();
2062 doc.commit_then_renew();
2063
2064 let oplog = doc.oplog().lock();
2068 let change = oplog
2069 .change_store
2070 .get_change_by_lamport_lte(IdLp::new(1, 700))
2071 .expect("the change should be found in the unflushed mem blocks");
2072 assert_eq!(change.id.peer, 1);
2073 assert!(change.lamport <= 700);
2074 assert_eq!(change.id.counter + change.atom_len() as Counter, 500);
2075 }
2076
2077 #[test]
2078 fn root_history_names_reject_oversized_name_without_retaining_it() {
2079 let mut names = FxHashSet::default();
2080 let mut name_bytes = 0;
2081 let oversized_name = "x".repeat(MAX_ROOT_HISTORY_NAME_BYTES + 1);
2082 let oversized = ContainerID::new_root(&oversized_name, crate::ContainerType::Map);
2083
2084 assert!(!record_root_name(&mut names, &mut name_bytes, &oversized));
2085 assert!(names.is_empty());
2086 assert_eq!(name_bytes, 0);
2087 }
2088
2089 #[test]
2090 fn test_change_store() {
2091 let doc = LoroDoc::new_auto_commit();
2092 doc.set_record_timestamp(true);
2093 let t = doc.get_text("t");
2094 t.insert(0, "hello", PosType::Unicode).unwrap();
2095 doc.commit_then_renew();
2096 let t = doc.get_list("t");
2097 t.insert(0, "hello").unwrap();
2098 test_encode_decode(doc);
2099 }
2100
2101 #[test]
2102 fn test_synced_doc() -> LoroResult<()> {
2103 let doc_a = LoroDoc::new_auto_commit();
2104 let doc_b = LoroDoc::new_auto_commit();
2105 let doc_c = LoroDoc::new_auto_commit();
2106
2107 {
2108 let map = doc_a.get_map("root");
2110 map.insert_container("text", TextHandler::new_detached())?;
2111 map.insert_container("list", ListHandler::new_detached())?;
2112 map.insert_container("tree", TreeHandler::new_detached())?;
2113 }
2114
2115 {
2116 let initial_state = doc_a.export(ExportMode::all_updates()).unwrap();
2118 doc_b.import(&initial_state)?;
2119 doc_c.import(&initial_state)?;
2120 }
2121
2122 {
2123 let map = doc_b.get_map("root");
2125 let text = map
2126 .insert_container("text", TextHandler::new_detached())
2127 .unwrap();
2128 text.insert(0, "Hello, ", PosType::Unicode)?;
2129
2130 let list = map
2131 .insert_container("list", ListHandler::new_detached())
2132 .unwrap();
2133 list.push("world")?;
2134 }
2135
2136 {
2137 let map = doc_c.get_map("root");
2139 let tree = map
2140 .insert_container("tree", TreeHandler::new_detached())
2141 .unwrap();
2142 let node_id = tree.create(TreeParentId::Root)?;
2143 tree.get_meta(node_id)?.insert("key", "value")?;
2144 let node_b = tree.create(TreeParentId::Root)?;
2145 tree.move_to(node_b, TreeParentId::Root, 0).unwrap();
2146
2147 let movable_list = map
2148 .insert_container("movable", MovableListHandler::new_detached())
2149 .unwrap();
2150 movable_list.push("item1".into())?;
2151 movable_list.push("item2".into())?;
2152 movable_list.mov(0, 1)?;
2153 }
2154
2155 let b_changes = doc_b
2157 .export(ExportMode::updates(&doc_a.oplog_vv()))
2158 .unwrap();
2159 doc_a.import(&b_changes)?;
2160
2161 let c_changes = doc_c
2163 .export(ExportMode::updates(&doc_a.oplog_vv()))
2164 .unwrap();
2165 doc_a.import(&c_changes)?;
2166
2167 test_encode_decode(doc_a);
2168 Ok(())
2169 }
2170}