mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-29 16:37:07 +00:00
Issue 762 (#763)
* Add InvalidRangeSpec error * Add EntityTooSmall to from_u32 * Add InvalidRangeSpec to from_u32 * Map InvalidRangeSpec to correct S3ErrorCode * Return Error::InvalidRangeSpec * Use auto implementation --------- Co-authored-by: Niklas Mollenhauer <nikeee@outlook.com>
This commit is contained in:
@@ -49,11 +49,12 @@ pub enum HealType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Heal priority
|
/// Heal priority
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
pub enum HealPriority {
|
pub enum HealPriority {
|
||||||
/// Low priority
|
/// Low priority
|
||||||
Low = 0,
|
Low = 0,
|
||||||
/// Normal priority
|
/// Normal priority
|
||||||
|
#[default]
|
||||||
Normal = 1,
|
Normal = 1,
|
||||||
/// High priority
|
/// High priority
|
||||||
High = 2,
|
High = 2,
|
||||||
@@ -61,12 +62,6 @@ pub enum HealPriority {
|
|||||||
Urgent = 3,
|
Urgent = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HealPriority {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Heal options
|
/// Heal options
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct HealOptions {
|
pub struct HealOptions {
|
||||||
|
|||||||
@@ -85,19 +85,14 @@ impl Display for DriveState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum HealScanMode {
|
pub enum HealScanMode {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
#[default]
|
||||||
Normal,
|
Normal,
|
||||||
Deep,
|
Deep,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HealScanMode {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct HealOpts {
|
pub struct HealOpts {
|
||||||
pub recursive: bool,
|
pub recursive: bool,
|
||||||
@@ -175,11 +170,12 @@ pub struct HealChannelResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Heal priority
|
/// Heal priority
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum HealChannelPriority {
|
pub enum HealChannelPriority {
|
||||||
/// Low priority
|
/// Low priority
|
||||||
Low,
|
Low,
|
||||||
/// Normal priority
|
/// Normal priority
|
||||||
|
#[default]
|
||||||
Normal,
|
Normal,
|
||||||
/// High priority
|
/// High priority
|
||||||
High,
|
High,
|
||||||
@@ -187,12 +183,6 @@ pub enum HealChannelPriority {
|
|||||||
Critical,
|
Critical,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for HealChannelPriority {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Heal channel sender
|
/// Heal channel sender
|
||||||
pub type HealChannelSender = mpsc::UnboundedSender<HealChannelCommand>;
|
pub type HealChannelSender = mpsc::UnboundedSender<HealChannelCommand>;
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,9 @@ pub enum StorageError {
|
|||||||
|
|
||||||
#[error("Precondition failed")]
|
#[error("Precondition failed")]
|
||||||
PreconditionFailed,
|
PreconditionFailed,
|
||||||
|
|
||||||
|
#[error("Invalid range specified: {0}")]
|
||||||
|
InvalidRangeSpec(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StorageError {
|
impl StorageError {
|
||||||
@@ -424,6 +427,7 @@ impl Clone for StorageError {
|
|||||||
StorageError::InsufficientReadQuorum(a, b) => StorageError::InsufficientReadQuorum(a.clone(), b.clone()),
|
StorageError::InsufficientReadQuorum(a, b) => StorageError::InsufficientReadQuorum(a.clone(), b.clone()),
|
||||||
StorageError::InsufficientWriteQuorum(a, b) => StorageError::InsufficientWriteQuorum(a.clone(), b.clone()),
|
StorageError::InsufficientWriteQuorum(a, b) => StorageError::InsufficientWriteQuorum(a.clone(), b.clone()),
|
||||||
StorageError::PreconditionFailed => StorageError::PreconditionFailed,
|
StorageError::PreconditionFailed => StorageError::PreconditionFailed,
|
||||||
|
StorageError::InvalidRangeSpec(a) => StorageError::InvalidRangeSpec(a.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -491,6 +495,7 @@ impl StorageError {
|
|||||||
StorageError::InsufficientWriteQuorum(_, _) => 0x3A,
|
StorageError::InsufficientWriteQuorum(_, _) => 0x3A,
|
||||||
StorageError::PreconditionFailed => 0x3B,
|
StorageError::PreconditionFailed => 0x3B,
|
||||||
StorageError::EntityTooSmall(_, _, _) => 0x3C,
|
StorageError::EntityTooSmall(_, _, _) => 0x3C,
|
||||||
|
StorageError::InvalidRangeSpec(_) => 0x3D,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,6 +564,8 @@ impl StorageError {
|
|||||||
0x39 => Some(StorageError::InsufficientReadQuorum(Default::default(), Default::default())),
|
0x39 => Some(StorageError::InsufficientReadQuorum(Default::default(), Default::default())),
|
||||||
0x3A => Some(StorageError::InsufficientWriteQuorum(Default::default(), Default::default())),
|
0x3A => Some(StorageError::InsufficientWriteQuorum(Default::default(), Default::default())),
|
||||||
0x3B => Some(StorageError::PreconditionFailed),
|
0x3B => Some(StorageError::PreconditionFailed),
|
||||||
|
0x3C => Some(StorageError::EntityTooSmall(Default::default(), Default::default(), Default::default())),
|
||||||
|
0x3D => Some(StorageError::InvalidRangeSpec(Default::default())),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ impl HTTPRangeSpec {
|
|||||||
let suffix_len = if self.start < 0 {
|
let suffix_len = if self.start < 0 {
|
||||||
self.start
|
self.start
|
||||||
.checked_neg()
|
.checked_neg()
|
||||||
.ok_or_else(|| Error::other("range value invalid: suffix length overflow"))?
|
.ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))?
|
||||||
} else {
|
} else {
|
||||||
self.start
|
self.start
|
||||||
};
|
};
|
||||||
@@ -304,14 +304,14 @@ impl HTTPRangeSpec {
|
|||||||
}
|
}
|
||||||
pub fn get_length(&self, res_size: i64) -> Result<i64> {
|
pub fn get_length(&self, res_size: i64) -> Result<i64> {
|
||||||
if res_size < 0 {
|
if res_size < 0 {
|
||||||
return Err(Error::other("The requested range is not satisfiable"));
|
return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_suffix_length {
|
if self.is_suffix_length {
|
||||||
let specified_len = if self.start < 0 {
|
let specified_len = if self.start < 0 {
|
||||||
self.start
|
self.start
|
||||||
.checked_neg()
|
.checked_neg()
|
||||||
.ok_or_else(|| Error::other("range value invalid: suffix length overflow"))?
|
.ok_or_else(|| Error::InvalidRangeSpec("range value invalid: suffix length overflow".to_string()))?
|
||||||
} else {
|
} else {
|
||||||
self.start
|
self.start
|
||||||
};
|
};
|
||||||
@@ -325,7 +325,7 @@ impl HTTPRangeSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.start >= res_size {
|
if self.start >= res_size {
|
||||||
return Err(Error::other("The requested range is not satisfiable"));
|
return Err(Error::InvalidRangeSpec("The requested range is not satisfiable".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.end > -1 {
|
if self.end > -1 {
|
||||||
@@ -343,7 +343,7 @@ impl HTTPRangeSpec {
|
|||||||
return Ok(range_length);
|
return Ok(range_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::other(format!(
|
Err(Error::InvalidRangeSpec(format!(
|
||||||
"range value invalid: start={}, end={}, expected start <= end and end >= -1",
|
"range value invalid: start={}, end={}, expected start <= end and end >= -1",
|
||||||
self.start, self.end
|
self.start, self.end
|
||||||
)))
|
)))
|
||||||
@@ -1361,7 +1361,7 @@ impl<R: AsyncRead + Unpin + Send + Sync> RangedDecompressReader<R> {
|
|||||||
// Validate the range request
|
// Validate the range request
|
||||||
if offset >= total_size {
|
if offset >= total_size {
|
||||||
tracing::debug!("Range offset {} exceeds total size {}", offset, total_size);
|
tracing::debug!("Range offset {} exceeds total size {}", offset, total_size);
|
||||||
return Err(Error::other("Range offset exceeds file size"));
|
return Err(Error::InvalidRangeSpec("Range offset exceeds file size".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust length if it extends beyond file end
|
// Adjust length if it extends beyond file end
|
||||||
|
|||||||
@@ -21,21 +21,15 @@ use std::time::Duration;
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// KMS backend types
|
/// KMS backend types
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum KmsBackend {
|
pub enum KmsBackend {
|
||||||
/// Vault backend (recommended for production)
|
/// Vault backend (recommended for production)
|
||||||
Vault,
|
Vault,
|
||||||
/// Local file-based backend for development and testing only
|
/// Local file-based backend for development and testing only
|
||||||
|
#[default]
|
||||||
Local,
|
Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for KmsBackend {
|
|
||||||
fn default() -> Self {
|
|
||||||
// Default to Local backend since Vault requires configuration
|
|
||||||
Self::Local
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main KMS configuration
|
/// Main KMS configuration
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct KmsConfig {
|
pub struct KmsConfig {
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ impl From<StorageError> for ApiError {
|
|||||||
StorageError::InvalidPart(_, _, _) => S3ErrorCode::InvalidPart,
|
StorageError::InvalidPart(_, _, _) => S3ErrorCode::InvalidPart,
|
||||||
StorageError::EntityTooSmall(_, _, _) => S3ErrorCode::EntityTooSmall,
|
StorageError::EntityTooSmall(_, _, _) => S3ErrorCode::EntityTooSmall,
|
||||||
StorageError::PreconditionFailed => S3ErrorCode::PreconditionFailed,
|
StorageError::PreconditionFailed => S3ErrorCode::PreconditionFailed,
|
||||||
|
StorageError::InvalidRangeSpec(_) => S3ErrorCode::InvalidRange,
|
||||||
_ => S3ErrorCode::InternalError,
|
_ => S3ErrorCode::InternalError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3202,7 +3202,7 @@ impl S3 for FS {
|
|||||||
|
|
||||||
range_spec
|
range_spec
|
||||||
.get_offset_length(validation_size)
|
.get_offset_length(validation_size)
|
||||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, format!("Invalid range: {e}")))?
|
.map_err(|e| S3Error::with_message(S3ErrorCode::InvalidRange, e.to_string()))?
|
||||||
} else {
|
} else {
|
||||||
(0, src_info.size)
|
(0, src_info.size)
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user