mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 12:57:20 +00:00
refactor: only keep counter on op
This commit is contained in:
parent
6e03c9c04b
commit
d62fa09e99
6 changed files with 77 additions and 46 deletions
|
@ -6,7 +6,7 @@ use crate::{
|
|||
log_store::LogStoreWeakRef,
|
||||
op::{InsertContent, Op, RichOp},
|
||||
op::{OpContent, RemoteOp},
|
||||
span::{HasId, IdSpan},
|
||||
span::IdSpan,
|
||||
value::{InsertValue, LoroValue},
|
||||
version::TotalOrderStamp,
|
||||
InternalString, LogStore,
|
||||
|
@ -57,7 +57,7 @@ impl MapContainer {
|
|||
let counter = id.counter;
|
||||
let container = store.get_container_idx(self_id).unwrap();
|
||||
store.append_local_ops(&[Op {
|
||||
id,
|
||||
counter: id.counter,
|
||||
container,
|
||||
content: OpContent::Normal {
|
||||
content: InsertContent::Dyn(Box::new(MapSet {
|
||||
|
@ -109,7 +109,7 @@ impl Container for MapContainer {
|
|||
let v: &MapSet = content.as_map().unwrap();
|
||||
let order = TotalOrderStamp {
|
||||
lamport,
|
||||
client_id: op.id_start().client_id,
|
||||
client_id: id_span.client_id,
|
||||
};
|
||||
if let Some(slot) = self.state.get_mut(&v.key) {
|
||||
if slot.order < order {
|
||||
|
@ -123,7 +123,7 @@ impl Container for MapContainer {
|
|||
ValueSlot {
|
||||
value: v.value.clone(),
|
||||
order,
|
||||
counter: op.id_start().counter,
|
||||
counter: op.counter,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use rle::{rle_tree::tree_trait::CumulateTreeTrait, RleTree, Sliceable};
|
||||
use rle::{rle_tree::tree_trait::CumulateTreeTrait, HasLength, RleTree, Sliceable};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::{
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
|||
log_store::LogStoreWeakRef,
|
||||
op::{InsertContent, Op, OpContent, RemoteOp},
|
||||
smstring::SmString,
|
||||
span::{HasIdSpan, IdSpan},
|
||||
span::{HasCounter, HasCounterSpan, HasIdSpan, IdSpan},
|
||||
value::LoroValue,
|
||||
LogStore, VersionVector,
|
||||
};
|
||||
|
@ -82,7 +82,10 @@ impl TextContainer {
|
|||
},
|
||||
store.get_or_create_container_idx(&self.id),
|
||||
);
|
||||
let last_id = op.id_last();
|
||||
let last_id = ID::new(
|
||||
store.this_client_id,
|
||||
op.counter + op.atom_len() as Counter - 1,
|
||||
);
|
||||
store.append_local_ops(&[op]);
|
||||
self.head = smallvec![last_id];
|
||||
self.vv.set_last(last_id);
|
||||
|
@ -106,7 +109,7 @@ impl TextContainer {
|
|||
store.get_or_create_container_idx(&self.id),
|
||||
);
|
||||
|
||||
let last_id = op.id_last();
|
||||
let last_id = ID::new(store.this_client_id, op.ctr_last());
|
||||
store.append_local_ops(&[op]);
|
||||
self.state.delete_range(Some(pos), Some(pos + len));
|
||||
self.head = smallvec![last_id];
|
||||
|
@ -198,7 +201,13 @@ impl Container for TextContainer {
|
|||
for op in change.ops.iter() {
|
||||
if op.container == self_idx {
|
||||
// TODO: convert op to local
|
||||
self.tracker.apply(op.id, &op.content)
|
||||
self.tracker.apply(
|
||||
ID {
|
||||
client_id: change.id.client_id,
|
||||
counter: op.counter,
|
||||
},
|
||||
&op.content,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
|||
id::{ClientID, Counter},
|
||||
isomorph::{Irc, IsoRw, IsoWeak},
|
||||
op::RemoteOp,
|
||||
span::{HasIdSpan, HasLamportSpan, IdSpan},
|
||||
span::{HasCounterSpan, HasIdSpan, HasLamportSpan, IdSpan},
|
||||
Lamport, Op, Timestamp, VersionVector, ID,
|
||||
};
|
||||
|
||||
|
@ -257,7 +257,9 @@ impl LogStore {
|
|||
client_id: self.this_client_id,
|
||||
counter: self.get_next_counter(self.this_client_id),
|
||||
};
|
||||
let last_id = ops.last().unwrap().id_last();
|
||||
let last = ops.last().unwrap();
|
||||
let last_ctr = last.ctr_last();
|
||||
let last_id = ID::new(self.this_client_id, last_ctr);
|
||||
let change = Change {
|
||||
id,
|
||||
deps: std::mem::replace(&mut self.frontier, smallvec::smallvec![last_id]),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::Op;
|
||||
|
||||
use crate::change::Lamport;
|
||||
use crate::container::ContainerID;
|
||||
|
||||
use crate::id::ClientID;
|
||||
use crate::id::ContainerIdx;
|
||||
|
@ -93,7 +92,7 @@ impl<'a> Iterator for OpSpanIter<'a> {
|
|||
|
||||
return Some(RichOp {
|
||||
op,
|
||||
lamport: (op.id.counter - change.id.counter) as Lamport + change.lamport,
|
||||
lamport: (op.counter - change.id.counter) as Lamport + change.lamport,
|
||||
timestamp: change.timestamp,
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
change::{Lamport, Timestamp},
|
||||
container::ContainerID,
|
||||
id::{Counter, ID},
|
||||
span::HasId,
|
||||
span::HasCounter,
|
||||
LogStore,
|
||||
};
|
||||
use rle::{HasIndex, HasLength, Mergable, Sliceable};
|
||||
|
@ -31,14 +31,14 @@ pub enum OpType {
|
|||
/// A Op may have multiple atomic operations, since Op can be merged.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Op {
|
||||
pub(crate) id: ID,
|
||||
pub(crate) counter: Counter,
|
||||
pub(crate) container: u32,
|
||||
pub(crate) content: OpContent,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RemoteOp {
|
||||
pub(crate) id: ID,
|
||||
pub(crate) counter: Counter,
|
||||
pub(crate) container: ContainerID,
|
||||
pub(crate) content: OpContent,
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ impl Op {
|
|||
#[inline]
|
||||
pub(crate) fn new(id: ID, content: OpContent, container: u32) -> Self {
|
||||
Op {
|
||||
id,
|
||||
counter: id.counter,
|
||||
content,
|
||||
container,
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl Op {
|
|||
pub(crate) fn convert(self, log: &LogStore) -> RemoteOp {
|
||||
let container = log.get_container_id(self.container).clone();
|
||||
RemoteOp {
|
||||
id: self.id,
|
||||
counter: self.counter,
|
||||
container,
|
||||
content: self.content,
|
||||
}
|
||||
|
@ -78,11 +78,10 @@ impl Op {
|
|||
|
||||
impl RemoteOp {
|
||||
pub(crate) fn convert(self, log: &mut LogStore) -> Op {
|
||||
let id = self.id;
|
||||
let container = log.get_or_create_container_idx(&self.container);
|
||||
let content = self.content;
|
||||
Op {
|
||||
id,
|
||||
counter: self.counter,
|
||||
container,
|
||||
content,
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ impl RemoteOp {
|
|||
|
||||
impl Mergable for Op {
|
||||
fn is_mergable(&self, other: &Self, cfg: &()) -> bool {
|
||||
self.id.is_connected_id(&other.id, self.content_len())
|
||||
self.counter + self.content_len() as Counter == other.counter
|
||||
&& self.content.is_mergable(&other.content, cfg)
|
||||
&& self.container == other.container
|
||||
}
|
||||
|
@ -135,10 +134,7 @@ impl Sliceable for Op {
|
|||
assert!(to > from);
|
||||
let content: OpContent = self.content.slice(from, to);
|
||||
Op {
|
||||
id: ID {
|
||||
client_id: self.id.client_id,
|
||||
counter: (self.id.counter + from as Counter),
|
||||
},
|
||||
counter: (self.counter + from as Counter),
|
||||
content,
|
||||
container: self.container.clone(),
|
||||
}
|
||||
|
@ -147,7 +143,7 @@ impl Sliceable for Op {
|
|||
|
||||
impl Mergable for RemoteOp {
|
||||
fn is_mergable(&self, other: &Self, cfg: &()) -> bool {
|
||||
self.id.is_connected_id(&other.id, self.content_len())
|
||||
self.counter + self.content_len() as Counter == other.counter
|
||||
&& self.content.is_mergable(&other.content, cfg)
|
||||
&& self.container == other.container
|
||||
}
|
||||
|
@ -191,22 +187,13 @@ impl Sliceable for RemoteOp {
|
|||
assert!(to > from);
|
||||
let content: OpContent = self.content.slice(from, to);
|
||||
RemoteOp {
|
||||
id: ID {
|
||||
client_id: self.id.client_id,
|
||||
counter: (self.id.counter + from as Counter),
|
||||
},
|
||||
counter: (self.counter + from as Counter),
|
||||
content,
|
||||
container: self.container.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasId for Op {
|
||||
fn id_start(&self) -> ID {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RichOp<'a> {
|
||||
pub op: &'a Op,
|
||||
pub lamport: Lamport,
|
||||
|
@ -217,7 +204,7 @@ impl HasIndex for Op {
|
|||
type Int = Counter;
|
||||
|
||||
fn get_start_index(&self) -> Self::Int {
|
||||
self.id.counter
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,6 +212,18 @@ impl HasIndex for RemoteOp {
|
|||
type Int = Counter;
|
||||
|
||||
fn get_start_index(&self) -> Self::Int {
|
||||
self.id.counter
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
||||
impl HasCounter for Op {
|
||||
fn ctr_start(&self) -> Counter {
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
||||
impl HasCounter for RemoteOp {
|
||||
fn ctr_start(&self) -> Counter {
|
||||
self.counter
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,6 +218,36 @@ pub trait HasId {
|
|||
fn id_start(&self) -> ID;
|
||||
}
|
||||
|
||||
pub trait HasCounter {
|
||||
fn ctr_start(&self) -> Counter;
|
||||
}
|
||||
|
||||
pub trait HasCounterSpan: HasCounter + HasLength {
|
||||
fn ctr_end(&self) -> Counter {
|
||||
self.ctr_start() + self.atom_len() as Counter
|
||||
}
|
||||
|
||||
fn ctr_last(&self) -> Counter {
|
||||
self.ctr_start() + self.atom_len() as Counter - 1
|
||||
}
|
||||
|
||||
fn ctr_span(&self) -> CounterSpan {
|
||||
CounterSpan {
|
||||
start: self.ctr_start(),
|
||||
end: self.ctr_end(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasCounter + HasLength> HasCounterSpan for T {}
|
||||
|
||||
impl<T: HasId> HasCounter for T {
|
||||
#[inline]
|
||||
fn ctr_start(&self) -> Counter {
|
||||
self.id_start().counter
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasIdSpan: HasId + HasLength {
|
||||
fn intersect<T: HasIdSpan>(&self, other: &T) -> bool {
|
||||
let self_start = self.id_start();
|
||||
|
@ -250,14 +280,6 @@ pub trait HasIdSpan: HasId + HasLength {
|
|||
self.id_start().inc(self.content_len() as i32 - 1)
|
||||
}
|
||||
|
||||
fn ctr_last(&self) -> Counter {
|
||||
self.id_start().counter + self.content_len() as i32 - 1
|
||||
}
|
||||
|
||||
fn ctr_first(&self) -> Counter {
|
||||
self.id_start().counter
|
||||
}
|
||||
|
||||
fn contains_id(&self, id: ID) -> bool {
|
||||
let id_start = self.id_start();
|
||||
if id.client_id != id_start.client_id {
|
||||
|
|
Loading…
Reference in a new issue