mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-18 18:46:17 +00:00
feat(storage): add direct chunk GET fast path (#2351)
Signed-off-by: houseme <housemecn@gmail.com> Co-authored-by: heihutu <heihutu@gmail.com> Co-authored-by: cxymds <Cxymds@qq.com>
This commit is contained in:
@@ -16,7 +16,7 @@ use crate::config::{Config, GLOBAL_STORAGE_CLASS, KVS, audit, notify, oidc, stor
|
||||
use crate::disk::{MIGRATING_META_BUCKET, RUSTFS_META_BUCKET};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::global::is_first_cluster_node_local;
|
||||
use crate::store_api::{ObjectInfo, ObjectOptions, PutObjReader, StorageAPI};
|
||||
use crate::store_api::{ChunkNativePutData, ObjectInfo, ObjectOptions, StorageAPI};
|
||||
use http::HeaderMap;
|
||||
use rustfs_config::audit::{AUDIT_MQTT_KEYS, AUDIT_MQTT_SUB_SYS, AUDIT_WEBHOOK_KEYS, AUDIT_WEBHOOK_SUB_SYS};
|
||||
use rustfs_config::notify::{NOTIFY_MQTT_KEYS, NOTIFY_MQTT_SUB_SYS, NOTIFY_WEBHOOK_KEYS, NOTIFY_WEBHOOK_SUB_SYS};
|
||||
@@ -128,10 +128,8 @@ pub async fn delete_config<S: StorageAPI>(api: Arc<S>, file: &str) -> Result<()>
|
||||
}
|
||||
|
||||
pub async fn save_config_with_opts<S: StorageAPI>(api: Arc<S>, file: &str, data: Vec<u8>, opts: &ObjectOptions) -> Result<()> {
|
||||
if let Err(err) = api
|
||||
.put_object(RUSTFS_META_BUCKET, file, &mut PutObjReader::from_vec(data), opts)
|
||||
.await
|
||||
{
|
||||
let mut put_data = ChunkNativePutData::from_vec(data);
|
||||
if let Err(err) = api.put_object(RUSTFS_META_BUCKET, file, &mut put_data, opts).await {
|
||||
error!("save_config_with_opts: err: {:?}, file: {}", err, file);
|
||||
return Err(err);
|
||||
}
|
||||
@@ -1078,10 +1076,10 @@ mod tests {
|
||||
use crate::global::{is_dist_erasure, is_erasure, is_erasure_sd, update_erasure_type};
|
||||
use crate::set_disk::SetDisks;
|
||||
use crate::store_api::{
|
||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, GetObjectReader,
|
||||
HTTPRangeSpec, HealOperations, ListMultipartsInfo, ListObjectVersionsInfo, ListObjectsV2Info, ListOperations,
|
||||
MakeBucketOptions, MultipartInfo, MultipartOperations, MultipartUploadResult, ObjectIO, ObjectInfo, ObjectOperations,
|
||||
ObjectOptions, ObjectToDelete, PartInfo, PutObjReader, StorageAPI, WalkOptions,
|
||||
BucketInfo, BucketOperations, BucketOptions, ChunkNativePutData, CompletePart, DeleteBucketOptions, DeletedObject,
|
||||
GetObjectReader, HTTPRangeSpec, HealOperations, ListMultipartsInfo, ListObjectVersionsInfo, ListObjectsV2Info,
|
||||
ListOperations, MakeBucketOptions, MultipartInfo, MultipartOperations, MultipartUploadResult, ObjectIO, ObjectInfo,
|
||||
ObjectOperations, ObjectOptions, ObjectToDelete, PartInfo, StorageAPI, WalkOptions,
|
||||
};
|
||||
use http::HeaderMap;
|
||||
use rustfs_config::audit::{AUDIT_MQTT_SUB_SYS, AUDIT_WEBHOOK_SUB_SYS};
|
||||
@@ -1304,7 +1302,7 @@ mod tests {
|
||||
&self,
|
||||
_bucket: &str,
|
||||
_object: &str,
|
||||
_data: &mut PutObjReader,
|
||||
_data: &mut ChunkNativePutData,
|
||||
_opts: &ObjectOptions,
|
||||
) -> Result<ObjectInfo> {
|
||||
panic!("unused in test")
|
||||
@@ -1491,7 +1489,7 @@ mod tests {
|
||||
_object: &str,
|
||||
_upload_id: &str,
|
||||
_part_id: usize,
|
||||
_data: &mut PutObjReader,
|
||||
_data: &mut ChunkNativePutData,
|
||||
_opts: &ObjectOptions,
|
||||
) -> Result<PartInfo> {
|
||||
panic!("unused in test")
|
||||
|
||||
@@ -150,18 +150,7 @@ impl Config {
|
||||
return false;
|
||||
}
|
||||
|
||||
let shard_size = shard_size as usize;
|
||||
|
||||
let mut inline_block = DEFAULT_INLINE_BLOCK;
|
||||
if self.initialized {
|
||||
inline_block = self.inline_block;
|
||||
}
|
||||
|
||||
if versioned {
|
||||
shard_size <= inline_block / 8
|
||||
} else {
|
||||
shard_size <= inline_block
|
||||
}
|
||||
shard_size as usize <= self.inline_shard_limit_bytes(versioned)
|
||||
}
|
||||
|
||||
pub fn inline_block(&self) -> usize {
|
||||
@@ -172,6 +161,15 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inline_shard_limit_bytes(&self, versioned: bool) -> usize {
|
||||
let inline_block = self.inline_block();
|
||||
if versioned { inline_block / 8 } else { inline_block }
|
||||
}
|
||||
|
||||
pub fn inline_object_limit_bytes(&self, data_shards: usize, versioned: bool) -> usize {
|
||||
self.inline_shard_limit_bytes(versioned).saturating_mul(data_shards.max(1))
|
||||
}
|
||||
|
||||
pub fn capacity_optimized(&self) -> bool {
|
||||
if !self.initialized {
|
||||
false
|
||||
@@ -336,3 +334,32 @@ pub fn validate_parity_inner(ss_parity: usize, rrs_parity: usize, set_drive_coun
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn inline_object_limit_matches_default_non_versioned_budget() {
|
||||
let cfg = Config {
|
||||
initialized: true,
|
||||
inline_block: DEFAULT_INLINE_BLOCK,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(cfg.inline_shard_limit_bytes(false), DEFAULT_INLINE_BLOCK);
|
||||
assert_eq!(cfg.inline_object_limit_bytes(8, false), DEFAULT_INLINE_BLOCK * 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inline_object_limit_scales_down_for_versioned_objects() {
|
||||
let cfg = Config {
|
||||
initialized: true,
|
||||
inline_block: DEFAULT_INLINE_BLOCK,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(cfg.inline_shard_limit_bytes(true), DEFAULT_INLINE_BLOCK / 8);
|
||||
assert_eq!(cfg.inline_object_limit_bytes(8, true), DEFAULT_INLINE_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user