mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
Generated
+17
@@ -276,6 +276,15 @@ version = "2.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
@@ -479,6 +488,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"backon",
|
"backon",
|
||||||
"base64-simd",
|
"base64-simd",
|
||||||
|
"blake2",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
"common",
|
"common",
|
||||||
@@ -486,6 +496,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"glob",
|
"glob",
|
||||||
"hex-simd",
|
"hex-simd",
|
||||||
|
"highway",
|
||||||
"http",
|
"http",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"lock",
|
"lock",
|
||||||
@@ -796,6 +807,12 @@ dependencies = [
|
|||||||
"vsimd",
|
"vsimd",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "highway"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c706f1711006204c2ba8fb1a7bd55f689bbf7feca9ff40325206b5e140cff6df"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hmac"
|
name = "hmac"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ rust-version.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
backon.workspace = true
|
backon.workspace = true
|
||||||
|
blake2 = "0.10.6"
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
common.workspace = true
|
common.workspace = true
|
||||||
glob = "0.3.1"
|
glob = "0.3.1"
|
||||||
@@ -23,6 +24,7 @@ serde_json.workspace = true
|
|||||||
tracing-error.workspace = true
|
tracing-error.workspace = true
|
||||||
s3s.workspace = true
|
s3s.workspace = true
|
||||||
http.workspace = true
|
http.workspace = true
|
||||||
|
highway = "1.2.0"
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
|
uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] }
|
||||||
reed-solomon-erasure = { version = "6.0.0", features = ["simd-accel"] }
|
reed-solomon-erasure = { version = "6.0.0", features = ["simd-accel"] }
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use blake2::{Blake2b, Blake2b512};
|
||||||
|
use highway::{HighwayHash, HighwayHasher, Key};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
disk::DiskStore,
|
||||||
|
erasure::{ReadAt, Write},
|
||||||
|
error::Result,
|
||||||
|
store_api::BitrotAlgorithm,
|
||||||
|
};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref BITROT_ALGORITHMS: HashMap<BitrotAlgorithm, &'static str> = {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert(BitrotAlgorithm::SHA256, "sha256");
|
||||||
|
m.insert(BitrotAlgorithm::BLAKE2b512, "blake2b");
|
||||||
|
m.insert(BitrotAlgorithm::HighwayHash256, "highwayhash256");
|
||||||
|
m.insert(BitrotAlgorithm::HighwayHash256S, "highwayhash256S");
|
||||||
|
m
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// const MAGIC_HIGHWAY_HASH256_KEY: &[u8] = &[
|
||||||
|
// 0x4b, 0xe7, 0x34, 0xfa, 0x8e, 0x23, 0x8a, 0xcd, 0x26, 0x3e, 0x83, 0xe6, 0xbb, 0x96, 0x85, 0x52, 0x04, 0x0f, 0x93, 0x5d, 0xa3,
|
||||||
|
// 0x9f, 0x44, 0x14, 0x97, 0xe0, 0x9d, 0x13, 0x22, 0xde, 0x36, 0xa0,
|
||||||
|
// ];
|
||||||
|
const MAGIC_HIGHWAY_HASH256_KEY: &[u64; 4] = &[3, 4, 2, 1];
|
||||||
|
|
||||||
|
pub enum Hasher {
|
||||||
|
SHA256(Sha256),
|
||||||
|
HighwayHash256(HighwayHasher),
|
||||||
|
BLAKE2b512(Blake2b512),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hasher {
|
||||||
|
pub fn update(&mut self, data: impl AsRef<[u8]>) {
|
||||||
|
match self {
|
||||||
|
Hasher::SHA256(core_wrapper) => {
|
||||||
|
core_wrapper.update(data);
|
||||||
|
}
|
||||||
|
Hasher::HighwayHash256(highway_hasher) => {
|
||||||
|
highway_hasher.append(data.as_ref());
|
||||||
|
}
|
||||||
|
Hasher::BLAKE2b512(core_wrapper) => {
|
||||||
|
core_wrapper.update(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finalize(self) -> Vec<u8> {
|
||||||
|
match self {
|
||||||
|
Hasher::SHA256(core_wrapper) => core_wrapper.finalize().to_vec(),
|
||||||
|
Hasher::HighwayHash256(highway_hasher) => highway_hasher
|
||||||
|
.finalize256()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|&n| n.to_le_bytes()) // 使用小端字节序转换
|
||||||
|
.collect(),
|
||||||
|
Hasher::BLAKE2b512(core_wrapper) => core_wrapper.finalize().to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitrotAlgorithm {
|
||||||
|
pub fn new(&self) -> Hasher {
|
||||||
|
match self {
|
||||||
|
BitrotAlgorithm::SHA256 => Hasher::SHA256(Sha256::new()),
|
||||||
|
BitrotAlgorithm::HighwayHash256 | BitrotAlgorithm::HighwayHash256S => {
|
||||||
|
let key = Key(*MAGIC_HIGHWAY_HASH256_KEY);
|
||||||
|
Hasher::HighwayHash256(HighwayHasher::new(key))
|
||||||
|
}
|
||||||
|
BitrotAlgorithm::BLAKE2b512 => Hasher::BLAKE2b512(Blake2b512::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn available(&self) -> bool {
|
||||||
|
BITROT_ALGORITHMS.get(self).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn string(&self) -> String {
|
||||||
|
BITROT_ALGORITHMS.get(self).map_or("".to_string(), |s| s.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BitrotVerifier {
|
||||||
|
algorithm: BitrotAlgorithm,
|
||||||
|
sum: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitrotVerifier {
|
||||||
|
pub fn new(algorithm: BitrotAlgorithm, checksum: &[u8]) -> BitrotVerifier {
|
||||||
|
BitrotVerifier {
|
||||||
|
algorithm,
|
||||||
|
sum: checksum.to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bitrot_algorithm_from_string(s: &str) -> BitrotAlgorithm {
|
||||||
|
for (k, v) in BITROT_ALGORITHMS.iter() {
|
||||||
|
if *v == s {
|
||||||
|
return k.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BitrotAlgorithm::HighwayHash256S
|
||||||
|
}
|
||||||
|
|
||||||
|
type BitrotWriter = Box<dyn Write>;
|
||||||
|
|
||||||
|
pub fn new_bitrot_writer(
|
||||||
|
disk: DiskStore,
|
||||||
|
orig_volume: &str,
|
||||||
|
volume: &str,
|
||||||
|
file_path: &str,
|
||||||
|
length: usize,
|
||||||
|
algo: BitrotAlgorithm,
|
||||||
|
shard_size: usize,
|
||||||
|
) -> BitrotWriter {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WholeBitrotWriter {
|
||||||
|
disk: DiskStore,
|
||||||
|
volume: String,
|
||||||
|
file_path: String,
|
||||||
|
shard_size: usize,
|
||||||
|
hash: Hasher,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WholeBitrotWriter {
|
||||||
|
pub fn new(disk: DiskStore, volume: &str, file_path: &str, algo: BitrotAlgorithm, shard_size: usize) -> Self {
|
||||||
|
WholeBitrotWriter {
|
||||||
|
disk,
|
||||||
|
volume: volume.to_string(),
|
||||||
|
file_path: file_path.to_string(),
|
||||||
|
shard_size,
|
||||||
|
hash: algo.new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl Write for WholeBitrotWriter {
|
||||||
|
async fn write(&mut self, buf: &[u8]) -> Result<()> {
|
||||||
|
let mut file = self.disk.append_file(&self.volume, &self.file_path).await?;
|
||||||
|
let _ = file.write(buf).await?;
|
||||||
|
self.hash.update(buf);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WholeBitrotReader {
|
||||||
|
disk: DiskStore,
|
||||||
|
volume: String,
|
||||||
|
file_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl ReadAt for WholeBitrotReader {
|
||||||
|
async fn read_at(&mut self, offset: usize, length: usize) -> Result<(Vec<u8>, usize)> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
-11
@@ -2,9 +2,9 @@ use super::error::{is_sys_err_io, is_sys_err_not_empty, is_sys_err_too_many_file
|
|||||||
use super::os::is_root_disk;
|
use super::os::is_root_disk;
|
||||||
use super::{endpoint::Endpoint, error::DiskError, format::FormatV3};
|
use super::{endpoint::Endpoint, error::DiskError, format::FormatV3};
|
||||||
use super::{
|
use super::{
|
||||||
os, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskMetrics, FileInfoVersions, FileReader, FileWriter,
|
os, CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskMetrics, FileInfoVersions,
|
||||||
Info, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, RenameDataResp, UpdateMetadataOpts, VolumeInfo,
|
FileReader, FileWriter, Info, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, RenameDataResp,
|
||||||
WalkDirOptions,
|
UpdateMetadataOpts, VolumeInfo, WalkDirOptions,
|
||||||
};
|
};
|
||||||
use crate::cache_value::cache::{Cache, Opts};
|
use crate::cache_value::cache::{Cache, Opts};
|
||||||
use crate::disk::error::{
|
use crate::disk::error::{
|
||||||
@@ -15,16 +15,16 @@ use crate::disk::os::check_path_length;
|
|||||||
use crate::disk::{LocalFileReader, LocalFileWriter, STORAGE_FORMAT_FILE};
|
use crate::disk::{LocalFileReader, LocalFileWriter, STORAGE_FORMAT_FILE};
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::global::{GLOBAL_IsErasureSD, GLOBAL_RootDiskThreshold};
|
use crate::global::{GLOBAL_IsErasureSD, GLOBAL_RootDiskThreshold};
|
||||||
|
use crate::store_api::BitrotAlgorithm;
|
||||||
use crate::utils::fs::{lstat, O_APPEND, O_CREATE, O_RDONLY, O_WRONLY};
|
use crate::utils::fs::{lstat, O_APPEND, O_CREATE, O_RDONLY, O_WRONLY};
|
||||||
use crate::utils::path::{clean, has_suffix, SLASH_SEPARATOR};
|
|
||||||
use crate::utils::os::get_info;
|
use crate::utils::os::get_info;
|
||||||
|
use crate::utils::path::{clean, has_suffix, SLASH_SEPARATOR};
|
||||||
use crate::{
|
use crate::{
|
||||||
file_meta::FileMeta,
|
file_meta::FileMeta,
|
||||||
store_api::{FileInfo, RawFileInfo},
|
store_api::{FileInfo, RawFileInfo},
|
||||||
utils,
|
utils,
|
||||||
};
|
};
|
||||||
use path_absolutize::Absolutize;
|
use path_absolutize::Absolutize;
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -36,6 +36,7 @@ use std::{
|
|||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::fs::{self, File};
|
use tokio::fs::{self, File};
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt, ErrorKind};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt, ErrorKind};
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@@ -149,19 +150,17 @@ impl LocalDisk {
|
|||||||
if root {
|
if root {
|
||||||
return Err(Error::new(DiskError::DriveIsRoot));
|
return Err(Error::new(DiskError::DriveIsRoot));
|
||||||
}
|
}
|
||||||
|
|
||||||
// disk_info.healing =
|
// disk_info.healing =
|
||||||
Ok(disk_info)
|
Ok(disk_info)
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
Err(err)
|
|
||||||
}
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let cache = Cache::new(Box::new(update_fn), Duration::from_secs(1), Opts::default());
|
let cache = Cache::new(Box::new(update_fn), Duration::from_secs(1), Opts::default());
|
||||||
|
|
||||||
// TODO: DIRECT suport
|
// TODO: DIRECT suport
|
||||||
// TODD: DiskInfo
|
// TODD: DiskInfo
|
||||||
let mut disk = Self {
|
let mut disk = Self {
|
||||||
@@ -650,6 +649,22 @@ impl LocalDisk {
|
|||||||
fn get_metrics(&self) -> DiskMetrics {
|
fn get_metrics(&self) -> DiskMetrics {
|
||||||
DiskMetrics::default()
|
DiskMetrics::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn bitrot_verify(
|
||||||
|
&self,
|
||||||
|
part_path: &PathBuf,
|
||||||
|
part_size: u64,
|
||||||
|
algo: BitrotAlgorithm,
|
||||||
|
sum: &[u8],
|
||||||
|
shard_size: u64,
|
||||||
|
) -> Result<()> {
|
||||||
|
let file = utils::fs::open_file(part_path, O_CREATE | O_WRONLY)
|
||||||
|
.await
|
||||||
|
.map_err(os_err_to_file_err)?;
|
||||||
|
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_root_path(path: impl AsRef<Path>) -> bool {
|
fn is_root_path(path: impl AsRef<Path>) -> bool {
|
||||||
@@ -846,6 +861,30 @@ impl DiskAPI for LocalDisk {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify_file(&self, volume: &str, path: &str, fi: FileInfo) -> Result<CheckPartsResp> {
|
||||||
|
let volume_dir = self.get_bucket_path(volume)?;
|
||||||
|
if !skip_access_checks(volume) {
|
||||||
|
if let Err(e) = utils::fs::access(&volume_dir).await {
|
||||||
|
return Err(convert_access_error(e, DiskError::VolumeAccessDenied));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut resp = CheckPartsResp {
|
||||||
|
results: Vec::with_capacity(fi.parts.len()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let erasure = fi.erasure;
|
||||||
|
fi.parts.iter().enumerate().for_each(|(i, part)| {
|
||||||
|
let checksum_info = erasure.get_checksum_info(part.number);
|
||||||
|
let part_path = Path::new(&volume_dir)
|
||||||
|
.join(path)
|
||||||
|
.join(fi.data_dir.map_or("".to_string(), |dir| dir.to_string()))
|
||||||
|
.join(format!("part.{}", part.number));
|
||||||
|
|
||||||
|
self.bi
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async fn rename_part(&self, src_volume: &str, src_path: &str, dst_volume: &str, dst_path: &str, meta: Vec<u8>) -> Result<()> {
|
async fn rename_part(&self, src_volume: &str, src_path: &str, dst_volume: &str, dst_path: &str, meta: Vec<u8>) -> Result<()> {
|
||||||
let src_volume_dir = self.get_bucket_path(src_volume)?;
|
let src_volume_dir = self.get_bucket_path(src_volume)?;
|
||||||
let dst_volume_dir = self.get_bucket_path(dst_volume)?;
|
let dst_volume_dir = self.get_bucket_path(dst_volume)?;
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ pub trait DiskAPI: Debug + Send + Sync + 'static {
|
|||||||
// CheckParts
|
// CheckParts
|
||||||
async fn delete(&self, volume: &str, path: &str, opt: DeleteOptions) -> Result<()>;
|
async fn delete(&self, volume: &str, path: &str, opt: DeleteOptions) -> Result<()>;
|
||||||
// VerifyFile
|
// VerifyFile
|
||||||
|
async fn verify_file(&self, volume: &str, path: &str, fi: FileInfo) -> Result<CheckPartsResp>;
|
||||||
// StatInfoFile
|
// StatInfoFile
|
||||||
// ReadParts
|
// ReadParts
|
||||||
async fn read_multiple(&self, req: ReadMultipleReq) -> Result<Vec<ReadMultipleResp>>;
|
async fn read_multiple(&self, req: ReadMultipleReq) -> Result<Vec<ReadMultipleResp>>;
|
||||||
@@ -136,6 +137,10 @@ pub trait DiskAPI: Debug + Send + Sync + 'static {
|
|||||||
async fn disk_info(&self, opts: &DiskInfoOptions) -> Result<DiskInfo>;
|
async fn disk_info(&self, opts: &DiskInfoOptions) -> Result<DiskInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct CheckPartsResp {
|
||||||
|
pub results: Vec<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct UpdateMetadataOpts {
|
pub struct UpdateMetadataOpts {
|
||||||
pub no_persistence: bool,
|
pub no_persistence: bool,
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ use tracing::info;
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
endpoint::Endpoint, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskOption, FileInfoVersions,
|
endpoint::Endpoint, CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskOption, FileInfoVersions, FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, RemoteFileReader, RemoteFileWriter, RenameDataResp, UpdateMetadataOpts, VolumeInfo, WalkDirOptions
|
||||||
FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, RemoteFileReader, RemoteFileWriter,
|
|
||||||
RenameDataResp, UpdateMetadataOpts, VolumeInfo, WalkDirOptions,
|
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
disk::error::DiskError,
|
disk::error::DiskError,
|
||||||
@@ -163,6 +161,11 @@ impl DiskAPI for RemoteDisk {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify_file(&self, volume: &str, path: &str, fi: FileInfo) -> Result<CheckPartsResp> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
async fn rename_part(&self, src_volume: &str, src_path: &str, dst_volume: &str, dst_path: &str, meta: Vec<u8>) -> Result<()> {
|
async fn rename_part(&self, src_volume: &str, src_path: &str, dst_volume: &str, dst_path: &str, meta: Vec<u8>) -> Result<()> {
|
||||||
info!("rename_part");
|
info!("rename_part");
|
||||||
let mut client = node_service_time_out_client(&self.addr)
|
let mut client = node_service_time_out_client(&self.addr)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod bitrot;
|
||||||
pub mod cache_value;
|
pub mod cache_value;
|
||||||
mod chunk_stream;
|
mod chunk_stream;
|
||||||
mod config;
|
mod config;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use http::HeaderMap;
|
|||||||
use rmp_serde::Serializer;
|
use rmp_serde::Serializer;
|
||||||
use s3s::dto::StreamingBlob;
|
use s3s::dto::StreamingBlob;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sha2::Sha256;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -240,6 +241,18 @@ pub struct ErasureInfo {
|
|||||||
pub checksums: Vec<ChecksumInfo>,
|
pub checksums: Vec<ChecksumInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ErasureInfo {
|
||||||
|
pub fn get_checksum_info(&self, part_number: usize) -> ChecksumInfo {
|
||||||
|
for sum in &self.checksums {
|
||||||
|
if sum.part_number == part_number {
|
||||||
|
return sum.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChecksumInfo {algorithm: BitrotAlgorithm::HighwayHash256S, ..Default::default()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Default, Clone)]
|
||||||
// ChecksumInfo - carries checksums of individual scattered parts per disk.
|
// ChecksumInfo - carries checksums of individual scattered parts per disk.
|
||||||
pub struct ChecksumInfo {
|
pub struct ChecksumInfo {
|
||||||
@@ -248,7 +261,7 @@ pub struct ChecksumInfo {
|
|||||||
pub hash: Vec<u8>,
|
pub hash: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Default, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Default, Clone, Eq, Hash)]
|
||||||
// BitrotAlgorithm specifies a algorithm used for bitrot protection.
|
// BitrotAlgorithm specifies a algorithm used for bitrot protection.
|
||||||
pub enum BitrotAlgorithm {
|
pub enum BitrotAlgorithm {
|
||||||
// SHA256 represents the SHA-256 hash function
|
// SHA256 represents the SHA-256 hash function
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
const GLOBAL_DIR_SUFFIX: &str = "__XLDIR__";
|
const GLOBAL_DIR_SUFFIX: &str = "__XLDIR__";
|
||||||
|
|
||||||
pub const SLASH_SEPARATOR: &str = "/";
|
pub const SLASH_SEPARATOR: &str = "/";
|
||||||
@@ -50,6 +52,16 @@ pub fn has_profix(s: &str, prefix: &str) -> bool {
|
|||||||
s.starts_with(prefix)
|
s.starts_with(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn path_join(elem: &[PathBuf]) -> PathBuf {
|
||||||
|
let mut joined_path = PathBuf::new();
|
||||||
|
|
||||||
|
for path in elem {
|
||||||
|
joined_path.push(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
joined_path
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LazyBuf {
|
pub struct LazyBuf {
|
||||||
s: String,
|
s: String,
|
||||||
buf: Option<Vec<u8>>,
|
buf: Option<Vec<u8>>,
|
||||||
|
|||||||
Reference in New Issue
Block a user