refactor: only keep counter on op

This commit is contained in:
Zixuan Chen 2022-11-01 00:07:24 +08:00
parent 6e03c9c04b
commit d62fa09e99
6 changed files with 77 additions and 46 deletions

View file

@ -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,
},
);

View file

@ -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,
)
}
}
}

View file

@ -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]),

View file

@ -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 {

View file

@ -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
}
}

View file

@ -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 {