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