fix: encode when only create container but no op

This commit is contained in:
leeeon233 2022-11-16 15:35:08 +08:00
parent 33edd89e6e
commit f468e3b57b
10 changed files with 122 additions and 18 deletions

1
Cargo.lock generated
View file

@ -302,6 +302,7 @@ version = "0.1.0"
dependencies = [
"bincode",
"columnar_derive",
"flate2",
"itertools",
"lazy_static",
"postcard",

View file

@ -1,10 +1,6 @@
use std::{
io::{Read, Write},
time::Instant,
};
use std::{io::Read, time::Instant};
use flate2::write::GzEncoder;
use flate2::{read::GzDecoder, Compression};
use flate2::read::GzDecoder;
use loro_core::{configure::Configure, container::registry::ContainerWrapper, LoroCore};
use serde_json::Value;
const RAW_DATA: &[u8; 901823] = include_bytes!("../benches/automerge-paper.json.gz");
@ -64,8 +60,12 @@ fn main() {
}
println!("Longest continuous bytes length {}", max_count);
let mut e = GzEncoder::new(Vec::new(), Compression::new(6));
e.write_all(&buf).unwrap();
let result = e.finish().unwrap();
println!("GZipped Size {}", result.len());
use columnar::{compress, CompressConfig};
let s = Instant::now();
let result = compress(&buf, &CompressConfig::default()).unwrap();
println!(
"GZipped Size {} time: {}ms",
result.len(),
s.elapsed().as_millis()
);
}

View file

@ -8,6 +8,12 @@ version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.19"
@ -177,6 +183,7 @@ version = "0.1.0"
dependencies = [
"bincode",
"columnar_derive",
"flate2",
"itertools",
"lazy_static",
"postcard",
@ -206,6 +213,15 @@ dependencies = [
"volatile-register",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crdt-list"
version = "0.3.0"
@ -303,6 +319,16 @@ dependencies = [
"syn",
]
[[package]]
name = "flate2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -504,6 +530,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
[[package]]
name = "nb"
version = "0.1.3"

View file

@ -53,3 +53,9 @@ name = "recursive"
path = "fuzz_targets/recursive.rs"
test = false
doc = false
[[bin]]
name = "encode"
path = "fuzz_targets/encode.rs"
test = false
doc = false

View file

@ -0,0 +1,8 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use loro_core::fuzz::{test_single_client_encode, Action};
fuzz_target!(|data: Vec<Action>| {
// fuzzed code goes here
test_single_client_encode(data)
});

View file

@ -411,7 +411,7 @@ impl Container for ListContainer {
values.into()
}
fn to_export(&mut self, op: &mut RemoteOp, gc: bool) {
fn to_export(&mut self, op: &mut RemoteOp, _gc: bool) {
for content in op.contents.iter_mut() {
if let Some((slice, _pos)) = content
.as_normal_mut()

View file

@ -189,7 +189,7 @@ impl Container for MapContainer {
todo!()
}
fn to_export(&mut self, _op: &mut RemoteOp, gc: bool) {}
fn to_export(&mut self, _op: &mut RemoteOp, _gc: bool) {}
fn to_import(&mut self, _op: &mut RemoteOp) {}
}

View file

@ -265,6 +265,40 @@ pub fn test_single_client(mut actions: Vec<Action>) {
}
}
pub fn test_single_client_encode(mut actions: Vec<Action>) {
let mut store = LoroCore::new(Default::default(), None);
let mut text_container = store.get_text("hello");
let mut ground_truth = String::new();
let mut applied = Vec::new();
for action in actions
.iter_mut()
.filter(|x| x.as_del().is_some() || x.as_ins().is_some())
{
ground_truth.preprocess(action);
applied.push(action.clone());
// println!("{}", (&applied).table());
ground_truth.apply_action(action);
match action {
Action::Ins { content, pos, .. } => {
text_container.insert(&store, *pos, &content.to_string());
}
Action::Del { pos, len, .. } => {
if text_container.text_len() == 0 {
return;
}
text_container.delete(&store, *pos, *len);
}
_ => {}
}
}
let encode_bytes = store.encode_snapshot();
let store2 =
LoroCore::decode_snapshot(&encode_bytes, None, crate::configure::Configure::default());
let encode_bytes2 = store2.encode_snapshot();
assert_eq!(encode_bytes, encode_bytes2);
}
pub fn minify_error<T, F, N>(site_num: u8, actions: Vec<T>, f: F, normalize: N)
where
F: Fn(u8, &mut [T]),
@ -616,4 +650,13 @@ mod test {
fn mini() {
minify_error(8, vec![], test_multi_sites, normalize)
}
#[test]
fn case_encode() {
test_single_client_encode(vec![Ins {
content: 49087,
pos: 4631600097073807295,
site: 191,
}])
}
}

View file

@ -1,4 +1,4 @@
use std::{collections::HashSet, fmt::Debug, panic::UnwindSafe, time::Instant};
use std::{collections::HashSet, fmt::Debug};
use arbitrary::Arbitrary;
use enum_as_inner::EnumAsInner;

View file

@ -51,9 +51,11 @@ struct OpEncoding {
#[columnar(strategy = "Rle", original_type = "u32")]
container: ContainerIdx,
/// key index or insert/delete pos
prop: usize,
#[columnar(strategy = "DeltaRle")]
prop: usize, // 18225 bytes
// TODO: can be compressed
gc: usize,
// #[columnar(compress(level = 0))]
value: LoroValue,
}
@ -85,7 +87,6 @@ struct Encoded {
#[columnar(type = "vec")]
deps: Vec<DepsEncoding>,
clients: Clients,
// TODO: can be compressed
containers: Containers,
keys: Vec<InternalString>,
}
@ -206,13 +207,25 @@ fn decode_changes(
} = encoded;
if change_encodings.is_empty() {
return LogStore::new(cfg, None);
let store = LogStore::new(cfg, None);
if !containers.is_empty() {
let mut s = store.write().unwrap();
for container in containers.iter() {
s.get_or_create_container(container);
}
drop(s);
}
return store;
}
let mut container_reg = ContainerRegistry::new();
let mut op_iter = ops.into_iter();
let mut changes = FxHashMap::default();
let mut deps_iter = deps.into_iter();
for container in containers.iter() {
container_reg.get_or_create(container);
}
for change_encoding in change_encodings {
let ChangeEncoding {
client_idx,
@ -242,8 +255,6 @@ fn decode_changes(
} = op;
let container_id = containers[container as usize].clone();
container_reg.get_or_create(&container_id);
let container_type = container_id.container_type();
let content = match container_type {
ContainerType::Map => {