fmt and improve import

This commit is contained in:
houseme
2026-06-28 11:41:11 +08:00
parent 4c83669c30
commit 143491e0af
18 changed files with 269 additions and 149 deletions
@@ -617,7 +617,10 @@ impl ReplicationResyncer {
} else { } else {
let state = TargetReplicationResyncStatus::new(); let state = TargetReplicationResyncStatus::new();
bucket_status.targets_map.insert(opts.arn.clone(), state); bucket_status.targets_map.insert(opts.arn.clone(), state);
bucket_status.targets_map.get_mut(&opts.arn).expect("ARN should be in targets map") bucket_status
.targets_map
.get_mut(&opts.arn)
.expect("ARN should be in targets map")
}; };
if !resync_state_accepts_update(state, &opts) { if !resync_state_accepts_update(state, &opts) {
@@ -678,7 +681,10 @@ impl ReplicationResyncer {
} else { } else {
let state = TargetReplicationResyncStatus::new(); let state = TargetReplicationResyncStatus::new();
bucket_status.targets_map.insert(opts.arn.clone(), state); bucket_status.targets_map.insert(opts.arn.clone(), state);
bucket_status.targets_map.get_mut(&opts.arn).expect("ARN should be in targets map") bucket_status
.targets_map
.get_mut(&opts.arn)
.expect("ARN should be in targets map")
}; };
if !resync_state_accepts_update(state, &opts) { if !resync_state_accepts_update(state, &opts) {
@@ -2710,7 +2716,13 @@ async fn replicate_delete_to_target(dobj: &DeletedObjectReplicationInfo, tgt_cli
&& !tgt_client.reset_id.is_empty() && !tgt_client.reset_id.is_empty()
&& dobj.op_type == ReplicationType::ExistingObject && dobj.op_type == ReplicationType::ExistingObject
{ {
rinfo.resync_timestamp = format!("{};{}", OffsetDateTime::now_utc().format(&Rfc3339).unwrap_or_else(|_| "invalid-time".to_string()), tgt_client.reset_id); rinfo.resync_timestamp = format!(
"{};{}",
OffsetDateTime::now_utc()
.format(&Rfc3339)
.unwrap_or_else(|_| "invalid-time".to_string()),
tgt_client.reset_id
);
} }
rinfo rinfo
@@ -3473,8 +3485,13 @@ impl ReplicateObjectInfoExt for ReplicateObjectInfo {
&& self.op_type == ReplicationType::ExistingObject && self.op_type == ReplicationType::ExistingObject
&& !tgt_client.reset_id.is_empty() && !tgt_client.reset_id.is_empty()
{ {
rinfo.resync_timestamp = rinfo.resync_timestamp = format!(
format!("{};{}", OffsetDateTime::now_utc().format(&Rfc3339).unwrap_or_else(|_| "invalid-time".to_string()), tgt_client.reset_id); "{};{}",
OffsetDateTime::now_utc()
.format(&Rfc3339)
.unwrap_or_else(|_| "invalid-time".to_string()),
tgt_client.reset_id
);
rinfo.replication_resynced = true; rinfo.replication_resynced = true;
} }
@@ -133,7 +133,8 @@ struct ObjectAttributePart {
impl ObjectAttributes { impl ObjectAttributes {
pub async fn parse_response(&mut self, h: &HeaderMap, body_vec: Vec<u8>) -> Result<(), std::io::Error> { pub async fn parse_response(&mut self, h: &HeaderMap, body_vec: Vec<u8>) -> Result<(), std::io::Error> {
let last_modified = h.get("Last-Modified") let last_modified = h
.get("Last-Modified")
.ok_or_else(|| std::io::Error::other("missing Last-Modified header"))? .ok_or_else(|| std::io::Error::other("missing Last-Modified header"))?
.to_str() .to_str()
.map_err(|e| std::io::Error::other(format!("invalid Last-Modified header: {e}")))?; .map_err(|e| std::io::Error::other(format!("invalid Last-Modified header: {e}")))?;
@@ -141,14 +142,14 @@ impl ObjectAttributes {
.map_err(|e| std::io::Error::other(format!("invalid Last-Modified date: {e}")))?; .map_err(|e| std::io::Error::other(format!("invalid Last-Modified date: {e}")))?;
self.last_modified = mod_time; self.last_modified = mod_time;
let version_id = h.get(X_AMZ_VERSION_ID) let version_id = h
.get(X_AMZ_VERSION_ID)
.ok_or_else(|| std::io::Error::other("missing version ID header"))? .ok_or_else(|| std::io::Error::other("missing version ID header"))?
.to_str() .to_str()
.map_err(|e| std::io::Error::other(format!("invalid version ID header: {e}")))?; .map_err(|e| std::io::Error::other(format!("invalid version ID header: {e}")))?;
self.version_id = version_id.to_string(); self.version_id = version_id.to_string();
let body_str = String::from_utf8(body_vec) let body_str = String::from_utf8(body_vec).map_err(|e| std::io::Error::other(format!("invalid UTF-8 body: {e}")))?;
.map_err(|e| std::io::Error::other(format!("invalid UTF-8 body: {e}")))?;
let mut response = match quick_xml::de::from_str::<ObjectAttributesResponse>(&body_str) { let mut response = match quick_xml::de::from_str::<ObjectAttributesResponse>(&body_str) {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
@@ -175,7 +176,10 @@ impl TransitionClient {
} }
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
headers.insert(X_AMZ_OBJECT_ATTRIBUTES, HeaderValue::from_str(GET_OBJECT_ATTRIBUTES_TAGS).expect("valid header value")); headers.insert(
X_AMZ_OBJECT_ATTRIBUTES,
HeaderValue::from_str(GET_OBJECT_ATTRIBUTES_TAGS).expect("valid header value"),
);
if opts.part_number_marker > 0 { if opts.part_number_marker > 0 {
headers.insert( headers.insert(
@@ -185,7 +189,10 @@ impl TransitionClient {
} }
if opts.max_parts > 0 { if opts.max_parts > 0 {
headers.insert(X_AMZ_MAX_PARTS, HeaderValue::from_str(&opts.max_parts.to_string()).expect("valid header value")); headers.insert(
X_AMZ_MAX_PARTS,
HeaderValue::from_str(&opts.max_parts.to_string()).expect("valid header value"),
);
} else { } else {
headers.insert( headers.insert(
X_AMZ_MAX_PARTS, X_AMZ_MAX_PARTS,
@@ -222,9 +229,7 @@ impl TransitionClient {
let resp_status = resp.status(); let resp_status = resp.status();
let h = resp.headers().clone(); let h = resp.headers().clone();
let has_etag = h.get("ETag") let has_etag = h.get("ETag").and_then(|v| v.to_str().ok()).unwrap_or("");
.and_then(|v| v.to_str().ok())
.unwrap_or("");
if !has_etag.is_empty() { if !has_etag.is_empty() {
return Err(std::io::Error::other( return Err(std::io::Error::other(
"get_object_attributes is not supported by the current endpoint version", "get_object_attributes is not supported by the current endpoint version",
@@ -241,8 +246,8 @@ impl TransitionClient {
} }
if resp_status != http::StatusCode::OK { if resp_status != http::StatusCode::OK {
let err_body = String::from_utf8(body_vec) let err_body =
.map_err(|e| std::io::Error::other(format!("invalid UTF-8 error body: {e}")))?; String::from_utf8(body_vec).map_err(|e| std::io::Error::other(format!("invalid UTF-8 error body: {e}")))?;
let mut er = match quick_xml::de::from_str::<AccessControlPolicy>(&err_body) { let mut er = match quick_xml::de::from_str::<AccessControlPolicy>(&err_body) {
Ok(result) => result, Ok(result) => result,
Err(err) => { Err(err) => {
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Static ECStore layout boundaries. //! Static ECStore layout boundaries.
//! //!
//! This module owns read-only layout descriptors used to keep static set //! This module owns read-only layout descriptors used to keep static set
+27 -21
View File
@@ -1,3 +1,17 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::*; use super::*;
#[cfg(feature = "rio-v2")] #[cfg(feature = "rio-v2")]
use aes_gcm::aead::Payload; use aes_gcm::aead::Payload;
@@ -122,7 +136,7 @@ fn restore_request_active(opts: &ObjectOptions) -> bool {
restore.type_.is_some() || restore.days.is_some() || restore.output_location.is_some() || restore.select_parameters.is_some() restore.type_.is_some() || restore.days.is_some() || restore.output_location.is_some() || restore.select_parameters.is_some()
} }
fn decode_compression_index(index: Option<&bytes::Bytes>) -> Option<Index> { fn decode_compression_index(index: Option<&Bytes>) -> Option<Index> {
crate::io_support::rio::decode_compression_index_bytes(index?) crate::io_support::rio::decode_compression_index_bytes(index?)
} }
@@ -833,11 +847,7 @@ impl<R: AsyncRead + Unpin + Send + Sync + 'static> RangedDecompressReader<R> {
} }
impl<R: AsyncRead + Unpin + Send + Sync + 'static> AsyncRead for RangedDecompressReader<R> { impl<R: AsyncRead + Unpin + Send + Sync + 'static> AsyncRead for RangedDecompressReader<R> {
fn poll_read( fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
use std::pin::Pin; use std::pin::Pin;
use std::task::Poll; use std::task::Poll;
use tokio::io::ReadBuf; use tokio::io::ReadBuf;
@@ -985,11 +995,7 @@ impl<R: AsyncRead + Unpin + Send + 'static> StreamConsumer<R> {
} }
impl<R: AsyncRead + Unpin + Send + 'static> AsyncRead for StreamConsumer<R> { impl<R: AsyncRead + Unpin + Send + 'static> AsyncRead for StreamConsumer<R> {
fn poll_read( fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll<std::io::Result<()>> {
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
use std::pin::Pin; use std::pin::Pin;
use std::task::Poll; use std::task::Poll;
@@ -1032,7 +1038,7 @@ fn encrypted_plaintext_size(oi: &ObjectInfo, is_multipart: bool, is_compressed:
oi.decrypted_size().map_err(Into::into) oi.decrypted_size().map_err(Into::into)
} }
fn is_multipart_encrypted_object(parts: &[rustfs_filemeta::ObjectPartInfo], etag: Option<&str>) -> bool { fn is_multipart_encrypted_object(parts: &[ObjectPartInfo], etag: Option<&str>) -> bool {
if parts.len() > 1 { if parts.len() > 1 {
return true; return true;
} }
@@ -1040,13 +1046,13 @@ fn is_multipart_encrypted_object(parts: &[rustfs_filemeta::ObjectPartInfo], etag
etag.map(|etag| etag.trim_matches('"').len() != 32).unwrap_or(false) etag.map(|etag| etag.trim_matches('"').len() != 32).unwrap_or(false)
} }
fn multipart_plaintext_size(parts: &[rustfs_filemeta::ObjectPartInfo], fallback: i64) -> i64 { fn multipart_plaintext_size(parts: &[ObjectPartInfo], fallback: i64) -> i64 {
let total: i64 = parts.iter().map(part_plaintext_size).sum(); let total: i64 = parts.iter().map(part_plaintext_size).sum();
if total > 0 { total } else { fallback } if total > 0 { total } else { fallback }
} }
fn multipart_part_numbers(parts: &[rustfs_filemeta::ObjectPartInfo]) -> Vec<usize> { fn multipart_part_numbers(parts: &[ObjectPartInfo]) -> Vec<usize> {
parts.iter().map(|part| part.number).collect() parts.iter().map(|part| part.number).collect()
} }
@@ -1605,13 +1611,13 @@ mod tests {
fn ssec_headers_from_key(key_bytes: [u8; 32]) -> HeaderMap<HeaderValue> { fn ssec_headers_from_key(key_bytes: [u8; 32]) -> HeaderMap<HeaderValue> {
let mut headers = HeaderMap::new(); let mut headers = HeaderMap::new();
headers.insert(rustfs_utils::http::SSEC_ALGORITHM_HEADER, HeaderValue::from_static("AES256")); headers.insert(SSEC_ALGORITHM_HEADER, HeaderValue::from_static("AES256"));
headers.insert( headers.insert(
rustfs_utils::http::SSEC_KEY_HEADER, SSEC_KEY_HEADER,
HeaderValue::from_str(&BASE64_STANDARD.encode(key_bytes)).expect("valid base64 header"), HeaderValue::from_str(&BASE64_STANDARD.encode(key_bytes)).expect("valid base64 header"),
); );
headers.insert( headers.insert(
rustfs_utils::http::SSEC_KEY_MD5_HEADER, SSEC_KEY_MD5_HEADER,
HeaderValue::from_str(&BASE64_STANDARD.encode(md5_bytes(key_bytes))).expect("valid md5 header"), HeaderValue::from_str(&BASE64_STANDARD.encode(md5_bytes(key_bytes))).expect("valid md5 header"),
); );
headers headers
@@ -2616,7 +2622,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_get_object_reader_compressed_range_returns_physical_offset_from_index() { async fn test_get_object_reader_compressed_range_returns_physical_offset_from_index() {
let mut index = crate::io_support::rio::Index::new(); let mut index = Index::new();
index.add(0, 0).unwrap(); index.add(0, 0).unwrap();
index.add(1_048_576, 2_097_152).unwrap(); index.add(1_048_576, 2_097_152).unwrap();
@@ -2670,7 +2676,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_read_plan_compressed_range_tracks_storage_and_visible_offsets() { async fn test_read_plan_compressed_range_tracks_storage_and_visible_offsets() {
let mut index = crate::io_support::rio::Index::new(); let mut index = Index::new();
index.add(0, 0).unwrap(); index.add(0, 0).unwrap();
index.add(1_048_576, 2_097_152).unwrap(); index.add(1_048_576, 2_097_152).unwrap();
@@ -2746,7 +2752,7 @@ mod tests {
#[cfg(feature = "rio-v2")] #[cfg(feature = "rio-v2")]
#[tokio::test] #[tokio::test]
async fn test_read_plan_accepts_minio_headerless_compression_index() { async fn test_read_plan_accepts_minio_headerless_compression_index() {
let mut index = crate::io_support::rio::Index::new(); let mut index = Index::new();
index.add(0, 0).unwrap(); index.add(0, 0).unwrap();
index.add(1_048_576, 2_097_152).unwrap(); index.add(1_048_576, 2_097_152).unwrap();
let headerless_index = crate::io_support::rio::compression_index_storage_bytes(&index); let headerless_index = crate::io_support::rio::compression_index_storage_bytes(&index);
@@ -2800,7 +2806,7 @@ mod tests {
#[cfg(feature = "rio-v2")] #[cfg(feature = "rio-v2")]
#[test] #[test]
fn test_get_compressed_offsets_aligns_encrypted_ranges_to_dare_packages() { fn test_get_compressed_offsets_aligns_encrypted_ranges_to_dare_packages() {
let mut index = crate::io_support::rio::Index::new(); let mut index = Index::new();
index.add(0, 0).unwrap(); index.add(0, 0).unwrap();
index.add(200_000, 2_097_152).unwrap(); index.add(200_000, 2_097_152).unwrap();
let stored_index = crate::io_support::rio::compression_index_storage_bytes(&index); let stored_index = crate::io_support::rio::compression_index_storage_bytes(&index);
+23 -9
View File
@@ -1,3 +1,17 @@
// Copyright 2024 RustFS Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::*; use super::*;
use crate::storage_api_contracts::{ use crate::storage_api_contracts::{
list::VersionMarker, list::VersionMarker,
@@ -354,14 +368,14 @@ impl ObjectInfo {
// Parse expires from metadata (HTTP date format RFC 7231 or ISO 8601) // Parse expires from metadata (HTTP date format RFC 7231 or ISO 8601)
let expires = fi.metadata.get("expires").and_then(|s| { let expires = fi.metadata.get("expires").and_then(|s| {
// Try parsing as ISO 8601 first // Try parsing as ISO 8601 first
time::OffsetDateTime::parse(s, &time::format_description::well_known::Iso8601::DEFAULT) OffsetDateTime::parse(s, &time::format_description::well_known::Iso8601::DEFAULT)
.or_else(|_| { .or_else(|_| {
// Try RFC 2822 format // Try RFC 2822 format
time::OffsetDateTime::parse(s, &time::format_description::well_known::Rfc2822) OffsetDateTime::parse(s, &time::format_description::well_known::Rfc2822)
}) })
.or_else(|_| { .or_else(|_| {
// Try RFC 3339 format // Try RFC 3339 format
time::OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339) OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
}) })
.ok() .ok()
}); });
@@ -775,7 +789,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn versions_listing_applies_version_marker_only_to_first_entry() { async fn versions_listing_applies_version_marker_only_to_first_entry() {
let metadata = rustfs_filemeta::test_data::create_real_xlmeta().expect("test metadata should be valid"); let metadata = rustfs_filemeta::test_data::create_real_xlmeta().expect("test metadata should be valid");
let entries = rustfs_filemeta::MetaCacheEntriesSorted { let entries = MetaCacheEntriesSorted {
o: rustfs_filemeta::MetaCacheEntries(vec![ o: rustfs_filemeta::MetaCacheEntries(vec![
Some(rustfs_filemeta::MetaCacheEntry { Some(rustfs_filemeta::MetaCacheEntry {
name: "obj-a".to_owned(), name: "obj-a".to_owned(),
@@ -878,7 +892,7 @@ mod tests {
#[test] #[test]
fn from_file_info_preserves_replication_decision() { fn from_file_info_preserves_replication_decision() {
let fi = rustfs_filemeta::FileInfo { let fi = FileInfo {
replication_state_internal: Some(ReplicationState { replication_state_internal: Some(ReplicationState {
replicate_decision_str: "arn=true;false;arn:replication::1:dest;rule-id".to_string(), replicate_decision_str: "arn=true;false;arn:replication::1:dest;rule-id".to_string(),
..Default::default() ..Default::default()
@@ -904,11 +918,11 @@ mod tests {
actual_size: 0, actual_size: 0,
user_defined: Arc::new(user_defined), user_defined: Arc::new(user_defined),
parts: Arc::new(vec![ parts: Arc::new(vec![
rustfs_filemeta::ObjectPartInfo { ObjectPartInfo {
actual_size: 4, actual_size: 4,
..Default::default() ..Default::default()
}, },
rustfs_filemeta::ObjectPartInfo { ObjectPartInfo {
actual_size: 5, actual_size: 5,
..Default::default() ..Default::default()
}, },
@@ -1016,13 +1030,13 @@ mod tests {
user_defined: Arc::new(ud), user_defined: Arc::new(ud),
user_tags: Arc::new("env=prod&team=storage".to_string()), user_tags: Arc::new("env=prod&team=storage".to_string()),
parts: Arc::new(vec![ parts: Arc::new(vec![
rustfs_filemeta::ObjectPartInfo { ObjectPartInfo {
number: 1, number: 1,
size: 1024, size: 1024,
actual_size: 1024, actual_size: 1024,
..Default::default() ..Default::default()
}, },
rustfs_filemeta::ObjectPartInfo { ObjectPartInfo {
number: 2, number: 2,
size: 512, size: 512,
actual_size: 512, actual_size: 512,
+2 -4
View File
@@ -338,9 +338,7 @@ pub fn shutdown_background_services() {
/// * `Ok(())` if successful /// * `Ok(())` if successful
/// * `Err(Arc<dyn LockClient>)` if setting fails (client already set) /// * `Err(Arc<dyn LockClient>)` if setting fails (client already set)
/// ///
pub fn set_global_lock_client( pub fn set_global_lock_client(client: Arc<dyn LockClient>) -> Result<(), Arc<dyn LockClient>> {
client: Arc<dyn rustfs_lock::client::LockClient>,
) -> Result<(), Arc<dyn rustfs_lock::client::LockClient>> {
GLOBAL_LOCAL_LOCK_CLIENT.set(client) GLOBAL_LOCAL_LOCK_CLIENT.set(client)
} }
@@ -349,7 +347,7 @@ pub fn set_global_lock_client(
/// # Returns /// # Returns
/// * `Option<Arc<dyn LockClient>>` - The global lock client, if set /// * `Option<Arc<dyn LockClient>>` - The global lock client, if set
/// ///
pub fn get_global_lock_client() -> Option<Arc<dyn rustfs_lock::client::LockClient>> { pub fn get_global_lock_client() -> Option<Arc<dyn LockClient>> {
GLOBAL_LOCAL_LOCK_CLIENT.get().cloned() GLOBAL_LOCAL_LOCK_CLIENT.get().cloned()
} }
+2 -2
View File
@@ -237,9 +237,9 @@ pub(crate) fn storage_class_parity(storage_class: Option<&str>) -> Option<usize>
pub(crate) fn backend_storage_class_parities(default_standard_parity: usize) -> (Option<usize>, Option<usize>) { pub(crate) fn backend_storage_class_parities(default_standard_parity: usize) -> (Option<usize>, Option<usize>) {
if let Some(sc) = get_global_storage_class() { if let Some(sc) = get_global_storage_class() {
let standard = sc let standard = sc
.get_parity_for_sc(crate::config::storageclass::CLASS_STANDARD) .get_parity_for_sc(storageclass::CLASS_STANDARD)
.or(Some(default_standard_parity)); .or(Some(default_standard_parity));
let reduced_redundancy = sc.get_parity_for_sc(crate::config::storageclass::RRS); let reduced_redundancy = sc.get_parity_for_sc(storageclass::RRS);
(standard, reduced_redundancy) (standard, reduced_redundancy)
} else { } else {
(Some(default_standard_parity), None) (Some(default_standard_parity), None)
+5 -5
View File
@@ -129,14 +129,14 @@ impl SetDisks {
let erasure = if !latest_meta.deleted && !latest_meta.is_remote() { let erasure = if !latest_meta.deleted && !latest_meta.is_remote() {
// Initialize erasure coding; use legacy mode for old-version files // Initialize erasure coding; use legacy mode for old-version files
crate::erasure::coding::Erasure::new_with_options( coding::Erasure::new_with_options(
latest_meta.erasure.data_blocks, latest_meta.erasure.data_blocks,
latest_meta.erasure.parity_blocks, latest_meta.erasure.parity_blocks,
latest_meta.erasure.block_size, latest_meta.erasure.block_size,
latest_meta.uses_legacy_checksum, latest_meta.uses_legacy_checksum,
) )
} else { } else {
crate::erasure::coding::Erasure::default() coding::Erasure::default()
}; };
result.object_size = result.object_size =
@@ -385,9 +385,9 @@ impl SetDisks {
if let (Some(disk), Some(metadata)) = (disk, &copy_parts_metadata[index]) { if let (Some(disk), Some(metadata)) = (disk, &copy_parts_metadata[index]) {
let checksum_info = metadata.erasure.get_checksum_info(part.number); let checksum_info = metadata.erasure.get_checksum_info(part.number);
let checksum_algo = if metadata.uses_legacy_checksum let checksum_algo = if metadata.uses_legacy_checksum
&& checksum_info.algorithm == rustfs_utils::HashAlgorithm::HighwayHash256S && checksum_info.algorithm == HashAlgorithm::HighwayHash256S
{ {
rustfs_utils::HashAlgorithm::HighwayHash256SLegacy HashAlgorithm::HighwayHash256SLegacy
} else { } else {
checksum_info.algorithm checksum_info.algorithm
}; };
@@ -498,7 +498,7 @@ impl SetDisks {
// parts_metadata[index].data = Some(w.inline_data().to_vec()); // parts_metadata[index].data = Some(w.inline_data().to_vec());
// } // }
parts_metadata[index].data = parts_metadata[index].data =
Some(writer.into_inline_data().map(bytes::Bytes::from).unwrap_or_default()); Some(writer.into_inline_data().map(Bytes::from).unwrap_or_default());
} }
parts_metadata[index].set_inline_data(); parts_metadata[index].set_inline_data();
} else { } else {
+6 -6
View File
@@ -131,7 +131,7 @@ impl SetDisks {
fn reprobe_runtime_candidates_once(&self, disks: &[DiskStore]) { fn reprobe_runtime_candidates_once(&self, disks: &[DiskStore]) {
for disk in disks { for disk in disks {
if disk.runtime_state() != crate::disk::health_state::RuntimeDriveHealthState::Online { if disk.runtime_state() != disk::health_state::RuntimeDriveHealthState::Online {
disk.reset_health_for_store_init_retry(); disk.reset_health_for_store_init_retry();
} }
} }
@@ -536,15 +536,15 @@ mod tests {
all_disks[1] all_disks[1]
.as_ref() .as_ref()
.expect("disk 1 should exist") .expect("disk 1 should exist")
.force_runtime_state_for_test(crate::disk::health_state::RuntimeDriveHealthState::Suspect); .force_runtime_state_for_test(disk::health_state::RuntimeDriveHealthState::Suspect);
all_disks[2] all_disks[2]
.as_ref() .as_ref()
.expect("disk 2 should exist") .expect("disk 2 should exist")
.force_runtime_state_for_test(crate::disk::health_state::RuntimeDriveHealthState::Returning); .force_runtime_state_for_test(disk::health_state::RuntimeDriveHealthState::Returning);
all_disks[3] all_disks[3]
.as_ref() .as_ref()
.expect("disk 3 should exist") .expect("disk 3 should exist")
.force_runtime_state_for_test(crate::disk::health_state::RuntimeDriveHealthState::Offline); .force_runtime_state_for_test(disk::health_state::RuntimeDriveHealthState::Offline);
let snapshot = set_disks.drive_membership_snapshot().await; let snapshot = set_disks.drive_membership_snapshot().await;
assert_eq!(snapshot.online.len(), 1); assert_eq!(snapshot.online.len(), 1);
@@ -563,7 +563,7 @@ mod tests {
assert!( assert!(
online_disks online_disks
.iter() .iter()
.all(|disk| { disk.runtime_state() != crate::disk::health_state::RuntimeDriveHealthState::Offline }), .all(|disk| { disk.runtime_state() != disk::health_state::RuntimeDriveHealthState::Offline }),
"offline disks should be filtered by membership snapshot" "offline disks should be filtered by membership snapshot"
); );
@@ -601,7 +601,7 @@ mod tests {
let all_disks = set_disks.get_disks_internal().await; let all_disks = set_disks.get_disks_internal().await;
for disk in all_disks.iter().flatten() { for disk in all_disks.iter().flatten() {
disk.force_runtime_state_for_test(crate::disk::health_state::RuntimeDriveHealthState::Returning); disk.force_runtime_state_for_test(disk::health_state::RuntimeDriveHealthState::Returning);
} }
let (online_disks, infos, healing) = set_disks.get_online_disks_with_healing_and_info(false).await; let (online_disks, infos, healing) = set_disks.get_online_disks_with_healing_and_info(false).await;
+3 -7
View File
@@ -1885,8 +1885,7 @@ impl crate::storage_api_contracts::object::ObjectIO for SetDisks {
let tmp_object = format!("{}/{}/part.1", tmp_dir, fi.data_dir.unwrap()); let tmp_object = format!("{}/{}/part.1", tmp_dir, fi.data_dir.unwrap());
let result: Result<ObjectInfo> = async { let result: Result<ObjectInfo> = async {
let erasure = let erasure = coding::Erasure::new(fi.erasure.data_blocks, fi.erasure.parity_blocks, fi.erasure.block_size);
coding::Erasure::new(fi.erasure.data_blocks, fi.erasure.parity_blocks, fi.erasure.block_size);
let is_inline_buffer = let is_inline_buffer =
runtime_sources::storage_class_should_inline(erasure.shard_file_size(data.size()), opts.versioned); runtime_sources::storage_class_should_inline(erasure.shard_file_size(data.size()), opts.versioned);
@@ -4218,8 +4217,7 @@ impl crate::storage_api_contracts::multipart::MultipartOperations for SetDisks {
let tmp_part = format!("{}x{}", Uuid::new_v4(), OffsetDateTime::now_utc().unix_timestamp()); let tmp_part = format!("{}x{}", Uuid::new_v4(), OffsetDateTime::now_utc().unix_timestamp());
let tmp_part_path = Arc::new(format!("{tmp_part}/{part_suffix}")); let tmp_part_path = Arc::new(format!("{tmp_part}/{part_suffix}"));
let erasure = let erasure = coding::Erasure::new(fi.erasure.data_blocks, fi.erasure.parity_blocks, fi.erasure.block_size);
coding::Erasure::new(fi.erasure.data_blocks, fi.erasure.parity_blocks, fi.erasure.block_size);
let writer_setup_stage_start = rustfs_io_metrics::put_stage_metrics_enabled().then(Instant::now); let writer_setup_stage_start = rustfs_io_metrics::put_stage_metrics_enabled().then(Instant::now);
let mut writers = Vec::with_capacity(shuffle_disks.len()); let mut writers = Vec::with_capacity(shuffle_disks.len());
@@ -5912,9 +5910,7 @@ async fn get_disks_info(disks: &[Option<DiskStore>], eps: &[Endpoint]) -> Vec<ru
let runtime_state = disk.runtime_state(); let runtime_state = disk.runtime_state();
let offline_duration_seconds = disk.offline_duration_secs(); let offline_duration_seconds = disk.offline_duration_secs();
let capacity_snapshot = disk.last_capacity_snapshot(); let capacity_snapshot = disk.last_capacity_snapshot();
if runtime_state.should_probe_for_admin() if runtime_state.should_probe_for_admin() || runtime_state == disk::health_state::RuntimeDriveHealthState::Suspect {
|| runtime_state == disk::health_state::RuntimeDriveHealthState::Suspect
{
match disk.disk_info(&DiskInfoOptions::default()).await { match disk.disk_info(&DiskInfoOptions::default()).await {
Ok(res) => { Ok(res) => {
disk.record_capacity_probe(res.total, res.used, res.free); disk.record_capacity_probe(res.total, res.used, res.free);
+2 -2
View File
@@ -221,7 +221,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn collect_list_parts_results_fails_early_when_quorum_is_impossible() { async fn collect_list_parts_results_fails_early_when_quorum_is_impossible() {
let started = std::time::Instant::now(); let started = Instant::now();
let tasks: Vec<_> = vec![ let tasks: Vec<_> = vec![
(10_u64, Err(DiskError::DiskNotFound)), (10_u64, Err(DiskError::DiskNotFound)),
(15, Err(DiskError::DiskNotFound)), (15, Err(DiskError::DiskNotFound)),
@@ -285,7 +285,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn collect_list_parts_results_fails_early_when_file_not_found_fallback_is_impossible() { async fn collect_list_parts_results_fails_early_when_file_not_found_fallback_is_impossible() {
let started = std::time::Instant::now(); let started = Instant::now();
let tasks: Vec<_> = vec![ let tasks: Vec<_> = vec![
(5_u64, Err(DiskError::FileNotFound)), (5_u64, Err(DiskError::FileNotFound)),
(10, Err(DiskError::FileCorrupt)), (10, Err(DiskError::FileCorrupt)),
+37 -50
View File
@@ -1936,7 +1936,7 @@ impl SetDisks {
object, offset, length, end_offset, part_index, last_part_index, last_part_relative_offset, "Multipart read bounds" object, offset, length, end_offset, part_index, last_part_index, last_part_relative_offset, "Multipart read bounds"
); );
let erasure = crate::erasure::coding::Erasure::new_with_options( let erasure = coding::Erasure::new_with_options(
fi.erasure.data_blocks, fi.erasure.data_blocks,
fi.erasure.parity_blocks, fi.erasure.parity_blocks,
fi.erasure.block_size, fi.erasure.block_size,
@@ -1987,12 +1987,11 @@ impl SetDisks {
); );
let checksum_info = fi.erasure.get_checksum_info(part_number); let checksum_info = fi.erasure.get_checksum_info(part_number);
let checksum_algo = let checksum_algo = if fi.uses_legacy_checksum && checksum_info.algorithm == HashAlgorithm::HighwayHash256S {
if fi.uses_legacy_checksum && checksum_info.algorithm == rustfs_utils::HashAlgorithm::HighwayHash256S { HashAlgorithm::HighwayHash256SLegacy
rustfs_utils::HashAlgorithm::HighwayHash256SLegacy } else {
} else { checksum_info.algorithm
checksum_info.algorithm };
};
let read_length = till_offset.saturating_sub(read_offset); let read_length = till_offset.saturating_sub(read_offset);
// Read zero-copy configuration from environment variable // Read zero-copy configuration from environment variable
@@ -2278,7 +2277,7 @@ impl SetDisks {
) -> Result<GetCodecStreamingReaderBuildOutcome> { ) -> Result<GetCodecStreamingReaderBuildOutcome> {
let (disks, files) = Self::shuffle_disks_and_parts_metadata_by_index(disks, files, fi); let (disks, files) = Self::shuffle_disks_and_parts_metadata_by_index(disks, files, fi);
let erasure = crate::erasure::coding::Erasure::new_with_options( let erasure = coding::Erasure::new_with_options(
fi.erasure.data_blocks, fi.erasure.data_blocks,
fi.erasure.parity_blocks, fi.erasure.parity_blocks,
fi.erasure.block_size, fi.erasure.block_size,
@@ -2362,7 +2361,7 @@ impl SetDisks {
fi: &FileInfo, fi: &FileInfo,
files: &[FileInfo], files: &[FileInfo],
disks: &[Option<DiskStore>], disks: &[Option<DiskStore>],
erasure: &crate::erasure::coding::Erasure, erasure: &coding::Erasure,
part_number: usize, part_number: usize,
part_offset: usize, part_offset: usize,
part_length: usize, part_length: usize,
@@ -2373,9 +2372,8 @@ impl SetDisks {
return Err(Error::other("codec streaming reader part length exceeds part size")); return Err(Error::other("codec streaming reader part length exceeds part size"));
} }
let checksum_info = fi.erasure.get_checksum_info(part_number); let checksum_info = fi.erasure.get_checksum_info(part_number);
let checksum_algo = if fi.uses_legacy_checksum && checksum_info.algorithm == rustfs_utils::HashAlgorithm::HighwayHash256S let checksum_algo = if fi.uses_legacy_checksum && checksum_info.algorithm == HashAlgorithm::HighwayHash256S {
{ HashAlgorithm::HighwayHash256SLegacy
rustfs_utils::HashAlgorithm::HighwayHash256SLegacy
} else { } else {
checksum_info.algorithm checksum_info.algorithm
}; };
@@ -2427,24 +2425,19 @@ impl SetDisks {
} }
let readers = reader_setup.readers; let readers = reader_setup.readers;
let source = let source = coding::decode::ParallelReader::new_with_metrics_path_read_costs_and_reconstruction_verification(
crate::erasure::coding::decode::ParallelReader::new_with_metrics_path_read_costs_and_reconstruction_verification( readers,
readers, erasure.clone(),
erasure.clone(), part_offset,
part_offset, part_size,
part_size, Some(metrics_path),
Some(metrics_path), read_costs,
read_costs, );
);
let engine = build_get_codec_streaming_decode_engine(erasure.clone())?; let engine = build_get_codec_streaming_decode_engine(erasure.clone())?;
let reader = crate::erasure::coding::decode_reader::ErasureDecodeReader::new_with_metrics_path( let reader =
source, coding::decode_reader::ErasureDecodeReader::new_with_metrics_path(source, engine, part_length, metrics_path)?;
engine,
part_length,
metrics_path,
)?;
Ok(GetCodecStreamingReaderBuildOutcome::Reader(Box::new( Ok(GetCodecStreamingReaderBuildOutcome::Reader(Box::new(
crate::erasure::coding::decode_reader::SyncErasureDecodeReader::new_with_metrics_path(reader, metrics_path), coding::decode_reader::SyncErasureDecodeReader::new_with_metrics_path(reader, metrics_path),
))) )))
} }
} }
@@ -2627,7 +2620,7 @@ mod metadata_cache_tests {
"read-repair submission should not wait for admission response" "read-repair submission should not wait for admission response"
); );
tokio::time::timeout(Duration::from_secs(1), async { timeout(Duration::from_secs(1), async {
while SLOW_READ_REPAIR_SUBMITTER_CALLS.load(Ordering::Relaxed) == 0 { while SLOW_READ_REPAIR_SUBMITTER_CALLS.load(Ordering::Relaxed) == 0 {
tokio::time::sleep(Duration::from_millis(5)).await; tokio::time::sleep(Duration::from_millis(5)).await;
} }
@@ -2656,7 +2649,7 @@ mod metadata_cache_tests {
) )
.await; .await;
let released_key = tokio::time::timeout(Duration::from_secs(1), async { let released_key = timeout(Duration::from_secs(1), async {
loop { loop {
if let Some(key) = reserve_read_repair_heal(&bucket, "object", None, 0, 0).await { if let Some(key) = reserve_read_repair_heal(&bucket, "object", None, 0, 0).await {
break key; break key;
@@ -3707,7 +3700,7 @@ mod tests {
); );
let mut remote_fi = fi; let mut remote_fi = fi;
remote_fi.transition_status = crate::bucket::lifecycle::lifecycle::TRANSITION_COMPLETE.to_string(); remote_fi.transition_status = TRANSITION_COMPLETE.to_string();
let remote = codec_streaming_test_object_info(&remote_fi); let remote = codec_streaming_test_object_info(&remote_fi);
assert_eq!( assert_eq!(
codec_streaming_reader_gate_for_test(&None, &remote, &remote_fi, true).decision, codec_streaming_reader_gate_for_test(&None, &remote, &remote_fi, true).decision,
@@ -3831,7 +3824,7 @@ mod tests {
#[test] #[test]
fn codec_streaming_decode_engine_builder_selects_rustfs() { fn codec_streaming_decode_engine_builder_selects_rustfs() {
temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, Some(GET_CODEC_STREAMING_ENGINE_RUSTFS), || { temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, Some(GET_CODEC_STREAMING_ENGINE_RUSTFS), || {
let erasure = crate::erasure::coding::Erasure::new(4, 2, 32); let erasure = coding::Erasure::new(4, 2, 32);
let engine = build_get_codec_streaming_decode_engine(erasure).expect("engine should be built"); let engine = build_get_codec_streaming_decode_engine(erasure).expect("engine should be built");
assert!(matches!(engine, CodecStreamingDecodeEngine::Rustfs(_))); assert!(matches!(engine, CodecStreamingDecodeEngine::Rustfs(_)));
@@ -3841,17 +3834,11 @@ mod tests {
#[test] #[test]
fn codec_streaming_metrics_path_matches_selected_engine() { fn codec_streaming_metrics_path_matches_selected_engine() {
temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, None::<&str>, || { temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, None::<&str>, || {
assert_eq!( assert_eq!(get_codec_streaming_metrics_path(), GET_OBJECT_PATH_CODEC_STREAMING_LEGACY_ENGINE);
get_codec_streaming_metrics_path(),
crate::diagnostics::get::GET_OBJECT_PATH_CODEC_STREAMING_LEGACY_ENGINE
);
}); });
temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, Some(GET_CODEC_STREAMING_ENGINE_RUSTFS), || { temp_env::with_var(ENV_RUSTFS_GET_CODEC_STREAMING_ENGINE, Some(GET_CODEC_STREAMING_ENGINE_RUSTFS), || {
assert_eq!( assert_eq!(get_codec_streaming_metrics_path(), GET_OBJECT_PATH_CODEC_STREAMING_RUSTFS_ENGINE);
get_codec_streaming_metrics_path(),
crate::diagnostics::get::GET_OBJECT_PATH_CODEC_STREAMING_RUSTFS_ENGINE
);
}); });
} }
@@ -4067,7 +4054,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn collect_read_multiple_results_fails_early_when_quorum_is_impossible() { async fn collect_read_multiple_results_fails_early_when_quorum_is_impossible() {
let started = std::time::Instant::now(); let started = Instant::now();
let resp = ReadMultipleResp { let resp = ReadMultipleResp {
bucket: "bucket".to_string(), bucket: "bucket".to_string(),
prefix: "prefix".to_string(), prefix: "prefix".to_string(),
@@ -4085,14 +4072,14 @@ mod tests {
] ]
.into_iter() .into_iter()
.map(|(delay_ms, outcome)| async move { .map(|(delay_ms, outcome)| async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
outcome outcome
}) })
.collect(); .collect();
let result = collect_read_multiple_results(tasks, 2).await; let result = collect_read_multiple_results(tasks, 2).await;
assert!(result.is_err(), "quorum should become impossible before slow tail completes"); assert!(result.is_err(), "quorum should become impossible before slow tail completes");
assert!(started.elapsed() < std::time::Duration::from_millis(120)); assert!(started.elapsed() < Duration::from_millis(120));
} }
#[tokio::test] #[tokio::test]
@@ -4114,7 +4101,7 @@ mod tests {
] ]
.into_iter() .into_iter()
.map(|(delay_ms, outcome)| async move { .map(|(delay_ms, outcome)| async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
outcome outcome
}) })
.collect(); .collect();
@@ -4142,7 +4129,7 @@ mod tests {
.map(|(delay_ms, should_panic)| { .map(|(delay_ms, should_panic)| {
let resp = resp.clone(); let resp = resp.clone();
async move { async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
if should_panic { if should_panic {
panic!("simulated task panic"); panic!("simulated task panic");
} }
@@ -4160,7 +4147,7 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn collect_read_parts_results_fails_early_when_quorum_is_impossible() { async fn collect_read_parts_results_fails_early_when_quorum_is_impossible() {
let started = std::time::Instant::now(); let started = Instant::now();
let part = ObjectPartInfo { let part = ObjectPartInfo {
number: 1, number: 1,
etag: "etag".to_string(), etag: "etag".to_string(),
@@ -4174,14 +4161,14 @@ mod tests {
] ]
.into_iter() .into_iter()
.map(|(delay_ms, outcome)| async move { .map(|(delay_ms, outcome)| async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
outcome outcome
}) })
.collect(); .collect();
let result = collect_read_parts_results(tasks, 2).await; let result = collect_read_parts_results(tasks, 2).await;
assert!(result.is_err(), "quorum should become impossible before slow tail completes"); assert!(result.is_err(), "quorum should become impossible before slow tail completes");
assert!(started.elapsed() < std::time::Duration::from_millis(120)); assert!(started.elapsed() < Duration::from_millis(120));
} }
#[tokio::test] #[tokio::test]
@@ -4199,7 +4186,7 @@ mod tests {
] ]
.into_iter() .into_iter()
.map(|(delay_ms, outcome)| async move { .map(|(delay_ms, outcome)| async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
outcome outcome
}) })
.collect(); .collect();
@@ -4222,7 +4209,7 @@ mod tests {
.map(|(delay_ms, should_panic)| { .map(|(delay_ms, should_panic)| {
let part = part.clone(); let part = part.clone();
async move { async move {
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await; tokio::time::sleep(Duration::from_millis(delay_ms)).await;
if should_panic { if should_panic {
panic!("simulated task panic"); panic!("simulated task panic");
} }
@@ -24,9 +24,7 @@ impl SetDisks {
) -> Result<()> { ) -> Result<()> {
let mut oi = obj_info.clone(); let mut oi = obj_info.clone();
oi.metadata_only = true; oi.metadata_only = true;
Arc::make_mut(&mut oi.user_defined).remove(X_AMZ_RESTORE.as_str()); Arc::make_mut(&mut oi.user_defined).remove(X_AMZ_RESTORE.as_str());
let version_id = oi.version_id.map(|v| v.to_string()); let version_id = oi.version_id.map(|v| v.to_string());
let _obj = self let _obj = self
.copy_object( .copy_object(
+44 -11
View File
@@ -380,7 +380,10 @@ impl Operation for ExportBucketMetadata {
.map_err(|e| s3_error!(InternalError, "failed to finalize export archive: {e}"))?; .map_err(|e| s3_error!(InternalError, "failed to finalize export archive: {e}"))?;
let mut header = HeaderMap::new(); let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/zip".parse().expect("valid header value")); header.insert(CONTENT_TYPE, "application/zip".parse().expect("valid header value"));
header.insert(CONTENT_DISPOSITION, "attachment; filename=bucket-meta.zip".parse().expect("valid header value")); header.insert(
CONTENT_DISPOSITION,
"attachment; filename=bucket-meta.zip".parse().expect("valid header value"),
);
header.insert(CONTENT_LENGTH, zip_bytes.get_ref().len().to_string().parse().expect("valid header value")); header.insert(CONTENT_LENGTH, zip_bytes.get_ref().len().to_string().parse().expect("valid header value"));
Ok(S3Response::with_headers((StatusCode::OK, Body::from(zip_bytes.into_inner())), header)) Ok(S3Response::with_headers((StatusCode::OK, Body::from(zip_bytes.into_inner())), header))
} }
@@ -597,7 +600,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.policy_config_json = content; metadata.policy_config_json = content;
metadata.policy_config_updated_at = update_at; metadata.policy_config_updated_at = update_at;
} }
@@ -617,7 +623,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.notification_config_xml = content; metadata.notification_config_xml = content;
metadata.notification_config_updated_at = update_at; metadata.notification_config_updated_at = update_at;
} }
@@ -638,7 +647,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.lifecycle_config_xml = content; metadata.lifecycle_config_xml = content;
metadata.lifecycle_config_updated_at = update_at; metadata.lifecycle_config_updated_at = update_at;
} }
@@ -659,7 +671,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.encryption_config_xml = content; metadata.encryption_config_xml = content;
metadata.encryption_config_updated_at = update_at; metadata.encryption_config_updated_at = update_at;
} }
@@ -680,7 +695,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.tagging_config_xml = content; metadata.tagging_config_xml = content;
metadata.tagging_config_updated_at = update_at; metadata.tagging_config_updated_at = update_at;
} }
@@ -701,7 +719,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.quota_config_json = content; metadata.quota_config_json = content;
metadata.quota_config_updated_at = update_at; metadata.quota_config_updated_at = update_at;
} }
@@ -722,7 +743,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.object_lock_config_xml = content; metadata.object_lock_config_xml = content;
metadata.object_lock_config_updated_at = update_at; metadata.object_lock_config_updated_at = update_at;
} }
@@ -743,7 +767,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.versioning_config_xml = content; metadata.versioning_config_xml = content;
metadata.versioning_config_updated_at = update_at; metadata.versioning_config_updated_at = update_at;
} }
@@ -764,7 +791,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.replication_config_xml = content; metadata.replication_config_xml = content;
metadata.replication_config_updated_at = update_at; metadata.replication_config_updated_at = update_at;
} }
@@ -785,7 +815,10 @@ impl Operation for ImportBucketMetadata {
continue; continue;
} }
let metadata = match bucket_metadatas.get_mut(bucket_name) { Some(m) => m, None => continue, }; let metadata = match bucket_metadatas.get_mut(bucket_name) {
Some(m) => m,
None => continue,
};
metadata.bucket_targets_config_json = content; metadata.bucket_targets_config_json = content;
metadata.bucket_targets_config_updated_at = update_at; metadata.bucket_targets_config_updated_at = update_at;
} }
+45 -9
View File
@@ -220,31 +220,67 @@ impl Operation for AddTier {
match args.tier_type { match args.tier_type {
TierType::S3 => { TierType::S3 => {
args.name = args.s3.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing S3 configuration"))?.name; args.name = args
.s3
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing S3 configuration"))?
.name;
} }
TierType::RustFS => { TierType::RustFS => {
args.name = args.rustfs.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing RustFS configuration"))?.name; args.name = args
.rustfs
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing RustFS configuration"))?
.name;
} }
TierType::MinIO => { TierType::MinIO => {
args.name = args.minio.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing MinIO configuration"))?.name; args.name = args
.minio
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing MinIO configuration"))?
.name;
} }
TierType::Aliyun => { TierType::Aliyun => {
args.name = args.aliyun.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Aliyun configuration"))?.name; args.name = args
.aliyun
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Aliyun configuration"))?
.name;
} }
TierType::Tencent => { TierType::Tencent => {
args.name = args.tencent.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Tencent configuration"))?.name; args.name = args
.tencent
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Tencent configuration"))?
.name;
} }
TierType::Huaweicloud => { TierType::Huaweicloud => {
args.name = args.huaweicloud.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Huawei Cloud configuration"))?.name; args.name = args
.huaweicloud
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Huawei Cloud configuration"))?
.name;
} }
TierType::Azure => { TierType::Azure => {
args.name = args.azure.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Azure configuration"))?.name; args.name = args
.azure
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing Azure configuration"))?
.name;
} }
TierType::GCS => { TierType::GCS => {
args.name = args.gcs.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing GCS configuration"))?.name; args.name = args
.gcs
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing GCS configuration"))?
.name;
} }
TierType::R2 => { TierType::R2 => {
args.name = args.r2.clone().ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing R2 configuration"))?.name; args.name = args
.r2
.clone()
.ok_or_else(|| S3Error::with_message(S3ErrorCode::InvalidRequest, "missing R2 configuration"))?
.name;
} }
_ => (), _ => (),
} }
+4 -1
View File
@@ -841,7 +841,10 @@ impl Operation for ExportIam {
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?; .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?;
let mut header = HeaderMap::new(); let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/zip".parse().expect("valid header value")); header.insert(CONTENT_TYPE, "application/zip".parse().expect("valid header value"));
header.insert(CONTENT_DISPOSITION, "attachment; filename=iam-assets.zip".parse().expect("valid header value")); header.insert(
CONTENT_DISPOSITION,
"attachment; filename=iam-assets.zip".parse().expect("valid header value"),
);
header.insert(CONTENT_LENGTH, zip_bytes.get_ref().len().to_string().parse().expect("valid header value")); header.insert(CONTENT_LENGTH, zip_bytes.get_ref().len().to_string().parse().expect("valid header value"));
Ok(S3Response::with_headers((StatusCode::OK, Body::from(zip_bytes.into_inner())), header)) Ok(S3Response::with_headers((StatusCode::OK, Body::from(zip_bytes.into_inner())), header))
} }
+1
View File
@@ -3450,6 +3450,7 @@ impl DefaultObjectUsecase {
sse_customer_key_md5, sse_customer_key_md5,
ssekms_key_id, ssekms_key_id,
encryption_applied, encryption_applied,
is_inline_fast_path: _,
} = read_setup; } = read_setup;
let versioning_start = rustfs_io_metrics::get_stage_metrics_enabled().then(std::time::Instant::now); let versioning_start = rustfs_io_metrics::get_stage_metrics_enabled().then(std::time::Instant::now);
+16 -4
View File
@@ -1435,7 +1435,10 @@ where
.unwrap()); .unwrap());
} }
let mut response = Response::builder().status(StatusCode::OK).body(ResBody::default()).expect("valid response body"); let mut response = Response::builder()
.status(StatusCode::OK)
.body(ResBody::default())
.expect("valid response body");
let cors_layer = ConditionalCorsLayer { let cors_layer = ConditionalCorsLayer {
cors_origins: (*cors_origins).clone(), cors_origins: (*cors_origins).clone(),
}; };
@@ -1464,7 +1467,10 @@ where
let cors_allowed = cors_headers.contains_key(cors::response::ACCESS_CONTROL_ALLOW_ORIGIN); let cors_allowed = cors_headers.contains_key(cors::response::ACCESS_CONTROL_ALLOW_ORIGIN);
let status = if cors_allowed { StatusCode::OK } else { StatusCode::FORBIDDEN }; let status = if cors_allowed { StatusCode::OK } else { StatusCode::FORBIDDEN };
let mut response = Response::builder().status(status).body(ResBody::default()).expect("valid response body"); let mut response = Response::builder()
.status(status)
.body(ResBody::default())
.expect("valid response body");
if cors_allowed { if cors_allowed {
for (key, value) in cors_headers.iter() { for (key, value) in cors_headers.iter() {
response.headers_mut().insert(key, value.clone()); response.headers_mut().insert(key, value.clone());
@@ -1474,7 +1480,10 @@ where
} }
// No bucket-level CORS config: fall back to global/default CORS behavior. // No bucket-level CORS config: fall back to global/default CORS behavior.
let mut response = Response::builder().status(StatusCode::OK).body(ResBody::default()).expect("valid response body"); let mut response = Response::builder()
.status(StatusCode::OK)
.body(ResBody::default())
.expect("valid response body");
cors_layer.apply_cors_headers(&request_headers, response.headers_mut()); cors_layer.apply_cors_headers(&request_headers, response.headers_mut());
Ok(response) Ok(response)
}); });
@@ -1482,7 +1491,10 @@ where
let request_headers_clone = request_headers.clone(); let request_headers_clone = request_headers.clone();
return Box::pin(async move { return Box::pin(async move {
let mut response = Response::builder().status(StatusCode::OK).body(ResBody::default()).expect("valid response body"); let mut response = Response::builder()
.status(StatusCode::OK)
.body(ResBody::default())
.expect("valid response body");
let cors_layer = ConditionalCorsLayer { let cors_layer = ConditionalCorsLayer {
cors_origins: (*cors_origins).clone(), cors_origins: (*cors_origins).clone(),
}; };