update ec share size

update bitrot
This commit is contained in:
weisd
2025-06-10 11:17:53 +08:00
parent 6ea0185519
commit 754ffd0ff2
21 changed files with 1903 additions and 1618 deletions
+6 -2
View File
@@ -93,6 +93,10 @@ pub struct ErasureInfo {
pub checksums: Vec<ChecksumInfo>,
}
pub fn calc_shard_size(block_size: usize, data_shards: usize) -> usize {
(block_size.div_ceil(data_shards) + 1) & !1
}
impl ErasureInfo {
pub fn get_checksum_info(&self, part_number: usize) -> ChecksumInfo {
for sum in &self.checksums {
@@ -109,7 +113,7 @@ impl ErasureInfo {
/// Calculate the size of each shard.
pub fn shard_size(&self) -> usize {
self.block_size.div_ceil(self.data_blocks)
calc_shard_size(self.block_size, self.data_blocks)
}
/// Calculate the total erasure file size for a given original size.
// Returns the final erasure size from the original size
@@ -120,7 +124,7 @@ impl ErasureInfo {
let num_shards = total_length / self.block_size;
let last_block_size = total_length % self.block_size;
let last_shard_size = last_block_size.div_ceil(self.data_blocks);
let last_shard_size = calc_shard_size(last_block_size, self.data_blocks);
num_shards * self.shard_size() + last_shard_size
}
+26 -29
View File
@@ -1,13 +1,12 @@
use crate::{Reader, Writer};
use pin_project_lite::pin_project;
use rustfs_utils::{HashAlgorithm, read_full, write_all};
use tokio::io::{AsyncRead, AsyncReadExt};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
pin_project! {
/// BitrotReader reads (hash+data) blocks from an async reader and verifies hash integrity.
pub struct BitrotReader {
pub struct BitrotReader<R> {
#[pin]
inner: Box<dyn Reader>,
inner: R,
hash_algo: HashAlgorithm,
shard_size: usize,
buf: Vec<u8>,
@@ -19,14 +18,12 @@ pin_project! {
}
}
impl BitrotReader {
/// Get a reference to the underlying reader.
pub fn get_ref(&self) -> &dyn Reader {
&*self.inner
}
impl<R> BitrotReader<R>
where
R: AsyncRead + Unpin + Send + Sync,
{
/// Create a new BitrotReader.
pub fn new(inner: Box<dyn Reader>, shard_size: usize, algo: HashAlgorithm) -> Self {
pub fn new(inner: R, shard_size: usize, algo: HashAlgorithm) -> Self {
let hash_size = algo.size();
Self {
inner,
@@ -86,9 +83,9 @@ impl BitrotReader {
pin_project! {
/// BitrotWriter writes (hash+data) blocks to an async writer.
pub struct BitrotWriter {
pub struct BitrotWriter<W> {
#[pin]
inner: Writer,
inner: W,
hash_algo: HashAlgorithm,
shard_size: usize,
buf: Vec<u8>,
@@ -96,9 +93,12 @@ pin_project! {
}
}
impl BitrotWriter {
impl<W> BitrotWriter<W>
where
W: AsyncWrite + Unpin + Send + Sync,
{
/// Create a new BitrotWriter.
pub fn new(inner: Writer, shard_size: usize, algo: HashAlgorithm) -> Self {
pub fn new(inner: W, shard_size: usize, algo: HashAlgorithm) -> Self {
let hash_algo = algo;
Self {
inner,
@@ -109,7 +109,7 @@ impl BitrotWriter {
}
}
pub fn into_inner(self) -> Writer {
pub fn into_inner(self) -> W {
self.inner
}
@@ -209,7 +209,7 @@ pub async fn bitrot_verify<R: AsyncRead + Unpin + Send>(
#[cfg(test)]
mod tests {
use crate::{BitrotReader, BitrotWriter, Writer};
use crate::{BitrotReader, BitrotWriter};
use rustfs_utils::HashAlgorithm;
use std::io::Cursor;
@@ -219,9 +219,9 @@ mod tests {
let data_size = data.len();
let shard_size = 8;
let buf = Vec::new();
let buf: Vec<u8> = Vec::new();
let writer = Cursor::new(buf);
let mut bitrot_writer = BitrotWriter::new(Writer::from_cursor(writer), shard_size, HashAlgorithm::HighwayHash256);
let mut bitrot_writer = BitrotWriter::new(writer, shard_size, HashAlgorithm::HighwayHash256);
let mut n = 0;
for chunk in data.chunks(shard_size) {
@@ -230,8 +230,7 @@ mod tests {
assert_eq!(n, data.len());
// 读
let reader = Cursor::new(bitrot_writer.into_inner().into_cursor_inner().unwrap());
let reader = Box::new(reader);
let reader = bitrot_writer.into_inner();
let mut bitrot_reader = BitrotReader::new(reader, shard_size, HashAlgorithm::HighwayHash256);
let mut out = Vec::new();
let mut n = 0;
@@ -253,18 +252,17 @@ mod tests {
let data = b"test data for bitrot";
let data_size = data.len();
let shard_size = 8;
let buf = Vec::new();
let buf: Vec<u8> = Vec::new();
let writer = Cursor::new(buf);
let mut bitrot_writer = BitrotWriter::new(Writer::from_cursor(writer), shard_size, HashAlgorithm::HighwayHash256);
let mut bitrot_writer = BitrotWriter::new(writer, shard_size, HashAlgorithm::HighwayHash256);
for chunk in data.chunks(shard_size) {
let _ = bitrot_writer.write(chunk).await.unwrap();
}
let mut written = bitrot_writer.into_inner().into_cursor_inner().unwrap();
let mut written = bitrot_writer.into_inner().into_inner();
// change the last byte to make hash mismatch
let pos = written.len() - 1;
written[pos] ^= 0xFF;
let reader = Cursor::new(written);
let reader = Box::new(reader);
let mut bitrot_reader = BitrotReader::new(reader, shard_size, HashAlgorithm::HighwayHash256);
let count = data_size.div_ceil(shard_size);
@@ -297,9 +295,9 @@ mod tests {
let data_size = data.len();
let shard_size = 8;
let buf = Vec::new();
let buf: Vec<u8> = Vec::new();
let writer = Cursor::new(buf);
let mut bitrot_writer = BitrotWriter::new(Writer::from_cursor(writer), shard_size, HashAlgorithm::None);
let mut bitrot_writer = BitrotWriter::new(writer, shard_size, HashAlgorithm::None);
let mut n = 0;
for chunk in data.chunks(shard_size) {
@@ -307,8 +305,7 @@ mod tests {
}
assert_eq!(n, data.len());
let reader = Cursor::new(bitrot_writer.into_inner().into_cursor_inner().unwrap());
let reader = Box::new(reader);
let reader = bitrot_writer.into_inner();
let mut bitrot_reader = BitrotReader::new(reader, shard_size, HashAlgorithm::None);
let mut out = Vec::new();
let mut n = 0;
-3
View File
@@ -30,9 +30,6 @@ pub use writer::*;
mod http_reader;
pub use http_reader::*;
mod bitrot;
pub use bitrot::*;
mod etag;
pub trait Reader: tokio::io::AsyncRead + Unpin + Send + Sync + EtagResolvable + HashReaderDetector {}