Merge branch 'erasure' of github.com:rustfs/s3-rustfs into erasure

This commit is contained in:
weisd
2024-07-03 17:47:39 +08:00
2 changed files with 34 additions and 19 deletions
+27 -12
View File
@@ -1,5 +1,5 @@
use super::ellipses::*; use super::ellipses::*;
use anyhow::{Error, Result}; use super::error::{Error, Result};
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashSet; use std::collections::HashSet;
@@ -33,7 +33,7 @@ impl<T: AsRef<str>> TryFrom<&[T]> for DisksLayout {
fn try_from(args: &[T]) -> Result<Self, Self::Error> { fn try_from(args: &[T]) -> Result<Self, Self::Error> {
if args.is_empty() { if args.is_empty() {
return Err(Error::msg("Invalid argument")); return Err(Error::from_string("Invalid argument"));
} }
let is_ellipses = args.iter().any(|v| has_ellipses(&[v])); let is_ellipses = args.iter().any(|v| has_ellipses(&[v]));
@@ -54,7 +54,9 @@ impl<T: AsRef<str>> TryFrom<&[T]> for DisksLayout {
let mut layout = Vec::with_capacity(args.len()); let mut layout = Vec::with_capacity(args.len());
for arg in args.iter() { for arg in args.iter() {
if !has_ellipses(&[arg]) && args.len() > 1 { if !has_ellipses(&[arg]) && args.len() > 1 {
return Err(Error::msg("all args must have ellipses for pool expansion (Invalid arguments specified)")); return Err(Error::from_string(
"all args must have ellipses for pool expansion (Invalid arguments specified)",
));
} }
let set_args = get_all_sets(is_ellipses, &[arg])?; let set_args = get_all_sets(is_ellipses, &[arg])?;
@@ -69,6 +71,19 @@ impl<T: AsRef<str>> TryFrom<&[T]> for DisksLayout {
} }
} }
impl DisksLayout {
pub fn is_empty_layout(&self) -> bool {
self.pools.is_empty()
|| self.pools[0].layout.is_empty()
|| self.pools[0].layout[0].is_empty()
|| self.pools[0].layout[0][0].is_empty()
}
pub fn is_single_drive_layout(&self) -> bool {
self.pools.len() == 1 && self.pools[0].layout.len() == 1 && self.pools[0].layout[0].len() == 1
}
}
/// parses all ellipses input arguments, expands them into /// parses all ellipses input arguments, expands them into
/// corresponding list of endpoints chunked evenly in accordance with a /// corresponding list of endpoints chunked evenly in accordance with a
/// specific set size. /// specific set size.
@@ -95,7 +110,7 @@ fn get_all_sets<T: AsRef<str>>(is_ellipses: bool, args: &[T]) -> Result<Vec<Vec<
for args in set_args.iter() { for args in set_args.iter() {
for arg in args { for arg in args {
if unique_args.contains(arg) { if unique_args.contains(arg) {
return Err(Error::msg(format!("Input args {} has duplicate ellipses", arg))); return Err(Error::from_string(format!("Input args {} has duplicate ellipses", arg)));
} }
unique_args.insert(arg); unique_args.insert(arg);
} }
@@ -254,20 +269,20 @@ fn possible_set_counts_with_symmetry(set_counts: &[usize], arg_patterns: &[ArgPa
/// indexes (total sets) /// indexes (total sets)
fn get_set_indexes<T: AsRef<str>>(args: &[T], total_sizes: &[usize], arg_patterns: &[ArgPattern]) -> Result<Vec<Vec<usize>>> { fn get_set_indexes<T: AsRef<str>>(args: &[T], total_sizes: &[usize], arg_patterns: &[ArgPattern]) -> Result<Vec<Vec<usize>>> {
if args.is_empty() || total_sizes.is_empty() { if args.is_empty() || total_sizes.is_empty() {
return Err(Error::msg("Invalid argument")); return Err(Error::from_string("Invalid argument"));
} }
for &size in total_sizes { for &size in total_sizes {
// Check if total_sizes has minimum range upto set_size // Check if total_sizes has minimum range upto set_size
if size < SET_SIZES[0] { if size < SET_SIZES[0] {
return Err(Error::msg(format!("Incorrect number of endpoints provided, size {}", size))); return Err(Error::from_string(format!("Incorrect number of endpoints provided, size {}", size)));
} }
} }
let common_size = get_divisible_size(total_sizes); let common_size = get_divisible_size(total_sizes);
let mut set_counts = possible_set_counts(common_size); let mut set_counts = possible_set_counts(common_size);
if set_counts.is_empty() { if set_counts.is_empty() {
return Err(Error::msg(format!( return Err(Error::from_string(format!(
"Incorrect number of endpoints provided, number of drives {} is not divisible by any supported erasure set sizes {}", "Incorrect number of endpoints provided, number of drives {} is not divisible by any supported erasure set sizes {}",
common_size, 0 common_size, 0
))); )));
@@ -278,13 +293,13 @@ fn get_set_indexes<T: AsRef<str>>(args: &[T], total_sizes: &[usize], arg_pattern
// Returns possible set counts with symmetry. // Returns possible set counts with symmetry.
set_counts = possible_set_counts_with_symmetry(&set_counts, arg_patterns); set_counts = possible_set_counts_with_symmetry(&set_counts, arg_patterns);
if set_counts.is_empty() { if set_counts.is_empty() {
return Err(Error::msg("No symmetric distribution detected with input endpoints provided")); return Err(Error::from_string("No symmetric distribution detected with input endpoints provided"));
} }
// Final set size with all the symmetry accounted for. // Final set size with all the symmetry accounted for.
let set_size = common_set_drive_count(common_size, &set_counts); let set_size = common_set_drive_count(common_size, &set_counts);
if !is_valid_set_size(set_size) { if !is_valid_set_size(set_size) {
return Err(Error::msg("Incorrect number of endpoints provided3")); return Err(Error::from_string("Incorrect number of endpoints provided3"));
} }
Ok(total_sizes Ok(total_sizes
@@ -475,7 +490,7 @@ mod test {
arg_patterns.push(patterns); arg_patterns.push(patterns);
} }
Err(err) => { Err(err) => {
panic!("Test{}: Unexpected failure {}", test_case.num, err); panic!("Test{}: Unexpected failure {:?}", test_case.num, err);
} }
} }
} }
@@ -494,7 +509,7 @@ mod test {
} }
Err(err) => { Err(err) => {
if test_case.success { if test_case.success {
panic!("Test{}: Expected success but failed instead {}", test_case.num, err); panic!("Test{}: Expected success but failed instead {:?}", test_case.num, err);
} }
} }
} }
@@ -754,7 +769,7 @@ mod test {
} }
Err(err) => { Err(err) => {
if test_case.success { if test_case.success {
panic!("Test{}: Expected success but failed instead {}", test_case.num, err); panic!("Test{}: Expected success but failed instead {:?}", test_case.num, err);
} }
} }
} }
+7 -7
View File
@@ -1,6 +1,6 @@
use lazy_static::*; use lazy_static::*;
use anyhow::{Error, Result}; use super::error::{Error, Result};
use regex::Regex; use regex::Regex;
lazy_static! { lazy_static! {
@@ -88,7 +88,7 @@ pub fn find_ellipses_patterns(arg: &str) -> Result<ArgPattern> {
let mut parts = match ELLIPSES_RE.captures(arg) { let mut parts = match ELLIPSES_RE.captures(arg) {
Some(caps) => caps, Some(caps) => caps,
None => { None => {
return Err(Error::msg(format!("Invalid ellipsis format in ({}), Ellipsis range must be provided in format {{N...M}} where N and M are positive integers, M must be greater than N, with an allowed minimum range of 4", arg))); return Err(Error::from_string(format!("Invalid ellipsis format in ({}), Ellipsis range must be provided in format {{N...M}} where N and M are positive integers, M must be greater than N, with an allowed minimum range of 4", arg)));
} }
}; };
@@ -125,7 +125,7 @@ pub fn find_ellipses_patterns(arg: &str) -> Result<ArgPattern> {
|| p.suffix.contains(OPEN_BRACES) || p.suffix.contains(OPEN_BRACES)
|| p.suffix.contains(CLOSE_BRACES) || p.suffix.contains(CLOSE_BRACES)
{ {
return Err(Error::msg(format!("Invalid ellipsis format in ({}), Ellipsis range must be provided in format {{N...M}} where N and M are positive integers, M must be greater than N, with an allowed minimum range of 4", arg))); return Err(Error::from_string(format!("Invalid ellipsis format in ({}), Ellipsis range must be provided in format {{N...M}} where N and M are positive integers, M must be greater than N, with an allowed minimum range of 4", arg)));
} }
} }
@@ -146,10 +146,10 @@ pub fn has_ellipses<T: AsRef<str>>(s: &[T]) -> bool {
/// {33...64} /// {33...64}
pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> { pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> {
if !pattern.contains(OPEN_BRACES) { if !pattern.contains(OPEN_BRACES) {
return Err(Error::msg("Invalid argument")); return Err(Error::from_string("Invalid argument"));
} }
if !pattern.contains(OPEN_BRACES) { if !pattern.contains(OPEN_BRACES) {
return Err(Error::msg("Invalid argument")); return Err(Error::from_string("Invalid argument"));
} }
let ellipses_range: Vec<&str> = pattern let ellipses_range: Vec<&str> = pattern
@@ -159,7 +159,7 @@ pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> {
.collect(); .collect();
if ellipses_range.len() != 2 { if ellipses_range.len() != 2 {
return Err(Error::msg("Invalid argument")); return Err(Error::from_string("Invalid argument"));
} }
// TODO: Add support for hexadecimals. // TODO: Add support for hexadecimals.
@@ -167,7 +167,7 @@ pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> {
let end = ellipses_range[1].parse::<usize>()?; let end = ellipses_range[1].parse::<usize>()?;
if start > end { if start > end {
return Err(Error::msg("Invalid argument:range start cannot be bigger than end")); return Err(Error::from_string("Invalid argument:range start cannot be bigger than end"));
} }
let mut ret: Vec<String> = Vec::with_capacity(end - start + 1); let mut ret: Vec<String> = Vec::with_capacity(end - start + 1);