mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-09 14:49:25 +00:00
+40
-20
@@ -6,7 +6,8 @@ use lazy_static::lazy_static;
|
||||
use sha2::{digest::core_api::BlockSizeUser, Digest, Sha256};
|
||||
use tokio::{
|
||||
spawn,
|
||||
sync::mpsc::{self, Sender}, task::JoinHandle,
|
||||
sync::mpsc::{self, Sender},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -33,7 +34,7 @@ lazy_static! {
|
||||
// ];
|
||||
const MAGIC_HIGHWAY_HASH256_KEY: &[u64; 4] = &[3, 4, 2, 1];
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Hasher {
|
||||
SHA256(Sha256),
|
||||
HighwayHash256(HighwayHasher),
|
||||
@@ -116,6 +117,7 @@ impl BitrotAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BitrotVerifier {
|
||||
_algorithm: BitrotAlgorithm,
|
||||
_sum: Vec<u8>,
|
||||
@@ -140,7 +142,7 @@ pub fn bitrot_algorithm_from_string(s: &str) -> BitrotAlgorithm {
|
||||
BitrotAlgorithm::HighwayHash256S
|
||||
}
|
||||
|
||||
type BitrotWriter = Box<dyn Write + Send>;
|
||||
pub type BitrotWriter = Box<dyn Write + Send>;
|
||||
|
||||
pub async fn new_bitrot_writer(
|
||||
disk: DiskStore,
|
||||
@@ -159,7 +161,7 @@ pub async fn new_bitrot_writer(
|
||||
Ok(Box::new(WholeBitrotWriter::new(disk, volume, file_path, algo, shard_size)))
|
||||
}
|
||||
|
||||
type BitrotReader = Box<dyn ReadAt>;
|
||||
pub type BitrotReader = Box<dyn ReadAt + Send>;
|
||||
|
||||
pub fn new_bitrot_reader(
|
||||
disk: DiskStore,
|
||||
@@ -177,6 +179,16 @@ pub fn new_bitrot_reader(
|
||||
Box::new(WholeBitrotReader::new(disk, bucket, file_path, algo, till_offset, sum))
|
||||
}
|
||||
|
||||
pub async fn close_bitrot_writers(writers: &mut [Option<BitrotWriter>]) -> Result<()> {
|
||||
for w in writers.into_iter() {
|
||||
if let Some(w) = w {
|
||||
let _ = w.close().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bitrot_writer_sum(w: &BitrotWriter) -> Vec<u8> {
|
||||
if let Some(w) = w.as_any().downcast_ref::<WholeBitrotWriter>() {
|
||||
return w.hash.clone().finalize();
|
||||
@@ -245,6 +257,7 @@ impl Write for WholeBitrotWriter {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WholeBitrotReader {
|
||||
disk: DiskStore,
|
||||
volume: String,
|
||||
@@ -292,7 +305,7 @@ impl ReadAt for WholeBitrotReader {
|
||||
struct StreamingBitrotWriter {
|
||||
hasher: Hasher,
|
||||
tx: Sender<Option<Vec<u8>>>,
|
||||
task: JoinHandle<()>,
|
||||
task: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl StreamingBitrotWriter {
|
||||
@@ -322,7 +335,11 @@ impl StreamingBitrotWriter {
|
||||
}
|
||||
});
|
||||
|
||||
Ok(StreamingBitrotWriter { hasher, tx, task })
|
||||
Ok(StreamingBitrotWriter {
|
||||
hasher,
|
||||
tx,
|
||||
task: Some(task),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,20 +356,22 @@ impl Write for StreamingBitrotWriter {
|
||||
self.hasher.reset();
|
||||
self.hasher.update(&buf);
|
||||
let hash_bytes = self.hasher.clone().finalize();
|
||||
println!("hash_bytes len: {}, buf len: {}", hash_bytes.len(), buf.len());
|
||||
let _ = self.tx.send(Some(hash_bytes)).await?;
|
||||
let _ = self.tx.send(Some(buf.to_vec())).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn close(self: Box<Self>) -> Result<()> {
|
||||
async fn close(&mut self) -> Result<()> {
|
||||
let _ = self.tx.send(None).await?;
|
||||
let _ = self.task.await;
|
||||
if let Some(task) = self.task.take() {
|
||||
let _ = task.await; // 等待任务完成
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StreamingBitrotReader {
|
||||
disk: DiskStore,
|
||||
_data: Vec<u8>,
|
||||
@@ -395,7 +414,6 @@ impl StreamingBitrotReader {
|
||||
#[async_trait::async_trait]
|
||||
impl ReadAt for StreamingBitrotReader {
|
||||
async fn read_at(&mut self, offset: usize, length: usize) -> Result<(Vec<u8>, usize)> {
|
||||
println!("in read_at");
|
||||
if offset % self.shard_size != 0 {
|
||||
return Err(Error::new(DiskError::Unexpected));
|
||||
}
|
||||
@@ -404,9 +422,7 @@ impl ReadAt for StreamingBitrotReader {
|
||||
let stream_offset = (offset / self.shard_size) * self.hasher.size() + offset;
|
||||
let buf_len = self.till_offset - stream_offset;
|
||||
let mut file = self.disk.read_file(&self.volume, &self.file_path).await?;
|
||||
println!("stream_offset: {}, buf_len: {}", stream_offset, buf_len);
|
||||
let (buf, _) = file.read_at(stream_offset, buf_len).await?;
|
||||
println!("buf: {:?}, len: {}", buf, buf.len());
|
||||
self.buf = buf;
|
||||
}
|
||||
if offset != self.curr_offset {
|
||||
@@ -415,12 +431,10 @@ impl ReadAt for StreamingBitrotReader {
|
||||
|
||||
self.hash_bytes = self.buf.drain(0..self.hash_bytes.capacity()).collect();
|
||||
let buf = self.buf.drain(0..length).collect::<Vec<_>>();
|
||||
println!("self.buf: {:?}", self.buf);
|
||||
self.hasher.reset();
|
||||
self.hasher.update(&buf);
|
||||
let actual = self.hasher.clone().finalize();
|
||||
if actual != self.hash_bytes {
|
||||
println!("except: {:?}, actual: {:?}", self.hash_bytes, actual);
|
||||
return Err(Error::new(DiskError::FileCorrupt));
|
||||
}
|
||||
|
||||
@@ -488,10 +502,8 @@ mod test {
|
||||
}
|
||||
|
||||
if checksum != sum {
|
||||
println!("failed: {:?}, expect: {:?}, actual: {:?}", algo, checksum, sum);
|
||||
return Err(Error::new(DiskError::FileCorrupt));
|
||||
}
|
||||
println!("success: {:?}", algo);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -500,6 +512,9 @@ mod test {
|
||||
#[tokio::test]
|
||||
async fn test_all_bitrot_algorithms() -> Result<()> {
|
||||
for algo in BITROT_ALGORITHMS.keys() {
|
||||
if *algo != BitrotAlgorithm::HighwayHash256S {
|
||||
continue;
|
||||
}
|
||||
test_bitrot_reader_writer_algo(algo.clone()).await?;
|
||||
}
|
||||
|
||||
@@ -528,10 +543,15 @@ mod test {
|
||||
|
||||
let mut reader = new_bitrot_reader(disk, b"", volume, file_path, 35, algo, &sum, 10);
|
||||
let read_len = 10;
|
||||
(_, _) = reader.read_at(0, read_len).await?;
|
||||
(_, _) = reader.read_at(10, read_len).await?;
|
||||
(_, _) = reader.read_at(20, read_len).await?;
|
||||
(_, _) = reader.read_at(30, read_len / 2).await?;
|
||||
let mut result: Vec<u8>;
|
||||
(result, _) = reader.read_at(0, read_len).await?;
|
||||
assert_eq!(result, b"aaaaaaaaaa");
|
||||
(result, _) = reader.read_at(10, read_len).await?;
|
||||
assert_eq!(result, b"aaaaaaaaaa");
|
||||
(result, _) = reader.read_at(20, read_len).await?;
|
||||
assert_eq!(result, b"aaaaaaaaaa");
|
||||
(result, _) = reader.read_at(30, read_len / 2).await?;
|
||||
assert_eq!(result, b"aaaaa");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user