mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 21:07:43 +00:00
bk: tree impl (untested)
This commit is contained in:
parent
3729deb12d
commit
a290f29bb5
1 changed files with 180 additions and 1 deletions
|
@ -663,8 +663,16 @@ impl TreeState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn tree_nodes(&self) -> Vec<TreeNode> {
|
pub(crate) fn tree_nodes(&self) -> Vec<TreeNode> {
|
||||||
|
self.get_all_tree_nodes_under(TreeParentId::Root)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn deleted_tree_nodes(&self) -> Vec<TreeNode> {
|
||||||
|
self.get_all_tree_nodes_under(TreeParentId::Deleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_all_tree_nodes_under(&self, root: TreeParentId) -> Vec<TreeNode> {
|
||||||
let mut ans = vec![];
|
let mut ans = vec![];
|
||||||
let children = self.children.get(&TreeParentId::Root);
|
let children = self.children.get(&root);
|
||||||
let mut q = children
|
let mut q = children
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
VecDeque::from_iter(x.iter().enumerate().zip(std::iter::repeat(None::<TreeID>)))
|
VecDeque::from_iter(x.iter().enumerate().zip(std::iter::repeat(None::<TreeID>)))
|
||||||
|
@ -1177,3 +1185,174 @@ mod jitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod snapshot {
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use fractional_index::FractionalIndex;
|
||||||
|
use loro_common::{IdFull, PeerID, TreeID};
|
||||||
|
use serde_columnar::columnar;
|
||||||
|
|
||||||
|
use crate::{encoding::value_register::ValueRegister, state::FastStateSnashot};
|
||||||
|
|
||||||
|
use super::{TreeNode, TreeParentId, TreeState};
|
||||||
|
|
||||||
|
#[columnar(vec, ser, de, iterable)]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct EncodedTreeNode {
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
peer_idx: usize,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
counter: i32,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
parent_peer_idx: usize,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
parent_counter: i32,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
last_set_peer_idx: usize,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
last_set_counter: i32,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
last_set_lamport: u32,
|
||||||
|
#[columnar(strategy = "DeltaRle")]
|
||||||
|
index: u32,
|
||||||
|
position: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[columnar(ser, de)]
|
||||||
|
struct EncodedTree {
|
||||||
|
#[columnar(class = "vec", iter = "EncodedTreeNode")]
|
||||||
|
nodes: Vec<EncodedTreeNode>,
|
||||||
|
alive_len: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(
|
||||||
|
state: &TreeState,
|
||||||
|
input: Vec<TreeNode>,
|
||||||
|
alive_len: usize,
|
||||||
|
) -> (ValueRegister<PeerID>, EncodedTree) {
|
||||||
|
let mut peers: ValueRegister<PeerID> = ValueRegister::new();
|
||||||
|
let mut nodes = Vec::with_capacity(input.len());
|
||||||
|
for node in input {
|
||||||
|
let n = state.trees.get(&node.id).unwrap();
|
||||||
|
let last_set_id = n.last_move_op;
|
||||||
|
nodes.push(EncodedTreeNode {
|
||||||
|
peer_idx: peers.register(&node.id.peer),
|
||||||
|
counter: node.id.counter,
|
||||||
|
// FIXME: this unwrap may panic
|
||||||
|
parent_peer_idx: peers.register(&node.parent.unwrap().peer),
|
||||||
|
// FIXME: this unwrap may panic
|
||||||
|
parent_counter: node.parent.unwrap().counter,
|
||||||
|
last_set_peer_idx: peers.register(&last_set_id.peer),
|
||||||
|
last_set_counter: last_set_id.counter,
|
||||||
|
last_set_lamport: last_set_id.lamport,
|
||||||
|
index: node.index as u32,
|
||||||
|
position: node.position.as_bytes().to_vec(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
peers,
|
||||||
|
EncodedTree {
|
||||||
|
nodes,
|
||||||
|
alive_len: alive_len as u32,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FastStateSnashot for TreeState {
|
||||||
|
fn encode_snapshot_fast<W: std::io::prelude::Write>(&mut self, mut w: W) {
|
||||||
|
let alive_tree_nodes = self.tree_nodes();
|
||||||
|
let deleted_tree_nodes = self.deleted_tree_nodes();
|
||||||
|
let alive_len = alive_tree_nodes.len();
|
||||||
|
let mut all_nodes = alive_tree_nodes;
|
||||||
|
all_nodes.extend(deleted_tree_nodes);
|
||||||
|
let (peers, encoded) = encode(self, all_nodes, alive_len);
|
||||||
|
let peers = peers.unwrap_vec();
|
||||||
|
leb128::write::unsigned(&mut w, peers.len() as u64).unwrap();
|
||||||
|
for peer in peers {
|
||||||
|
w.write_all(&peer.to_le_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let vec = serde_columnar::to_vec(&encoded).unwrap();
|
||||||
|
w.write_all(&vec).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_value(
|
||||||
|
mut bytes: &[u8],
|
||||||
|
) -> loro_common::LoroResult<(loro_common::LoroValue, &[u8])> {
|
||||||
|
// TODO: PREF: FIXME: The performance for decoding the whole tree
|
||||||
|
// can be improved a lot
|
||||||
|
let peer_num = leb128::read::unsigned(&mut bytes).unwrap() as usize;
|
||||||
|
let mut peers = Vec::with_capacity(peer_num);
|
||||||
|
for _ in 0..peer_num {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
bytes.read_exact(&mut buf).unwrap();
|
||||||
|
peers.push(PeerID::from_le_bytes(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
let encoded: EncodedTree = serde_columnar::from_bytes(bytes)?;
|
||||||
|
let mut nodes = Vec::new();
|
||||||
|
for node in encoded.nodes.into_iter().take(encoded.alive_len as usize) {
|
||||||
|
let node = TreeNode {
|
||||||
|
id: TreeID::new(peers[node.peer_idx], node.counter),
|
||||||
|
parent: Some(TreeID::new(
|
||||||
|
peers[node.parent_peer_idx],
|
||||||
|
node.parent_counter,
|
||||||
|
)),
|
||||||
|
position: FractionalIndex::from_bytes(node.position),
|
||||||
|
index: node.index as usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.push(node.into_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((nodes.into(), bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_snapshot_fast(
|
||||||
|
idx: crate::container::idx::ContainerIdx,
|
||||||
|
(_, mut bytes): (loro_common::LoroValue, &[u8]),
|
||||||
|
ctx: crate::state::ContainerCreationContext,
|
||||||
|
) -> loro_common::LoroResult<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let peer_num = leb128::read::unsigned(&mut bytes).unwrap() as usize;
|
||||||
|
let mut peers = Vec::with_capacity(peer_num);
|
||||||
|
for _ in 0..peer_num {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
bytes.read_exact(&mut buf).unwrap();
|
||||||
|
peers.push(PeerID::from_le_bytes(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut tree =
|
||||||
|
TreeState::new(idx, ctx.peer, ctx.configure.tree_position_jitter.clone());
|
||||||
|
let encoded: EncodedTree = serde_columnar::from_bytes(bytes)?;
|
||||||
|
for (i, node) in encoded.nodes.into_iter().enumerate() {
|
||||||
|
let is_dead = i >= encoded.alive_len as usize;
|
||||||
|
tree.mov(
|
||||||
|
TreeID::new(peers[node.peer_idx], node.counter),
|
||||||
|
if is_dead {
|
||||||
|
TreeParentId::Deleted
|
||||||
|
} else {
|
||||||
|
TreeParentId::Node(TreeID::new(
|
||||||
|
peers[node.parent_peer_idx],
|
||||||
|
node.parent_counter,
|
||||||
|
))
|
||||||
|
},
|
||||||
|
IdFull::new(
|
||||||
|
peers[node.last_set_peer_idx],
|
||||||
|
node.last_set_counter,
|
||||||
|
node.last_set_lamport,
|
||||||
|
),
|
||||||
|
Some(FractionalIndex::from_bytes(node.position)),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue