mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
fix: 优化endpoint new的逻辑
This commit is contained in:
Generated
+7
@@ -319,6 +319,7 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"netif",
|
"netif",
|
||||||
"path-absolutize",
|
"path-absolutize",
|
||||||
|
"path-clean",
|
||||||
"reed-solomon-erasure",
|
"reed-solomon-erasure",
|
||||||
"regex",
|
"regex",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
@@ -882,6 +883,12 @@ dependencies = [
|
|||||||
"path-dedot",
|
"path-dedot",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "path-clean"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "path-dedot"
|
name = "path-dedot"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ tokio-util = { version = "0.7.11", features = ["io"] }
|
|||||||
s3s = "0.10.0"
|
s3s = "0.10.0"
|
||||||
crc32fast = "1.4.2"
|
crc32fast = "1.4.2"
|
||||||
siphasher = "1.0.1"
|
siphasher = "1.0.1"
|
||||||
|
path-clean = "1.0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||||
|
|||||||
@@ -283,11 +283,11 @@ fn possible_set_counts_with_symmetry(set_counts: &[usize], arg_patterns: &[ArgPa
|
|||||||
for &ss in set_counts {
|
for &ss in set_counts {
|
||||||
let mut symmetry = false;
|
let mut symmetry = false;
|
||||||
for arg_pattern in arg_patterns {
|
for arg_pattern in arg_patterns {
|
||||||
for p in arg_pattern.inner.iter() {
|
for p in arg_pattern.as_ref().iter() {
|
||||||
if p.seq.len() > ss {
|
if p.len() > ss {
|
||||||
symmetry = (p.seq.len() % ss) == 0;
|
symmetry = (p.len() % ss) == 0;
|
||||||
} else {
|
} else {
|
||||||
symmetry = (ss % p.seq.len()) == 0;
|
symmetry = (ss % p.len()) == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,6 +520,13 @@ mod test {
|
|||||||
]],
|
]],
|
||||||
success: true,
|
success: true,
|
||||||
},
|
},
|
||||||
|
TestCase {
|
||||||
|
num: 15,
|
||||||
|
args: vec!["https://node{1...3}.example.net/mnt/drive{1...8}"],
|
||||||
|
total_sizes: vec![24],
|
||||||
|
indexes: vec![vec![12, 12]],
|
||||||
|
success: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for test_case in test_cases {
|
for test_case in test_cases {
|
||||||
|
|||||||
+20
-4
@@ -16,9 +16,9 @@ const ELLIPSES: &str = "...";
|
|||||||
/// associated prefix and suffixes.
|
/// associated prefix and suffixes.
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct Pattern {
|
pub struct Pattern {
|
||||||
pub prefix: String,
|
pub(crate) prefix: String,
|
||||||
pub suffix: String,
|
pub(crate) suffix: String,
|
||||||
pub seq: Vec<String>,
|
pub(crate) seq: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pattern {
|
impl Pattern {
|
||||||
@@ -37,12 +37,28 @@ impl Pattern {
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.seq.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// contains a list of patterns provided in the input.
|
/// contains a list of patterns provided in the input.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ArgPattern {
|
pub struct ArgPattern {
|
||||||
pub inner: Vec<Pattern>,
|
inner: Vec<Pattern>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<Vec<Pattern>> for ArgPattern {
|
||||||
|
fn as_ref(&self) -> &Vec<Pattern> {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsMut<Vec<Pattern>> for ArgPattern {
|
||||||
|
fn as_mut(&mut self) -> &mut Vec<Pattern> {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgPattern {
|
impl ArgPattern {
|
||||||
|
|||||||
+34
-26
@@ -2,6 +2,7 @@ use super::disks_layout::DisksLayout;
|
|||||||
use super::error::{Error, Result};
|
use super::error::{Error, Result};
|
||||||
use super::utils::net;
|
use super::utils::net;
|
||||||
use path_absolutize::Absolutize;
|
use path_absolutize::Absolutize;
|
||||||
|
use path_clean::PathClean;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::{collections::HashMap, path::Path, usize};
|
use std::{collections::HashMap, path::Path, usize};
|
||||||
@@ -70,20 +71,18 @@ impl TryFrom<&str> for Endpoint {
|
|||||||
/// Performs the conversion.
|
/// Performs the conversion.
|
||||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
/// check whether given path is not empty.
|
/// check whether given path is not empty.
|
||||||
fn is_empty_path(path: &str) -> bool {
|
fn is_empty_path(path: impl AsRef<Path>) -> bool {
|
||||||
["", "/", "\\"].iter().any(|&v| v.eq(path))
|
["", "/", "\\"].iter().any(|&v| Path::new(v).eq(path.as_ref()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_empty_path(value) {
|
if is_empty_path(value) {
|
||||||
return Err(Error::from_string("empty or root endpoint is not supported"));
|
return Err(Error::from_string("empty or root endpoint is not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO What if the value passed in is something like d:\data\rustfs
|
|
||||||
|
|
||||||
let mut is_local = false;
|
let mut is_local = false;
|
||||||
let url = match Url::parse(value) {
|
let url = match Url::parse(value) {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
Ok(mut url) => {
|
Ok(mut url) if url.has_host() => {
|
||||||
// URL style of endpoint.
|
// URL style of endpoint.
|
||||||
// Valid URL style endpoint is
|
// Valid URL style endpoint is
|
||||||
// - Scheme field must contain "http" or "https"
|
// - Scheme field must contain "http" or "https"
|
||||||
@@ -96,7 +95,7 @@ impl TryFrom<&str> for Endpoint {
|
|||||||
return Err(Error::from_string("invalid URL endpoint format"));
|
return Err(Error::from_string("invalid URL endpoint format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_empty_path(url.path()) {
|
if is_empty_path(Path::new(url.path()).clean()) {
|
||||||
return Err(Error::from_string("empty or root endpoint is not supported"));
|
return Err(Error::from_string("empty or root endpoint is not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,31 +123,20 @@ impl TryFrom<&str> for Endpoint {
|
|||||||
|
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
|
Ok(_) => {
|
||||||
|
// like d:/foo
|
||||||
|
is_local = true;
|
||||||
|
url_parse_from_file_path(value)?
|
||||||
|
}
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
ParseError::InvalidPort => {
|
ParseError::InvalidPort => {
|
||||||
return Err(Error::from_string("invalid URL endpoint format: port number must be between 1 to 65535"))
|
return Err(Error::from_string("invalid URL endpoint format: port number must be between 1 to 65535"))
|
||||||
}
|
}
|
||||||
ParseError::EmptyHost => return Err(Error::from_string("invalid URL endpoint format: empty host name")),
|
ParseError::EmptyHost => return Err(Error::from_string("invalid URL endpoint format: empty host name")),
|
||||||
ParseError::RelativeUrlWithoutBase => {
|
ParseError::RelativeUrlWithoutBase => {
|
||||||
// Only check if the arg is an ip address and ask for scheme since its absent.
|
// like /foo
|
||||||
// localhost, example.com, any FQDN cannot be disambiguated from a regular file path such as
|
is_local = true;
|
||||||
// /mnt/export1. So we go ahead and start the rustfs server in FS modes in these cases.
|
url_parse_from_file_path(value)?
|
||||||
if net::is_socket_addr(value) {
|
|
||||||
return Err(Error::from_string("invalid URL endpoint format: missing scheme http or https"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let file_path = match Path::new(value).absolutize() {
|
|
||||||
Ok(path) => path,
|
|
||||||
Err(err) => return Err(Error::from_string(format!("absolute path failed: {}", err))),
|
|
||||||
};
|
|
||||||
|
|
||||||
match Url::from_file_path(file_path) {
|
|
||||||
Ok(url) => {
|
|
||||||
is_local = true;
|
|
||||||
url
|
|
||||||
}
|
|
||||||
Err(_) => return Err(Error::from_string("Convert a file path into an URL failed")),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => return Err(Error::from_string(format!("invalid URL endpoint format: {}", e))),
|
_ => return Err(Error::from_string(format!("invalid URL endpoint format: {}", e))),
|
||||||
},
|
},
|
||||||
@@ -503,6 +491,26 @@ impl EndpointServerPools {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// parse a file path into an URL.
|
||||||
|
fn url_parse_from_file_path(value: &str) -> Result<url::Url> {
|
||||||
|
// Only check if the arg is an ip address and ask for scheme since its absent.
|
||||||
|
// localhost, example.com, any FQDN cannot be disambiguated from a regular file path such as
|
||||||
|
// /mnt/export1. So we go ahead and start the rustfs server in FS modes in these cases.
|
||||||
|
if net::is_socket_addr(value) {
|
||||||
|
return Err(Error::from_string("invalid URL endpoint format: missing scheme http or https"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_path = match Path::new(value).absolutize() {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(err) => return Err(Error::from_string(format!("absolute path failed: {}", err))),
|
||||||
|
};
|
||||||
|
|
||||||
|
match Url::from_file_path(file_path) {
|
||||||
|
Ok(url) => Ok(url),
|
||||||
|
Err(_) => return Err(Error::from_string("Convert a file path into an URL failed")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -519,7 +527,7 @@ mod test {
|
|||||||
|
|
||||||
let u2 = url::Url::parse("https://example.org/path").unwrap();
|
let u2 = url::Url::parse("https://example.org/path").unwrap();
|
||||||
let u4 = url::Url::parse("http://192.168.253.200/path").unwrap();
|
let u4 = url::Url::parse("http://192.168.253.200/path").unwrap();
|
||||||
let root_slash_foo = url::Url::from_file_path("d:/foo").unwrap();
|
let root_slash_foo = url::Url::from_file_path("/foo").unwrap();
|
||||||
|
|
||||||
let test_cases = [
|
let test_cases = [
|
||||||
TestCase {
|
TestCase {
|
||||||
|
|||||||
Reference in New Issue
Block a user