mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-20 03:22:18 +00:00
feat: optimize small GET read paths (#4022)
This commit is contained in:
@@ -332,8 +332,8 @@ impl ECStore {
|
||||
pool_meta: RwLock::new(pool_meta),
|
||||
rebalance_meta: RwLock::new(None),
|
||||
decommission_cancelers,
|
||||
start_gate: tokio::sync::Mutex::new(()),
|
||||
pool_meta_save_gate: tokio::sync::Mutex::new(()),
|
||||
start_gate: Mutex::new(()),
|
||||
pool_meta_save_gate: Mutex::new(()),
|
||||
});
|
||||
|
||||
// Only set it when the global deployment ID is not yet configured
|
||||
@@ -545,6 +545,7 @@ mod tests {
|
||||
Ok(GetObjectReader {
|
||||
stream: Box::new(Cursor::new(self.read_payload.clone())),
|
||||
object_info: self.object_info(bucket, object, self.read_payload.len()),
|
||||
buffered_body: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -428,6 +428,7 @@ impl ECStore {
|
||||
diag_enabled,
|
||||
);
|
||||
opts.no_lock = true;
|
||||
opts.metadata_cache_safe = true;
|
||||
|
||||
Ok(Some(ObjectLockDiagGuard::new(
|
||||
guard,
|
||||
@@ -1301,6 +1302,10 @@ impl ECStore {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::bucket::lifecycle::core::TRANSITION_COMPLETE;
|
||||
use crate::layout::{
|
||||
endpoints::{Endpoints, PoolEndpoints},
|
||||
format::FormatV3,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
@@ -1818,6 +1823,76 @@ mod tests {
|
||||
assert!(lookup_opts.no_lock);
|
||||
}
|
||||
|
||||
async fn new_read_lock_test_store() -> ECStore {
|
||||
let format = FormatV3::new(1, 2);
|
||||
let endpoints = vec![
|
||||
Endpoint::try_from("http://127.0.0.1:9000/data0").expect("first endpoint should parse"),
|
||||
Endpoint::try_from("http://127.0.0.1:9001/data1").expect("second endpoint should parse"),
|
||||
];
|
||||
let pool_endpoints = PoolEndpoints {
|
||||
legacy: false,
|
||||
set_count: 1,
|
||||
drives_per_set: 2,
|
||||
endpoints: Endpoints::from(endpoints),
|
||||
cmd_line: "read-lock-metadata-cache-safe-test".to_string(),
|
||||
platform: "test".to_string(),
|
||||
};
|
||||
let endpoint_pools = EndpointServerPools::from(vec![pool_endpoints.clone()]);
|
||||
let sets = Sets::new(vec![None, None], &pool_endpoints, &format, 0, 1)
|
||||
.await
|
||||
.expect("test sets should be created with empty disks");
|
||||
|
||||
ECStore {
|
||||
id: Uuid::new_v4(),
|
||||
disk_map: HashMap::new(),
|
||||
pools: vec![sets],
|
||||
peer_sys: S3PeerSys::new(&endpoint_pools),
|
||||
pool_meta: RwLock::new(PoolMeta::default()),
|
||||
rebalance_meta: RwLock::new(None),
|
||||
decommission_cancelers: RwLock::new(Vec::new()),
|
||||
start_gate: Mutex::new(()),
|
||||
pool_meta_save_gate: Mutex::new(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn acquired_read_lock_marks_metadata_cache_safe_for_set_layer() {
|
||||
let store = new_read_lock_test_store().await;
|
||||
let mut opts = ObjectOptions::default();
|
||||
|
||||
let guard = store
|
||||
.acquire_object_read_lock_if_needed("get_object", "bucket", "object", &mut opts)
|
||||
.await
|
||||
.expect("read lock should be acquired");
|
||||
|
||||
assert!(guard.is_some(), "read lock should be held by the outer store layer");
|
||||
assert!(opts.no_lock, "set layer should not reacquire the object lock");
|
||||
assert!(
|
||||
opts.metadata_cache_safe,
|
||||
"metadata cache is safe only because the outer store layer acquired the read lock"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn prelocked_read_request_does_not_mark_metadata_cache_safe() {
|
||||
let store = new_read_lock_test_store().await;
|
||||
let mut opts = ObjectOptions {
|
||||
no_lock: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let guard = store
|
||||
.acquire_object_read_lock_if_needed("get_object", "bucket", "object", &mut opts)
|
||||
.await
|
||||
.expect("prelocked read should not acquire another lock");
|
||||
|
||||
assert!(guard.is_none(), "prelocked caller should keep lock ownership outside ECStore");
|
||||
assert!(
|
||||
!opts.metadata_cache_safe,
|
||||
"generic no_lock callers must stay ineligible for metadata cache unless explicitly marked safe"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial_test::serial]
|
||||
async fn reader_lock_is_held_when_optimization_is_disabled() {
|
||||
@@ -1841,6 +1916,7 @@ mod tests {
|
||||
let reader = GetObjectReader {
|
||||
stream: Box::new(Cursor::new(Vec::<u8>::new())),
|
||||
object_info: ObjectInfo::default(),
|
||||
buffered_body: None,
|
||||
};
|
||||
|
||||
let reader = ECStore::attach_read_lock_guard(reader, Some(read_guard));
|
||||
@@ -1879,6 +1955,7 @@ mod tests {
|
||||
let reader = GetObjectReader {
|
||||
stream: Box::new(Cursor::new(vec![1, 2, 3])),
|
||||
object_info: ObjectInfo::default(),
|
||||
buffered_body: None,
|
||||
};
|
||||
|
||||
let mut reader = ECStore::attach_read_lock_guard(reader, Some(read_guard));
|
||||
|
||||
Reference in New Issue
Block a user