mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-10 15:16:56 +00:00
mc test ok
This commit is contained in:
+719
-719
File diff suppressed because it is too large
Load Diff
@@ -34,13 +34,17 @@ impl BucketMetadataError {
|
||||
|
||||
impl From<BucketMetadataError> for Error {
|
||||
fn from(e: BucketMetadataError) -> Self {
|
||||
Error::other(e)
|
||||
match e {
|
||||
BucketMetadataError::BucketPolicyNotFound => Error::BucketPolicyNotFound,
|
||||
_ => Error::other(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for BucketMetadataError {
|
||||
fn from(e: Error) -> Self {
|
||||
match e {
|
||||
Error::BucketPolicyNotFound => BucketMetadataError::BucketPolicyNotFound,
|
||||
Error::Io(e) => e.into(),
|
||||
_ => BucketMetadataError::other(e),
|
||||
}
|
||||
|
||||
+17
-17
@@ -1,29 +1,29 @@
|
||||
use super::error::{Error, Result};
|
||||
use super::os::{is_root_disk, rename_all};
|
||||
use super::{endpoint::Endpoint, error::DiskError, format::FormatV3};
|
||||
use super::{
|
||||
os, CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskMetrics, FileInfoVersions, Info,
|
||||
ReadMultipleReq, ReadMultipleResp, ReadOptions, RenameDataResp, UpdateMetadataOpts, VolumeInfo, WalkDirOptions,
|
||||
BUCKET_META_PREFIX, RUSTFS_META_BUCKET, STORAGE_FORMAT_FILE_BACKUP,
|
||||
BUCKET_META_PREFIX, CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskLocation, DiskMetrics,
|
||||
FileInfoVersions, Info, RUSTFS_META_BUCKET, ReadMultipleReq, ReadMultipleResp, ReadOptions, RenameDataResp,
|
||||
STORAGE_FORMAT_FILE_BACKUP, UpdateMetadataOpts, VolumeInfo, WalkDirOptions, os,
|
||||
};
|
||||
use super::{endpoint::Endpoint, error::DiskError, format::FormatV3};
|
||||
|
||||
use crate::bucket::metadata_sys::{self};
|
||||
use crate::bucket::versioning::VersioningApi;
|
||||
use crate::bucket::versioning_sys::BucketVersioningSys;
|
||||
use crate::disk::STORAGE_FORMAT_FILE;
|
||||
use crate::disk::error::FileAccessDeniedWithContext;
|
||||
use crate::disk::error_conv::{to_access_error, to_file_error, to_unformatted_disk_error, to_volume_error};
|
||||
use crate::disk::fs::{
|
||||
access, lstat, lstat_std, remove, remove_all_std, remove_std, rename, O_APPEND, O_CREATE, O_RDONLY, O_TRUNC, O_WRONLY,
|
||||
O_APPEND, O_CREATE, O_RDONLY, O_TRUNC, O_WRONLY, access, lstat, lstat_std, remove, remove_all_std, remove_std, rename,
|
||||
};
|
||||
use crate::disk::os::{check_path_length, is_empty_dir};
|
||||
use crate::disk::STORAGE_FORMAT_FILE;
|
||||
use crate::disk::{
|
||||
conv_part_err_to_int, CHECK_PART_FILE_CORRUPT, CHECK_PART_FILE_NOT_FOUND, CHECK_PART_SUCCESS, CHECK_PART_UNKNOWN,
|
||||
CHECK_PART_VOLUME_NOT_FOUND,
|
||||
CHECK_PART_FILE_CORRUPT, CHECK_PART_FILE_NOT_FOUND, CHECK_PART_SUCCESS, CHECK_PART_UNKNOWN, CHECK_PART_VOLUME_NOT_FOUND,
|
||||
conv_part_err_to_int,
|
||||
};
|
||||
use crate::global::{GLOBAL_IsErasureSD, GLOBAL_RootDiskThreshold};
|
||||
use crate::heal::data_scanner::{
|
||||
lc_has_active_rules, rep_has_active_rules, scan_data_folder, ScannerItem, ShouldSleepFn, SizeSummary,
|
||||
ScannerItem, ShouldSleepFn, SizeSummary, lc_has_active_rules, rep_has_active_rules, scan_data_folder,
|
||||
};
|
||||
use crate::heal::data_scanner_metric::{ScannerMetric, ScannerMetrics};
|
||||
use crate::heal::data_usage_cache::{DataUsageCache, DataUsageEntry};
|
||||
@@ -35,23 +35,23 @@ use crate::new_object_layer_fn;
|
||||
use crate::store_api::{ObjectInfo, StorageAPI};
|
||||
use crate::utils::os::get_info;
|
||||
use crate::utils::path::{
|
||||
clean, decode_dir_object, encode_dir_object, has_suffix, path_join, path_join_buf, GLOBAL_DIR_SUFFIX,
|
||||
GLOBAL_DIR_SUFFIX_WITH_SLASH, SLASH_SEPARATOR,
|
||||
GLOBAL_DIR_SUFFIX, GLOBAL_DIR_SUFFIX_WITH_SLASH, SLASH_SEPARATOR, clean, decode_dir_object, encode_dir_object, has_suffix,
|
||||
path_join, path_join_buf,
|
||||
};
|
||||
|
||||
use common::defer;
|
||||
use path_absolutize::Absolutize;
|
||||
use rustfs_filemeta::{
|
||||
get_file_info, read_xl_meta_no_data, Cache, FileInfo, FileInfoOpts, FileMeta, MetaCacheEntry, MetacacheWriter, Opts,
|
||||
RawFileInfo, UpdateFn,
|
||||
Cache, FileInfo, FileInfoOpts, FileMeta, MetaCacheEntry, MetacacheWriter, Opts, RawFileInfo, UpdateFn, get_file_info,
|
||||
read_xl_meta_no_data,
|
||||
};
|
||||
use rustfs_rio::{bitrot_verify, Reader};
|
||||
use rustfs_rio::{Reader, bitrot_verify};
|
||||
use rustfs_utils::HashAlgorithm;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::io::SeekFrom;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use std::{
|
||||
fs::Metadata,
|
||||
@@ -60,8 +60,8 @@ use std::{
|
||||
use time::OffsetDateTime;
|
||||
use tokio::fs::{self, File};
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWrite, AsyncWriteExt, ErrorKind};
|
||||
use tokio::sync::mpsc::Sender;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
use tracing::{debug, error, info, warn};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -1550,7 +1550,7 @@ impl DiskAPI for LocalDisk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
#[tracing::instrument(level = "debug", skip(self, fi))]
|
||||
async fn rename_data(
|
||||
&self,
|
||||
src_volume: &str,
|
||||
|
||||
+13
-13
@@ -1,8 +1,8 @@
|
||||
use crate::utils::ellipses::*;
|
||||
use common::error::{Error, Result};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::io::{Error, Result};
|
||||
use tracing::debug;
|
||||
|
||||
/// Supported set sizes this is used to find the optimal
|
||||
@@ -89,7 +89,7 @@ pub struct DisksLayout {
|
||||
impl DisksLayout {
|
||||
pub fn from_volumes<T: AsRef<str>>(args: &[T]) -> Result<Self> {
|
||||
if args.is_empty() {
|
||||
return Err(Error::from_string("Invalid argument"));
|
||||
return Err(Error::other("Invalid argument"));
|
||||
}
|
||||
|
||||
let is_ellipses = args.iter().any(|v| has_ellipses(&[v]));
|
||||
@@ -98,7 +98,7 @@ impl DisksLayout {
|
||||
debug!("{} not set use default:0, {:?}", ENV_RUSTFS_ERASURE_SET_DRIVE_COUNT, err);
|
||||
"0".to_string()
|
||||
});
|
||||
let set_drive_count: usize = set_drive_count_env.parse()?;
|
||||
let set_drive_count: usize = set_drive_count_env.parse().map_err(Error::other)?;
|
||||
|
||||
// None of the args have ellipses use the old style.
|
||||
if !is_ellipses {
|
||||
@@ -116,7 +116,7 @@ impl DisksLayout {
|
||||
let mut layout = Vec::with_capacity(args.len());
|
||||
for arg in args.iter() {
|
||||
if !has_ellipses(&[arg]) && args.len() > 1 {
|
||||
return Err(Error::from_string(
|
||||
return Err(Error::other(
|
||||
"all args must have ellipses for pool expansion (Invalid arguments specified)",
|
||||
));
|
||||
}
|
||||
@@ -189,7 +189,7 @@ fn get_all_sets<T: AsRef<str>>(set_drive_count: usize, is_ellipses: bool, args:
|
||||
for args in set_args.iter() {
|
||||
for arg in args {
|
||||
if unique_args.contains(arg) {
|
||||
return Err(Error::from_string(format!("Input args {} has duplicate ellipses", arg)));
|
||||
return Err(Error::other(format!("Input args {} has duplicate ellipses", arg)));
|
||||
}
|
||||
unique_args.insert(arg);
|
||||
}
|
||||
@@ -245,7 +245,7 @@ impl EndpointSet {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_volumes<T: AsRef<str>>(args: &[T], set_drive_count: usize) -> Result<Self, Error> {
|
||||
pub fn from_volumes<T: AsRef<str>>(args: &[T], set_drive_count: usize) -> Result<Self> {
|
||||
let mut arg_patterns = Vec::with_capacity(args.len());
|
||||
for arg in args {
|
||||
arg_patterns.push(find_ellipses_patterns(arg.as_ref())?);
|
||||
@@ -377,20 +377,20 @@ fn get_set_indexes<T: AsRef<str>>(
|
||||
arg_patterns: &[ArgPattern],
|
||||
) -> Result<Vec<Vec<usize>>> {
|
||||
if args.is_empty() || total_sizes.is_empty() {
|
||||
return Err(Error::from_string("Invalid argument"));
|
||||
return Err(Error::other("Invalid argument"));
|
||||
}
|
||||
|
||||
for &size in total_sizes {
|
||||
// Check if total_sizes has minimum range upto set_size
|
||||
if size < SET_SIZES[0] || size < set_drive_count {
|
||||
return Err(Error::from_string(format!("Incorrect number of endpoints provided, size {}", size)));
|
||||
return Err(Error::other(format!("Incorrect number of endpoints provided, size {}", size)));
|
||||
}
|
||||
}
|
||||
|
||||
let common_size = get_divisible_size(total_sizes);
|
||||
let mut set_counts = possible_set_counts(common_size);
|
||||
if set_counts.is_empty() {
|
||||
return Err(Error::from_string(format!(
|
||||
return Err(Error::other(format!(
|
||||
"Incorrect number of endpoints provided, number of drives {} is not divisible by any supported erasure set sizes {}",
|
||||
common_size, 0
|
||||
)));
|
||||
@@ -399,7 +399,7 @@ fn get_set_indexes<T: AsRef<str>>(
|
||||
// Returns possible set counts with symmetry.
|
||||
set_counts = possible_set_counts_with_symmetry(&set_counts, arg_patterns);
|
||||
if set_counts.is_empty() {
|
||||
return Err(Error::from_string("No symmetric distribution detected with input endpoints provided"));
|
||||
return Err(Error::other("No symmetric distribution detected with input endpoints provided"));
|
||||
}
|
||||
|
||||
let set_size = {
|
||||
@@ -407,7 +407,7 @@ fn get_set_indexes<T: AsRef<str>>(
|
||||
let has_set_drive_count = set_counts.contains(&set_drive_count);
|
||||
|
||||
if !has_set_drive_count {
|
||||
return Err(Error::from_string(format!(
|
||||
return Err(Error::other(format!(
|
||||
"Invalid set drive count {}. Acceptable values for {:?} number drives are {:?}",
|
||||
set_drive_count, common_size, &set_counts
|
||||
)));
|
||||
@@ -416,7 +416,7 @@ fn get_set_indexes<T: AsRef<str>>(
|
||||
} else {
|
||||
set_counts = possible_set_counts_with_symmetry(&set_counts, arg_patterns);
|
||||
if set_counts.is_empty() {
|
||||
return Err(Error::from_string(format!(
|
||||
return Err(Error::other(format!(
|
||||
"No symmetric distribution detected with input endpoints , drives {} cannot be spread symmetrically by any supported erasure set sizes {:?}",
|
||||
common_size, &set_counts
|
||||
)));
|
||||
@@ -427,7 +427,7 @@ fn get_set_indexes<T: AsRef<str>>(
|
||||
};
|
||||
|
||||
if !is_valid_set_size(set_size) {
|
||||
return Err(Error::from_string("Incorrect number of endpoints provided3"));
|
||||
return Err(Error::other("Incorrect number of endpoints provided3"));
|
||||
}
|
||||
|
||||
Ok(total_sizes
|
||||
|
||||
+28
-31
@@ -6,9 +6,9 @@ use crate::{
|
||||
global::global_rustfs_port,
|
||||
utils::net::{self, XHost},
|
||||
};
|
||||
use common::error::{Error, Result};
|
||||
use std::io::{Error, Result};
|
||||
use std::{
|
||||
collections::{hash_map::Entry, HashMap, HashSet},
|
||||
collections::{HashMap, HashSet, hash_map::Entry},
|
||||
net::IpAddr,
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ impl<T: AsRef<str>> TryFrom<&[T]> for Endpoints {
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
let endpoint = match Endpoint::try_from(arg.as_ref()) {
|
||||
Ok(ep) => ep,
|
||||
Err(e) => return Err(Error::from_string(format!("'{}': {}", arg.as_ref(), e))),
|
||||
Err(e) => return Err(Error::other(format!("'{}': {}", arg.as_ref(), e))),
|
||||
};
|
||||
|
||||
// All endpoints have to be same type and scheme if applicable.
|
||||
@@ -84,15 +84,15 @@ impl<T: AsRef<str>> TryFrom<&[T]> for Endpoints {
|
||||
endpoint_type = Some(endpoint.get_type());
|
||||
schema = Some(endpoint.url.scheme().to_owned());
|
||||
} else if Some(endpoint.get_type()) != endpoint_type {
|
||||
return Err(Error::from_string("mixed style endpoints are not supported"));
|
||||
return Err(Error::other("mixed style endpoints are not supported"));
|
||||
} else if Some(endpoint.url.scheme()) != schema.as_deref() {
|
||||
return Err(Error::from_string("mixed scheme is not supported"));
|
||||
return Err(Error::other("mixed scheme is not supported"));
|
||||
}
|
||||
|
||||
// Check for duplicate endpoints.
|
||||
let endpoint_str = endpoint.to_string();
|
||||
if uniq_set.contains(&endpoint_str) {
|
||||
return Err(Error::from_string("duplicate endpoints found"));
|
||||
return Err(Error::other("duplicate endpoints found"));
|
||||
}
|
||||
|
||||
uniq_set.insert(endpoint_str);
|
||||
@@ -156,7 +156,7 @@ impl PoolEndpointList {
|
||||
/// hostnames and discovers those are local or remote.
|
||||
fn create_pool_endpoints(server_addr: &str, disks_layout: &DisksLayout) -> Result<Self> {
|
||||
if disks_layout.is_empty_layout() {
|
||||
return Err(Error::from_string("invalid number of endpoints"));
|
||||
return Err(Error::other("invalid number of endpoints"));
|
||||
}
|
||||
|
||||
let server_addr = net::check_local_server_addr(server_addr)?;
|
||||
@@ -167,7 +167,7 @@ impl PoolEndpointList {
|
||||
endpoint.update_is_local(server_addr.port())?;
|
||||
|
||||
if endpoint.get_type() != EndpointType::Path {
|
||||
return Err(Error::from_string("use path style endpoint for single node setup"));
|
||||
return Err(Error::other("use path style endpoint for single node setup"));
|
||||
}
|
||||
|
||||
endpoint.set_pool_index(0);
|
||||
@@ -201,7 +201,7 @@ impl PoolEndpointList {
|
||||
}
|
||||
|
||||
if endpoints.as_ref().is_empty() {
|
||||
return Err(Error::from_string("invalid number of endpoints"));
|
||||
return Err(Error::other("invalid number of endpoints"));
|
||||
}
|
||||
|
||||
pool_endpoints.push(endpoints);
|
||||
@@ -227,15 +227,14 @@ impl PoolEndpointList {
|
||||
|
||||
let host = ep.url.host().unwrap();
|
||||
let host_ip_set = host_ip_cache.entry(host.clone()).or_insert({
|
||||
net::get_host_ip(host.clone())
|
||||
.map_err(|e| Error::from_string(format!("host '{}' cannot resolve: {}", host, e)))?
|
||||
net::get_host_ip(host.clone()).map_err(|e| Error::other(format!("host '{}' cannot resolve: {}", host, e)))?
|
||||
});
|
||||
|
||||
let path = ep.get_file_path();
|
||||
match path_ip_map.entry(path) {
|
||||
Entry::Occupied(mut e) => {
|
||||
if e.get().intersection(host_ip_set).count() > 0 {
|
||||
return Err(Error::from_string(format!(
|
||||
return Err(Error::other(format!(
|
||||
"same path '{}' can not be served by different port on same address",
|
||||
path
|
||||
)));
|
||||
@@ -257,7 +256,7 @@ impl PoolEndpointList {
|
||||
|
||||
let path = ep.get_file_path();
|
||||
if local_path_set.contains(path) {
|
||||
return Err(Error::from_string(format!(
|
||||
return Err(Error::other(format!(
|
||||
"path '{}' cannot be served by different address on same server",
|
||||
path
|
||||
)));
|
||||
@@ -285,7 +284,7 @@ impl PoolEndpointList {
|
||||
// If all endpoints have same port number, Just treat it as local erasure setup
|
||||
// using URL style endpoints.
|
||||
if local_port_set.len() == 1 && local_server_host_set.len() > 1 {
|
||||
return Err(Error::from_string("all local endpoints should not have different hostnames/ips"));
|
||||
return Err(Error::other("all local endpoints should not have different hostnames/ips"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,7 +452,7 @@ impl EndpointServerPools {
|
||||
/// both ellipses and without ellipses transparently.
|
||||
pub fn create_server_endpoints(server_addr: &str, disks_layout: &DisksLayout) -> Result<(EndpointServerPools, SetupType)> {
|
||||
if disks_layout.pools.is_empty() {
|
||||
return Err(Error::from_string("Invalid arguments specified"));
|
||||
return Err(Error::other("Invalid arguments specified"));
|
||||
}
|
||||
|
||||
let pool_eps = PoolEndpointList::create_pool_endpoints(server_addr, disks_layout)?;
|
||||
@@ -490,7 +489,7 @@ impl EndpointServerPools {
|
||||
|
||||
for ep in eps.endpoints.as_ref() {
|
||||
if exits.contains(&ep.to_string()) {
|
||||
return Err(Error::from_string("duplicate endpoints found"));
|
||||
return Err(Error::other("duplicate endpoints found"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,8 +663,8 @@ mod test {
|
||||
None,
|
||||
6,
|
||||
),
|
||||
(vec!["d1", "d2", "d3", "d1"], Some(Error::from_string("duplicate endpoints found")), 7),
|
||||
(vec!["d1", "d2", "d3", "./d1"], Some(Error::from_string("duplicate endpoints found")), 8),
|
||||
(vec!["d1", "d2", "d3", "d1"], Some(Error::other("duplicate endpoints found")), 7),
|
||||
(vec!["d1", "d2", "d3", "./d1"], Some(Error::other("duplicate endpoints found")), 8),
|
||||
(
|
||||
vec![
|
||||
"http://localhost/d1",
|
||||
@@ -673,17 +672,17 @@ mod test {
|
||||
"http://localhost/d1",
|
||||
"http://localhost/d4",
|
||||
],
|
||||
Some(Error::from_string("duplicate endpoints found")),
|
||||
Some(Error::other("duplicate endpoints found")),
|
||||
9,
|
||||
),
|
||||
(
|
||||
vec!["ftp://server/d1", "http://server/d2", "http://server/d3", "http://server/d4"],
|
||||
Some(Error::from_string("'ftp://server/d1': invalid URL endpoint format")),
|
||||
Some(Error::other("'ftp://server/d1': invalid URL endpoint format")),
|
||||
10,
|
||||
),
|
||||
(
|
||||
vec!["d1", "http://localhost/d2", "d3", "d4"],
|
||||
Some(Error::from_string("mixed style endpoints are not supported")),
|
||||
Some(Error::other("mixed style endpoints are not supported")),
|
||||
11,
|
||||
),
|
||||
(
|
||||
@@ -693,7 +692,7 @@ mod test {
|
||||
"http://example.net/d1",
|
||||
"https://example.edut/d1",
|
||||
],
|
||||
Some(Error::from_string("mixed scheme is not supported")),
|
||||
Some(Error::other("mixed scheme is not supported")),
|
||||
12,
|
||||
),
|
||||
(
|
||||
@@ -703,7 +702,7 @@ mod test {
|
||||
"192.168.1.210:9000/tmp/dir2",
|
||||
"192.168.110:9000/tmp/dir3",
|
||||
],
|
||||
Some(Error::from_string(
|
||||
Some(Error::other(
|
||||
"'192.168.1.210:9000/tmp/dir0': invalid URL endpoint format: missing scheme http or https",
|
||||
)),
|
||||
13,
|
||||
@@ -811,7 +810,7 @@ mod test {
|
||||
TestCase {
|
||||
num: 1,
|
||||
server_addr: "localhost",
|
||||
expected_err: Some(Error::from_string("address localhost: missing port in address")),
|
||||
expected_err: Some(Error::other("address localhost: missing port in address")),
|
||||
..Default::default()
|
||||
},
|
||||
// Erasure Single Drive
|
||||
@@ -819,7 +818,7 @@ mod test {
|
||||
num: 2,
|
||||
server_addr: "localhost:9000",
|
||||
args: vec!["http://localhost/d1"],
|
||||
expected_err: Some(Error::from_string("use path style endpoint for single node setup")),
|
||||
expected_err: Some(Error::other("use path style endpoint for single node setup")),
|
||||
..Default::default()
|
||||
},
|
||||
TestCase {
|
||||
@@ -859,7 +858,7 @@ mod test {
|
||||
"https://example.com/d1",
|
||||
"https://example.com/d2",
|
||||
],
|
||||
expected_err: Some(Error::from_string("same path '/d1' can not be served by different port on same address")),
|
||||
expected_err: Some(Error::other("same path '/d1' can not be served by different port on same address")),
|
||||
..Default::default()
|
||||
},
|
||||
// Erasure Setup with PathEndpointType
|
||||
@@ -953,7 +952,7 @@ mod test {
|
||||
"http://127.0.0.1/d3",
|
||||
"http://127.0.0.1/d4",
|
||||
],
|
||||
expected_err: Some(Error::from_string("all local endpoints should not have different hostnames/ips")),
|
||||
expected_err: Some(Error::other("all local endpoints should not have different hostnames/ips")),
|
||||
..Default::default()
|
||||
},
|
||||
TestCase {
|
||||
@@ -965,9 +964,7 @@ mod test {
|
||||
case7_endpoint1.as_str(),
|
||||
"http://10.0.0.2:9001/export",
|
||||
],
|
||||
expected_err: Some(Error::from_string(
|
||||
"same path '/export' can not be served by different port on same address",
|
||||
)),
|
||||
expected_err: Some(Error::other("same path '/export' can not be served by different port on same address")),
|
||||
..Default::default()
|
||||
},
|
||||
TestCase {
|
||||
@@ -979,7 +976,7 @@ mod test {
|
||||
"http://10.0.0.1:9000/export",
|
||||
"http://10.0.0.2:9000/export",
|
||||
],
|
||||
expected_err: Some(Error::from_string("path '/export' cannot be served by different address on same server")),
|
||||
expected_err: Some(Error::other("path '/export' cannot be served by different address on same server")),
|
||||
..Default::default()
|
||||
},
|
||||
// DistErasure type
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::bitrot::{BitrotReader, BitrotWriter};
|
||||
use crate::disk::error::{Error, Result};
|
||||
use crate::disk::error_reduce::{reduce_write_quorum_errs, OBJECT_OP_IGNORED_ERRS};
|
||||
use crate::disk::error_reduce::{OBJECT_OP_IGNORED_ERRS, reduce_write_quorum_errs};
|
||||
use crate::io::Etag;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::join_all;
|
||||
@@ -72,11 +72,7 @@ impl Erasure {
|
||||
if total_size > 0 {
|
||||
let new_len = {
|
||||
let remain = total_size - total;
|
||||
if remain > self.block_size {
|
||||
self.block_size
|
||||
} else {
|
||||
remain
|
||||
}
|
||||
if remain > self.block_size { self.block_size } else { remain }
|
||||
};
|
||||
|
||||
if new_len == 0 && total > 0 {
|
||||
|
||||
@@ -164,6 +164,9 @@ pub enum StorageError {
|
||||
#[error("first disk wiat")]
|
||||
FirstDiskWait,
|
||||
|
||||
#[error("Bucket policy not found")]
|
||||
BucketPolicyNotFound,
|
||||
|
||||
#[error("Io error: {0}")]
|
||||
Io(std::io::Error),
|
||||
}
|
||||
@@ -376,6 +379,7 @@ impl Clone for StorageError {
|
||||
StorageError::FirstDiskWait => StorageError::FirstDiskWait,
|
||||
StorageError::TooManyOpenFiles => StorageError::TooManyOpenFiles,
|
||||
StorageError::NoHealRequired => StorageError::NoHealRequired,
|
||||
StorageError::BucketPolicyNotFound => StorageError::BucketPolicyNotFound,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,6 +442,7 @@ impl StorageError {
|
||||
StorageError::ConfigNotFound => 0x35,
|
||||
StorageError::TooManyOpenFiles => 0x36,
|
||||
StorageError::NoHealRequired => 0x37,
|
||||
StorageError::BucketPolicyNotFound => 0x38,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,6 +507,7 @@ impl StorageError {
|
||||
0x35 => Some(StorageError::ConfigNotFound),
|
||||
0x36 => Some(StorageError::TooManyOpenFiles),
|
||||
0x37 => Some(StorageError::NoHealRequired),
|
||||
0x38 => Some(StorageError::BucketPolicyNotFound),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
+3399
-3399
File diff suppressed because it is too large
Load Diff
@@ -27,11 +27,7 @@ impl InlineData {
|
||||
}
|
||||
|
||||
pub fn after_version(&self) -> &[u8] {
|
||||
if self.0.is_empty() {
|
||||
&self.0
|
||||
} else {
|
||||
&self.0[1..]
|
||||
}
|
||||
if self.0.is_empty() { &self.0 } else { &self.0[1..] }
|
||||
}
|
||||
|
||||
pub fn find(&self, key: &str) -> Result<Option<Vec<u8>>> {
|
||||
|
||||
+56
-70
@@ -1,7 +1,7 @@
|
||||
use crate::disk::error_reduce::{reduce_read_quorum_errs, reduce_write_quorum_errs, OBJECT_OP_IGNORED_ERRS};
|
||||
use crate::disk::error_reduce::{OBJECT_OP_IGNORED_ERRS, reduce_read_quorum_errs, reduce_write_quorum_errs};
|
||||
use crate::disk::{
|
||||
self, conv_part_err_to_int, has_part_err, CHECK_PART_DISK_NOT_FOUND, CHECK_PART_FILE_CORRUPT, CHECK_PART_FILE_NOT_FOUND,
|
||||
CHECK_PART_SUCCESS,
|
||||
self, CHECK_PART_DISK_NOT_FOUND, CHECK_PART_FILE_CORRUPT, CHECK_PART_FILE_NOT_FOUND, CHECK_PART_SUCCESS,
|
||||
conv_part_err_to_int, has_part_err,
|
||||
};
|
||||
use crate::erasure_coding;
|
||||
use crate::error::{Error, Result};
|
||||
@@ -9,24 +9,24 @@ use crate::global::GLOBAL_MRFState;
|
||||
use crate::heal::data_usage_cache::DataUsageCache;
|
||||
use crate::store_api::ObjectToDelete;
|
||||
use crate::{
|
||||
cache_value::metacache_set::{list_path_raw, ListPathRawOptions},
|
||||
config::{storageclass, GLOBAL_StorageClass},
|
||||
cache_value::metacache_set::{ListPathRawOptions, list_path_raw},
|
||||
config::{GLOBAL_StorageClass, storageclass},
|
||||
disk::{
|
||||
endpoint::Endpoint, error::DiskError, format::FormatV3, new_disk, CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo,
|
||||
DiskInfoOptions, DiskOption, DiskStore, FileInfoVersions, ReadMultipleReq, ReadMultipleResp, ReadOptions,
|
||||
UpdateMetadataOpts, RUSTFS_META_BUCKET, RUSTFS_META_MULTIPART_BUCKET, RUSTFS_META_TMP_BUCKET,
|
||||
CheckPartsResp, DeleteOptions, DiskAPI, DiskInfo, DiskInfoOptions, DiskOption, DiskStore, FileInfoVersions,
|
||||
RUSTFS_META_BUCKET, RUSTFS_META_MULTIPART_BUCKET, RUSTFS_META_TMP_BUCKET, ReadMultipleReq, ReadMultipleResp, ReadOptions,
|
||||
UpdateMetadataOpts, endpoint::Endpoint, error::DiskError, format::FormatV3, new_disk,
|
||||
},
|
||||
error::{to_object_err, StorageError},
|
||||
error::{StorageError, to_object_err},
|
||||
global::{
|
||||
get_global_deployment_id, is_dist_erasure, GLOBAL_BackgroundHealState, GLOBAL_LOCAL_DISK_MAP,
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES,
|
||||
GLOBAL_BackgroundHealState, GLOBAL_LOCAL_DISK_MAP, GLOBAL_LOCAL_DISK_SET_DRIVES, get_global_deployment_id,
|
||||
is_dist_erasure,
|
||||
},
|
||||
heal::{
|
||||
data_usage::{DATA_USAGE_CACHE_NAME, DATA_USAGE_ROOT},
|
||||
data_usage_cache::{DataUsageCacheInfo, DataUsageEntry, DataUsageEntryInfo},
|
||||
heal_commands::{
|
||||
HealOpts, HealScanMode, HealingTracker, DRIVE_STATE_CORRUPT, DRIVE_STATE_MISSING, DRIVE_STATE_OFFLINE,
|
||||
DRIVE_STATE_OK, HEAL_DEEP_SCAN, HEAL_ITEM_OBJECT, HEAL_NORMAL_SCAN,
|
||||
DRIVE_STATE_CORRUPT, DRIVE_STATE_MISSING, DRIVE_STATE_OFFLINE, DRIVE_STATE_OK, HEAL_DEEP_SCAN, HEAL_ITEM_OBJECT,
|
||||
HEAL_NORMAL_SCAN, HealOpts, HealScanMode, HealingTracker,
|
||||
},
|
||||
heal_ops::BG_HEALING_UUID,
|
||||
},
|
||||
@@ -39,13 +39,13 @@ use crate::{
|
||||
store_init::load_format_erasure,
|
||||
utils::{
|
||||
crypto::{base64_decode, base64_encode, hex},
|
||||
path::{encode_dir_object, has_suffix, SLASH_SEPARATOR},
|
||||
path::{SLASH_SEPARATOR, encode_dir_object, has_suffix},
|
||||
},
|
||||
xhttp,
|
||||
};
|
||||
use crate::{disk::STORAGE_FORMAT_FILE, heal::mrf::PartialOperation};
|
||||
use crate::{
|
||||
heal::data_scanner::{globalHealConfig, HEAL_DELETE_DANGLING},
|
||||
heal::data_scanner::{HEAL_DELETE_DANGLING, globalHealConfig},
|
||||
store_api::ListObjectVersionsInfo,
|
||||
};
|
||||
use crate::{
|
||||
@@ -57,18 +57,18 @@ use chrono::Utc;
|
||||
use futures::future::join_all;
|
||||
use glob::Pattern;
|
||||
use http::HeaderMap;
|
||||
use lock::{namespace_lock::NsLockMap, LockApi};
|
||||
use lock::{LockApi, namespace_lock::NsLockMap};
|
||||
use madmin::heal_commands::{HealDriveInfo, HealResultItem};
|
||||
use md5::{Digest as Md5Digest, Md5};
|
||||
use rand::{
|
||||
thread_rng,
|
||||
{seq::SliceRandom, Rng},
|
||||
{Rng, seq::SliceRandom},
|
||||
};
|
||||
use rustfs_filemeta::{
|
||||
file_info_from_raw, merge_file_meta_versions, FileInfo, FileMeta, FileMetaShallowVersion, MetaCacheEntries, MetaCacheEntry,
|
||||
MetadataResolutionParams, ObjectPartInfo, RawFileInfo,
|
||||
FileInfo, FileMeta, FileMetaShallowVersion, MetaCacheEntries, MetaCacheEntry, MetadataResolutionParams, ObjectPartInfo,
|
||||
RawFileInfo, file_info_from_raw, merge_file_meta_versions,
|
||||
};
|
||||
use rustfs_rio::{bitrot_verify, BitrotReader, BitrotWriter, EtagResolvable, HashReader, Writer};
|
||||
use rustfs_rio::{BitrotReader, BitrotWriter, EtagResolvable, HashReader, Writer, bitrot_verify};
|
||||
use rustfs_utils::HashAlgorithm;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::hash::Hash;
|
||||
@@ -84,8 +84,8 @@ use std::{
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
use tokio::{
|
||||
io::{empty, AsyncWrite},
|
||||
sync::{broadcast, RwLock},
|
||||
io::{AsyncWrite, empty},
|
||||
sync::{RwLock, broadcast},
|
||||
};
|
||||
use tokio::{
|
||||
select,
|
||||
@@ -406,11 +406,7 @@ impl SetDisks {
|
||||
}
|
||||
}
|
||||
|
||||
if max >= write_quorum {
|
||||
data_dir
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if max >= write_quorum { data_dir } else { None }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -741,11 +737,7 @@ impl SetDisks {
|
||||
|
||||
fn common_time(times: &[Option<OffsetDateTime>], quorum: usize) -> Option<OffsetDateTime> {
|
||||
let (time, count) = Self::common_time_and_occurrence(times);
|
||||
if count >= quorum {
|
||||
time
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if count >= quorum { time } else { None }
|
||||
}
|
||||
|
||||
fn common_time_and_occurrence(times: &[Option<OffsetDateTime>]) -> (Option<OffsetDateTime>, usize) {
|
||||
@@ -786,11 +778,7 @@ impl SetDisks {
|
||||
|
||||
fn common_etag(etags: &[Option<String>], quorum: usize) -> Option<String> {
|
||||
let (etag, count) = Self::common_etags(etags);
|
||||
if count >= quorum {
|
||||
etag
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if count >= quorum { etag } else { None }
|
||||
}
|
||||
|
||||
fn common_etags(etags: &[Option<String>]) -> (Option<String>, usize) {
|
||||
@@ -1837,13 +1825,7 @@ impl SetDisks {
|
||||
|
||||
let total_size = fi.size;
|
||||
|
||||
let length = {
|
||||
if length == 0 {
|
||||
total_size - offset
|
||||
} else {
|
||||
length
|
||||
}
|
||||
};
|
||||
let length = { if length == 0 { total_size - offset } else { length } };
|
||||
|
||||
if offset > total_size || offset + length > total_size {
|
||||
return Err(Error::other("offset out of range"));
|
||||
@@ -1896,12 +1878,16 @@ impl SetDisks {
|
||||
readers.push(Some(reader));
|
||||
errors.push(None);
|
||||
} else if let Some(disk) = disk_op {
|
||||
// Calculate ceiling division of till_offset by shard_size
|
||||
let till_offset =
|
||||
till_offset.div_ceil(erasure.shard_size()) * HashAlgorithm::HighwayHash256.size() + till_offset;
|
||||
|
||||
let rd = disk
|
||||
.read_file_stream(
|
||||
bucket,
|
||||
&format!("{}/{}/part.{}", object, files[idx].data_dir.unwrap_or(Uuid::nil()), part_number),
|
||||
part_offset,
|
||||
till_offset,
|
||||
part_length,
|
||||
)
|
||||
.await?;
|
||||
let reader = BitrotReader::new(rd, erasure.shard_size(), HashAlgorithm::HighwayHash256);
|
||||
@@ -2403,8 +2389,10 @@ impl SetDisks {
|
||||
}
|
||||
|
||||
if !lastest_meta.deleted && lastest_meta.erasure.distribution.len() != available_disks.len() {
|
||||
let err_str = format!("unexpected file distribution ({:?}) from available disks ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution, available_disks, bucket, object, version_id);
|
||||
let err_str = format!(
|
||||
"unexpected file distribution ({:?}) from available disks ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution, available_disks, bucket, object, version_id
|
||||
);
|
||||
warn!(err_str);
|
||||
let err = DiskError::other(err_str);
|
||||
return Ok((
|
||||
@@ -2416,8 +2404,10 @@ impl SetDisks {
|
||||
|
||||
let latest_disks = Self::shuffle_disks(&available_disks, &lastest_meta.erasure.distribution);
|
||||
if !lastest_meta.deleted && lastest_meta.erasure.distribution.len() != outdate_disks.len() {
|
||||
let err_str = format!("unexpected file distribution ({:?}) from outdated disks ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution, outdate_disks, bucket, object, version_id);
|
||||
let err_str = format!(
|
||||
"unexpected file distribution ({:?}) from outdated disks ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution, outdate_disks, bucket, object, version_id
|
||||
);
|
||||
warn!(err_str);
|
||||
let err = DiskError::other(err_str);
|
||||
return Ok((
|
||||
@@ -2428,8 +2418,14 @@ impl SetDisks {
|
||||
}
|
||||
|
||||
if !lastest_meta.deleted && lastest_meta.erasure.distribution.len() != parts_metadata.len() {
|
||||
let err_str = format!("unexpected file distribution ({:?}) from metadata entries ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution, parts_metadata.len(), bucket, object, version_id);
|
||||
let err_str = format!(
|
||||
"unexpected file distribution ({:?}) from metadata entries ({:?}), looks like backend disks have been manually modified refusing to heal {}/{}({})",
|
||||
lastest_meta.erasure.distribution,
|
||||
parts_metadata.len(),
|
||||
bucket,
|
||||
object,
|
||||
version_id
|
||||
);
|
||||
warn!(err_str);
|
||||
let err = DiskError::other(err_str);
|
||||
return Ok((
|
||||
@@ -3907,6 +3903,7 @@ impl ObjectIO for SetDisks {
|
||||
};
|
||||
|
||||
writers.push(Some(writer));
|
||||
errors.push(None);
|
||||
} else {
|
||||
errors.push(Some(DiskError::DiskNotFound));
|
||||
writers.push(None);
|
||||
@@ -3915,6 +3912,7 @@ impl ObjectIO for SetDisks {
|
||||
|
||||
let nil_count = errors.iter().filter(|&e| e.is_none()).count();
|
||||
if nil_count < write_quorum {
|
||||
error!("not enough disks to write: {:?}", errors);
|
||||
if let Some(write_err) = reduce_write_quorum_errs(&errors, OBJECT_OP_IGNORED_ERRS, write_quorum) {
|
||||
return Err(to_object_err(write_err.into(), vec![bucket, object]));
|
||||
}
|
||||
@@ -3926,7 +3924,7 @@ impl ObjectIO for SetDisks {
|
||||
|
||||
let (reader, w_size) = Arc::new(erasure).encode(stream, &mut writers, write_quorum).await?; // TODO: 出错,删除临时目录
|
||||
|
||||
mem::replace(&mut data.stream, reader);
|
||||
let _ = mem::replace(&mut data.stream, reader);
|
||||
// if let Err(err) = close_bitrot_writers(&mut writers).await {
|
||||
// error!("close_bitrot_writers err {:?}", err);
|
||||
// }
|
||||
@@ -4549,25 +4547,11 @@ impl StorageAPI for SetDisks {
|
||||
|
||||
let erasure = erasure_coding::Erasure::new(fi.erasure.data_blocks, fi.erasure.parity_blocks, fi.erasure.block_size);
|
||||
|
||||
let is_inline_buffer = {
|
||||
if let Some(sc) = GLOBAL_StorageClass.get() {
|
||||
sc.should_inline(erasure.shard_file_size(data.content_length), opts.versioned)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
let mut writers = Vec::with_capacity(shuffle_disks.len());
|
||||
let mut errors = Vec::with_capacity(shuffle_disks.len());
|
||||
for disk_op in shuffle_disks.iter() {
|
||||
if let Some(disk) = disk_op {
|
||||
let writer = if is_inline_buffer {
|
||||
BitrotWriter::new(
|
||||
Writer::from_cursor(Cursor::new(Vec::new())),
|
||||
erasure.shard_size(),
|
||||
HashAlgorithm::HighwayHash256,
|
||||
)
|
||||
} else {
|
||||
let writer = {
|
||||
let f = match disk
|
||||
.create_file("", RUSTFS_META_TMP_BUCKET, &tmp_part_path, erasure.shard_file_size(data.content_length))
|
||||
.await
|
||||
@@ -4584,6 +4568,7 @@ impl StorageAPI for SetDisks {
|
||||
};
|
||||
|
||||
writers.push(Some(writer));
|
||||
errors.push(None);
|
||||
} else {
|
||||
errors.push(Some(DiskError::DiskNotFound));
|
||||
writers.push(None);
|
||||
@@ -4601,8 +4586,9 @@ impl StorageAPI for SetDisks {
|
||||
|
||||
let stream = mem::replace(&mut data.stream, HashReader::new(Box::new(Cursor::new(Vec::new())), 0, 0, None, false)?);
|
||||
|
||||
let (mut reader, w_size) = Arc::new(erasure).encode(stream, &mut writers, write_quorum).await?; // TODO: 出错,删除临时目录
|
||||
mem::replace(&mut data.stream, reader);
|
||||
let (reader, w_size) = Arc::new(erasure).encode(stream, &mut writers, write_quorum).await?; // TODO: 出错,删除临时目录
|
||||
|
||||
let _ = mem::replace(&mut data.stream, reader);
|
||||
|
||||
let mut etag = data.stream.try_resolve_etag().unwrap_or_default();
|
||||
|
||||
@@ -5755,9 +5741,9 @@ fn get_complete_multipart_md5(parts: &[CompletePart]) -> String {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::disk::error::DiskError;
|
||||
use crate::disk::CHECK_PART_UNKNOWN;
|
||||
use crate::disk::CHECK_PART_VOLUME_NOT_FOUND;
|
||||
use crate::disk::error::DiskError;
|
||||
use crate::store_api::CompletePart;
|
||||
use rustfs_filemeta::ErasureInfo;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use common::error::{Error, Result};
|
||||
use std::io::{Error, Result};
|
||||
|
||||
pub fn parse_bool(str: &str) -> Result<bool> {
|
||||
match str {
|
||||
"1" | "t" | "T" | "true" | "TRUE" | "True" | "on" | "ON" | "On" | "enabled" => Ok(true),
|
||||
"0" | "f" | "F" | "false" | "FALSE" | "False" | "off" | "OFF" | "Off" | "disabled" => Ok(false),
|
||||
_ => Err(Error::from_string(format!("ParseBool: parsing {}", str))),
|
||||
_ => Err(Error::other(format!("ParseBool: parsing {}", str))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use common::error::{Error, Result};
|
||||
use lazy_static::*;
|
||||
use regex::Regex;
|
||||
use std::io::{Error, Result};
|
||||
|
||||
lazy_static! {
|
||||
static ref ELLIPSES_RE: Regex = Regex::new(r"(.*)(\{[0-9a-z]*\.\.\.[0-9a-z]*\})(.*)").unwrap();
|
||||
@@ -107,7 +107,10 @@ pub fn find_ellipses_patterns(arg: &str) -> Result<ArgPattern> {
|
||||
let mut parts = match ELLIPSES_RE.captures(arg) {
|
||||
Some(caps) => caps,
|
||||
None => {
|
||||
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)));
|
||||
return Err(Error::other(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
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,7 +147,10 @@ pub fn find_ellipses_patterns(arg: &str) -> Result<ArgPattern> {
|
||||
|| p.suffix.contains(OPEN_BRACES)
|
||||
|| p.suffix.contains(CLOSE_BRACES)
|
||||
{
|
||||
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)));
|
||||
return Err(Error::other(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
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,10 +171,10 @@ pub fn has_ellipses<T: AsRef<str>>(s: &[T]) -> bool {
|
||||
/// {33...64}
|
||||
pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> {
|
||||
if !pattern.contains(OPEN_BRACES) {
|
||||
return Err(Error::from_string("Invalid argument"));
|
||||
return Err(Error::other("Invalid argument"));
|
||||
}
|
||||
if !pattern.contains(OPEN_BRACES) {
|
||||
return Err(Error::from_string("Invalid argument"));
|
||||
return Err(Error::other("Invalid argument"));
|
||||
}
|
||||
|
||||
let ellipses_range: Vec<&str> = pattern
|
||||
@@ -178,15 +184,15 @@ pub fn parse_ellipses_range(pattern: &str) -> Result<Vec<String>> {
|
||||
.collect();
|
||||
|
||||
if ellipses_range.len() != 2 {
|
||||
return Err(Error::from_string("Invalid argument"));
|
||||
return Err(Error::other("Invalid argument"));
|
||||
}
|
||||
|
||||
// TODO: Add support for hexadecimals.
|
||||
let start = ellipses_range[0].parse::<usize>()?;
|
||||
let end = ellipses_range[1].parse::<usize>()?;
|
||||
let start = ellipses_range[0].parse::<usize>().map_err(|e| Error::other(e))?;
|
||||
let end = ellipses_range[1].parse::<usize>().map_err(|e| Error::other(e))?;
|
||||
|
||||
if start > end {
|
||||
return Err(Error::from_string("Invalid argument:range start cannot be bigger than end"));
|
||||
return Err(Error::other("Invalid argument:range start cannot be bigger than end"));
|
||||
}
|
||||
|
||||
let mut ret: Vec<String> = Vec::with_capacity(end - start + 1);
|
||||
|
||||
+11
-14
@@ -1,5 +1,5 @@
|
||||
use common::error::{Error, Result};
|
||||
use lazy_static::lazy_static;
|
||||
use std::io::{Error, Result};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
fmt::Display,
|
||||
@@ -23,7 +23,7 @@ pub fn is_socket_addr(addr: &str) -> bool {
|
||||
pub fn check_local_server_addr(server_addr: &str) -> Result<SocketAddr> {
|
||||
let addr: Vec<SocketAddr> = match server_addr.to_socket_addrs() {
|
||||
Ok(addr) => addr.collect(),
|
||||
Err(err) => return Err(Error::new(Box::new(err))),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
// 0.0.0.0 is a wildcard address and refers to local network
|
||||
@@ -44,7 +44,7 @@ pub fn check_local_server_addr(server_addr: &str) -> Result<SocketAddr> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::from_string("host in server address should be this server"))
|
||||
Err(Error::other("host in server address should be this server"))
|
||||
}
|
||||
|
||||
/// checks if the given parameter correspond to one of
|
||||
@@ -55,7 +55,7 @@ pub fn is_local_host(host: Host<&str>, port: u16, local_port: u16) -> Result<boo
|
||||
Host::Domain(domain) => {
|
||||
let ips = match (domain, 0).to_socket_addrs().map(|v| v.map(|v| v.ip()).collect::<Vec<_>>()) {
|
||||
Ok(ips) => ips,
|
||||
Err(err) => return Err(Error::new(Box::new(err))),
|
||||
Err(err) => return Err(err),
|
||||
};
|
||||
|
||||
ips.iter().any(|ip| local_set.contains(ip))
|
||||
@@ -79,7 +79,7 @@ pub fn get_host_ip(host: Host<&str>) -> Result<HashSet<IpAddr>> {
|
||||
.map(|v| v.map(|v| v.ip()).collect::<HashSet<_>>())
|
||||
{
|
||||
Ok(ips) => Ok(ips),
|
||||
Err(err) => Err(Error::new(Box::new(err))),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
Host::Ipv4(ip) => {
|
||||
let mut set = HashSet::with_capacity(1);
|
||||
@@ -102,7 +102,7 @@ pub fn get_available_port() -> u16 {
|
||||
pub(crate) fn must_get_local_ips() -> Result<Vec<IpAddr>> {
|
||||
match netif::up() {
|
||||
Ok(up) => Ok(up.map(|x| x.address().to_owned()).collect()),
|
||||
Err(err) => Err(Error::from_string(format!("Unable to get IP addresses of this host: {}", err))),
|
||||
Err(err) => Err(Error::other(format!("Unable to get IP addresses of this host: {}", err))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ pub fn parse_and_resolve_address(addr_str: &str) -> Result<SocketAddr> {
|
||||
let port_str = port;
|
||||
let port: u16 = port_str
|
||||
.parse()
|
||||
.map_err(|e| Error::from_string(format!("Invalid port format: {}, err:{:?}", addr_str, e)))?;
|
||||
.map_err(|e| Error::other(format!("Invalid port format: {}, err:{:?}", addr_str, e)))?;
|
||||
let final_port = if port == 0 {
|
||||
get_available_port() // assume get_available_port is available here
|
||||
} else {
|
||||
@@ -199,13 +199,10 @@ mod test {
|
||||
("localhost:54321", Ok(())),
|
||||
("0.0.0.0:9000", Ok(())),
|
||||
// (":0", Ok(())),
|
||||
("localhost", Err(Error::from_string("invalid socket address"))),
|
||||
("", Err(Error::from_string("invalid socket address"))),
|
||||
(
|
||||
"example.org:54321",
|
||||
Err(Error::from_string("host in server address should be this server")),
|
||||
),
|
||||
(":-10", Err(Error::from_string("invalid port value"))),
|
||||
("localhost", Err(Error::other("invalid socket address"))),
|
||||
("", Err(Error::other("invalid socket address"))),
|
||||
("example.org:54321", Err(Error::other("host in server address should be this server"))),
|
||||
(":-10", Err(Error::other("invalid port value"))),
|
||||
];
|
||||
|
||||
for test_case in test_cases {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use nix::sys::stat::{self, stat};
|
||||
use nix::sys::statfs::{self, statfs, FsType};
|
||||
use nix::sys::statfs::{self, FsType, statfs};
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead, Error, ErrorKind};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::disk::Info;
|
||||
use common::error::{Error as e_Error, Result};
|
||||
use std::io::{Error, Result};
|
||||
|
||||
use super::IOStats;
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
bfree,
|
||||
p.as_ref().display()
|
||||
),
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
blocks,
|
||||
p.as_ref().display()
|
||||
),
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,7 +60,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
total,
|
||||
p.as_ref().display()
|
||||
),
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,7 +122,7 @@ pub fn get_drive_stats(major: u32, minor: u32) -> Result<IOStats> {
|
||||
fn read_drive_stats(stats_file: &str) -> Result<IOStats> {
|
||||
let stats = read_stat(stats_file)?;
|
||||
if stats.len() < 11 {
|
||||
return Err(e_Error::from_string(format!("found invalid format while reading {}", stats_file)));
|
||||
return Err(Error::new(ErrorKind::Other, format!("found invalid format while reading {}", stats_file)));
|
||||
}
|
||||
let mut io_stats = IOStats {
|
||||
read_ios: stats[0],
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use super::IOStats;
|
||||
use crate::disk::Info;
|
||||
use common::error::Result;
|
||||
use nix::sys::{stat::stat, statfs::statfs};
|
||||
use std::io::Error;
|
||||
use std::io::{Error, Result};
|
||||
use std::path::Path;
|
||||
|
||||
/// returns total and free bytes available in a directory, e.g. `/`.
|
||||
@@ -22,7 +21,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
bavail,
|
||||
bfree,
|
||||
p.as_ref().display()
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,7 +33,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
reserved,
|
||||
blocks,
|
||||
p.as_ref().display()
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -47,7 +46,7 @@ pub fn get_info(p: impl AsRef<Path>) -> std::io::Result<Info> {
|
||||
free,
|
||||
total,
|
||||
p.as_ref().display()
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
use super::IOStats;
|
||||
use crate::disk::Info;
|
||||
use common::error::Result;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::io::{Error, ErrorKind, Result};
|
||||
use std::mem;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::path::Path;
|
||||
|
||||
Reference in New Issue
Block a user