Use Rust erasure library and turn on erasure (#3768)

* split out erasure into new crate; add implementation using rust reed-solomon-library

* Track erasures with a &[bool] instead of indexes

* fix bug that reported the number of erasures incorrectly

* Introduce erasure `Session` for consistent config

* Increase test coverage; fix bugs

* Add ability to remove blobs from erasure meta tracking. test added

* Track deletion of coding blobs in blocktree via ErasureMeta. Added to
test

* Remove unused functions in blocktree

* add randomness to recovery thread to exercise recovery due to either new
data or coding blobs

* Add unit test for ErasureMeta index handling

* Re-enable test in broadcast stage
This commit is contained in:
Mark E. Sinclair
2019-04-16 23:00:24 -05:00
committed by GitHub
parent 1e20d449ce
commit b9bb5af4a5
12 changed files with 638 additions and 765 deletions

View File

@@ -1,4 +1,3 @@
#[cfg(feature = "erasure")]
use crate::erasure::{NUM_CODING, NUM_DATA};
#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
@@ -59,7 +58,6 @@ impl SlotMeta {
}
}
#[cfg(feature = "erasure")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
/// Erasure coding information
pub struct ErasureMeta {
@@ -71,7 +69,6 @@ pub struct ErasureMeta {
pub coding: u64,
}
#[cfg(feature = "erasure")]
impl ErasureMeta {
pub fn new(set_index: u64) -> ErasureMeta {
ErasureMeta {
@@ -91,36 +88,56 @@ impl ErasureMeta {
}
pub fn is_coding_present(&self, index: u64) -> bool {
let set_index = Self::set_index_for(index);
let position = index - self.start_index();
let start = self.start_index();
let end = start + NUM_CODING as u64;
set_index == self.set_index && self.coding & (1 << position) != 0
if start <= index && index < end {
let position = index - start;
self.coding & (1 << position) != 0
} else {
false
}
}
pub fn set_coding_present(&mut self, index: u64) {
pub fn set_coding_present(&mut self, index: u64, present: bool) {
let set_index = Self::set_index_for(index);
if set_index as u64 == self.set_index {
let position = index - self.start_index();
self.coding |= 1 << position;
if present {
self.coding |= 1 << position;
} else {
self.coding &= !(1 << position);
}
}
}
pub fn is_data_present(&self, index: u64) -> bool {
let set_index = Self::set_index_for(index);
let position = index - self.start_index();
let start = self.start_index();
let end = start + NUM_DATA as u64;
set_index == self.set_index && self.data & (1 << position) != 0
if start <= index && index < end {
let position = index - start;
self.data & (1 << position) != 0
} else {
false
}
}
pub fn set_data_present(&mut self, index: u64) {
pub fn set_data_present(&mut self, index: u64, present: bool) {
let set_index = Self::set_index_for(index);
if set_index as u64 == self.set_index {
let position = index - self.start_index();
self.data |= 1 << position;
if present {
self.data |= 1 << position;
} else {
self.data &= !(1 << position);
}
}
}
@@ -139,7 +156,29 @@ impl ErasureMeta {
}
}
#[cfg(feature = "erasure")]
#[test]
fn test_meta_indexes() {
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
for _ in 0..100 {
let set_index = rng.gen_range(0, 1_000);
let blob_index = (set_index * NUM_DATA as u64) + rng.gen_range(0, 16);
assert_eq!(set_index, ErasureMeta::set_index_for(blob_index));
let e_meta = ErasureMeta::new(set_index);
assert_eq!(e_meta.start_index(), set_index * NUM_DATA as u64);
let (data_end_idx, coding_end_idx) = e_meta.end_indexes();
assert_eq!(data_end_idx, (set_index + 1) * NUM_DATA as u64);
assert_eq!(
coding_end_idx,
set_index * NUM_DATA as u64 + NUM_CODING as u64
);
}
}
#[test]
fn test_meta_coding_present() {
let set_index = 0;
@@ -150,7 +189,7 @@ fn test_meta_coding_present() {
};
for i in 0..NUM_CODING as u64 {
e_meta.set_coding_present(i);
e_meta.set_coding_present(i, true);
assert_eq!(e_meta.is_coding_present(i), true);
}
for i in NUM_CODING as u64..NUM_DATA as u64 {
@@ -160,7 +199,7 @@ fn test_meta_coding_present() {
e_meta.set_index = ErasureMeta::set_index_for((NUM_DATA * 17) as u64);
for i in (NUM_DATA * 17) as u64..((NUM_DATA * 17) + NUM_CODING) as u64 {
e_meta.set_coding_present(i);
e_meta.set_coding_present(i, true);
assert_eq!(e_meta.is_coding_present(i), true);
}
for i in (NUM_DATA * 17 + NUM_CODING) as u64..((NUM_DATA * 17) + NUM_DATA) as u64 {
@@ -168,7 +207,6 @@ fn test_meta_coding_present() {
}
}
#[cfg(feature = "erasure")]
#[test]
fn test_can_recover() {
let set_index = 0;
@@ -211,3 +249,31 @@ fn test_can_recover() {
e_meta.data = 0b1111_1111_1111_1000;
assert!(e_meta.can_recover());
}
#[test]
fn test_meta_data_present() {
let set_index = 0;
let mut e_meta = ErasureMeta {
set_index,
data: 0,
coding: 0,
};
for i in 0..NUM_DATA as u64 {
e_meta.set_data_present(i, true);
assert_eq!(e_meta.is_data_present(i), true);
}
for i in NUM_DATA as u64..2 * NUM_DATA as u64 {
assert_eq!(e_meta.is_data_present(i), false);
}
e_meta.set_index = ErasureMeta::set_index_for((NUM_DATA * 23) as u64);
for i in (NUM_DATA * 23) as u64..(NUM_DATA * 24) as u64 {
e_meta.set_data_present(i, true);
assert_eq!(e_meta.is_data_present(i), true);
}
for i in (NUM_DATA * 22) as u64..(NUM_DATA * 23) as u64 {
assert_eq!(e_meta.is_data_present(i), false);
}
}