mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-22 20:36:38 +00:00
refactor: move ecstore owner layout modules (#3932)
This commit is contained in:
@@ -0,0 +1,378 @@
|
||||
// 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 crate::bucket::bandwidth::monitor::Monitor;
|
||||
use crate::{
|
||||
bucket::lifecycle::bucket_lifecycle_ops::LifecycleSys,
|
||||
disk::DiskStore,
|
||||
endpoints::{EndpointServerPools, PoolEndpoints, SetupType},
|
||||
event_notification::EventNotifier,
|
||||
store::ECStore,
|
||||
tier::tier::TierConfigMgr,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use rustfs_lock::client::LockClient;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, OnceLock},
|
||||
time::SystemTime,
|
||||
};
|
||||
use tokio::sync::{OnceCell, RwLock};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::warn;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub const DISK_ASSUME_UNKNOWN_SIZE: u64 = 1 << 30;
|
||||
pub const DISK_MIN_INODES: u64 = 1000;
|
||||
pub const DISK_FILL_FRACTION: f64 = 0.99;
|
||||
pub const DISK_RESERVE_FRACTION: f64 = 0.15;
|
||||
|
||||
lazy_static! {
|
||||
static ref GLOBAL_RUSTFS_PORT: OnceLock<u16> = OnceLock::new();
|
||||
static ref globalDeploymentIDPtr: OnceLock<Uuid> = OnceLock::new();
|
||||
pub static ref GLOBAL_OBJECT_API: OnceLock<Arc<ECStore>> = OnceLock::new();
|
||||
pub static ref GLOBAL_IsErasure: RwLock<bool> = RwLock::new(false);
|
||||
pub static ref GLOBAL_IsDistErasure: RwLock<bool> = RwLock::new(false);
|
||||
pub static ref GLOBAL_IsErasureSD: RwLock<bool> = RwLock::new(false);
|
||||
pub static ref GLOBAL_LOCAL_DISK_MAP: Arc<RwLock<HashMap<String, Option<DiskStore>>>> = Arc::new(RwLock::new(HashMap::new()));
|
||||
pub static ref GLOBAL_LOCAL_DISK_ID_MAP: Arc<RwLock<HashMap<Uuid, String>>> = Arc::new(RwLock::new(HashMap::new()));
|
||||
pub static ref GLOBAL_LOCAL_DISK_SET_DRIVES: Arc<RwLock<TypeLocalDiskSetDrives>> = Arc::new(RwLock::new(Vec::new()));
|
||||
pub static ref GLOBAL_Endpoints: OnceLock<EndpointServerPools> = OnceLock::new();
|
||||
pub static ref GLOBAL_RootDiskThreshold: RwLock<u64> = RwLock::new(0);
|
||||
pub static ref GLOBAL_TierConfigMgr: Arc<RwLock<TierConfigMgr>> = TierConfigMgr::new();
|
||||
pub static ref GLOBAL_LifecycleSys: Arc<LifecycleSys> = LifecycleSys::new();
|
||||
pub static ref GLOBAL_EventNotifier: Arc<RwLock<EventNotifier>> = EventNotifier::new();
|
||||
pub static ref GLOBAL_BOOT_TIME: OnceCell<SystemTime> = OnceCell::new();
|
||||
pub static ref GLOBAL_LocalNodeName: String = "127.0.0.1:9000".to_string();
|
||||
pub static ref GLOBAL_LocalNodeNameHex: String = rustfs_utils::crypto::hex(GLOBAL_LocalNodeName.as_bytes());
|
||||
pub static ref GLOBAL_NodeNamesHex: HashMap<String, ()> = HashMap::new();
|
||||
pub static ref GLOBAL_REGION: OnceLock<s3s::region::Region> = OnceLock::new();
|
||||
pub static ref GLOBAL_LOCAL_LOCK_CLIENT: OnceLock<Arc<dyn LockClient>> = OnceLock::new();
|
||||
pub static ref GLOBAL_LOCK_CLIENTS: OnceLock<HashMap<String, Arc<dyn LockClient>>> = OnceLock::new();
|
||||
pub static ref GLOBAL_BUCKET_MONITOR: OnceLock<Arc<Monitor>> = OnceLock::new();
|
||||
}
|
||||
|
||||
pub fn init_global_bucket_monitor(num_nodes: u64) {
|
||||
if GLOBAL_BUCKET_MONITOR.set(Monitor::new(num_nodes)).is_err() {
|
||||
warn!(
|
||||
"global bucket monitor already initialized, ignoring re-initialization with num_nodes={}",
|
||||
num_nodes
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_global_bucket_monitor() -> Option<Arc<Monitor>> {
|
||||
GLOBAL_BUCKET_MONITOR.get().cloned()
|
||||
}
|
||||
|
||||
/// Global cancellation token for background services (data scanner and auto heal)
|
||||
static GLOBAL_BACKGROUND_SERVICES_CANCEL_TOKEN: OnceLock<CancellationToken> = OnceLock::new();
|
||||
|
||||
/// Get the global rustfs port
|
||||
///
|
||||
/// # Returns
|
||||
/// * `u16` - The global rustfs port
|
||||
///
|
||||
pub fn global_rustfs_port() -> u16 {
|
||||
if let Some(p) = GLOBAL_RUSTFS_PORT.get() {
|
||||
*p
|
||||
} else {
|
||||
rustfs_config::DEFAULT_PORT
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the global rustfs port
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `value` - The port value to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
pub fn set_global_rustfs_port(value: u16) {
|
||||
GLOBAL_RUSTFS_PORT.set(value).expect("set_global_rustfs_port fail");
|
||||
}
|
||||
|
||||
/// Set the global deployment id
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `id` - The Uuid to set as the global deployment id
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
///
|
||||
pub fn set_global_deployment_id(id: Uuid) {
|
||||
globalDeploymentIDPtr.set(id).unwrap();
|
||||
}
|
||||
|
||||
/// Get the global deployment id
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<String>` - The global deployment id as a string, if set
|
||||
///
|
||||
pub fn get_global_deployment_id() -> Option<String> {
|
||||
globalDeploymentIDPtr.get().map(|v| v.to_string())
|
||||
}
|
||||
/// Set the global endpoints
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `eps` - A vector of PoolEndpoints to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
///
|
||||
pub fn set_global_endpoints(eps: Vec<PoolEndpoints>) {
|
||||
GLOBAL_Endpoints
|
||||
.set(EndpointServerPools::from(eps))
|
||||
.expect("GLOBAL_Endpoints set failed")
|
||||
}
|
||||
|
||||
/// Get the global endpoints
|
||||
///
|
||||
/// # Returns
|
||||
/// * `EndpointServerPools` - The global endpoints
|
||||
///
|
||||
pub fn get_global_endpoints() -> EndpointServerPools {
|
||||
if let Some(eps) = GLOBAL_Endpoints.get() {
|
||||
eps.clone()
|
||||
} else {
|
||||
EndpointServerPools::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_global_endpoints_opt() -> Option<EndpointServerPools> {
|
||||
GLOBAL_Endpoints.get().cloned()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub async fn reset_local_disk_test_state() {
|
||||
GLOBAL_LOCAL_DISK_MAP.write().await.clear();
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.write().await.clear();
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES.write().await.clear();
|
||||
}
|
||||
|
||||
pub async fn is_first_cluster_node_local() -> bool {
|
||||
get_global_endpoints().first_local()
|
||||
}
|
||||
|
||||
pub fn get_global_tier_config_mgr() -> Arc<RwLock<TierConfigMgr>> {
|
||||
GLOBAL_TierConfigMgr.clone()
|
||||
}
|
||||
|
||||
/// Create a new object layer instance
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<Arc<ECStore>>` - The global object layer instance, if set
|
||||
///
|
||||
pub fn new_object_layer_fn() -> Option<Arc<ECStore>> {
|
||||
GLOBAL_OBJECT_API.get().cloned()
|
||||
}
|
||||
|
||||
pub type ObjectStoreResolver = dyn Fn() -> Option<Arc<ECStore>> + Send + Sync + 'static;
|
||||
|
||||
static GLOBAL_OBJECT_STORE_RESOLVER: OnceLock<Arc<ObjectStoreResolver>> = OnceLock::new();
|
||||
|
||||
pub fn set_object_store_resolver(resolver: Arc<ObjectStoreResolver>) -> bool {
|
||||
GLOBAL_OBJECT_STORE_RESOLVER.set(resolver).is_ok()
|
||||
}
|
||||
|
||||
pub fn resolve_object_store_handle() -> Option<Arc<ECStore>> {
|
||||
GLOBAL_OBJECT_STORE_RESOLVER
|
||||
.get()
|
||||
.and_then(|resolver| resolver())
|
||||
.or_else(new_object_layer_fn)
|
||||
}
|
||||
|
||||
/// Set the global object layer
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `o` - The ECStore instance to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
pub async fn set_object_layer(o: Arc<ECStore>) {
|
||||
GLOBAL_OBJECT_API.set(o).expect("set_object_layer fail ")
|
||||
}
|
||||
|
||||
/// Check if the setup type is distributed erasure coding
|
||||
///
|
||||
/// # Returns
|
||||
/// * `bool` - True if the setup type is distributed erasure coding, false otherwise
|
||||
///
|
||||
pub async fn is_dist_erasure() -> bool {
|
||||
let lock = GLOBAL_IsDistErasure.read().await;
|
||||
*lock
|
||||
}
|
||||
|
||||
/// Check if the setup type is erasure coding with single data center
|
||||
///
|
||||
/// # Returns
|
||||
/// * `bool` - True if the setup type is erasure coding with single data center, false otherwise
|
||||
///
|
||||
pub async fn is_erasure_sd() -> bool {
|
||||
let lock = GLOBAL_IsErasureSD.read().await;
|
||||
*lock
|
||||
}
|
||||
|
||||
/// Check if the setup type is erasure coding
|
||||
///
|
||||
/// # Returns
|
||||
/// * `bool` - True if the setup type is erasure coding, false otherwise
|
||||
///
|
||||
pub async fn is_erasure() -> bool {
|
||||
let lock = GLOBAL_IsErasure.read().await;
|
||||
*lock
|
||||
}
|
||||
|
||||
/// Update the global erasure type based on the setup type
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `setup_type` - The SetupType to update the global erasure type
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
pub async fn update_erasure_type(setup_type: SetupType) {
|
||||
let mut is_erasure = GLOBAL_IsErasure.write().await;
|
||||
*is_erasure = setup_type == SetupType::Erasure;
|
||||
|
||||
let mut is_dist_erasure = GLOBAL_IsDistErasure.write().await;
|
||||
*is_dist_erasure = setup_type == SetupType::DistErasure;
|
||||
|
||||
if *is_dist_erasure {
|
||||
*is_erasure = true
|
||||
}
|
||||
|
||||
let mut is_erasure_sd = GLOBAL_IsErasureSD.write().await;
|
||||
*is_erasure_sd = setup_type == SetupType::ErasureSD;
|
||||
}
|
||||
|
||||
// pub fn is_legacy() -> bool {
|
||||
// if let Some(endpoints) = GLOBAL_Endpoints.get() {
|
||||
// endpoints.as_ref().len() == 1 && endpoints.as_ref()[0].legacy
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
|
||||
pub(crate) type TypeLocalDiskSetDrives = Vec<Vec<Vec<Option<DiskStore>>>>;
|
||||
|
||||
/// Set the global region
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `region` - The Region instance to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
pub fn set_global_region(region: s3s::region::Region) {
|
||||
GLOBAL_REGION.set(region).unwrap();
|
||||
}
|
||||
|
||||
/// Get the global region
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<s3s::region::Region>` - The global region, if set
|
||||
///
|
||||
pub fn get_global_region() -> Option<s3s::region::Region> {
|
||||
GLOBAL_REGION.get().cloned()
|
||||
}
|
||||
|
||||
/// Initialize the global background services cancellation token
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `cancel_token` - The CancellationToken instance to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(())` if successful
|
||||
/// * `Err(CancellationToken)` if setting fails
|
||||
///
|
||||
pub fn init_background_services_cancel_token(cancel_token: CancellationToken) -> Result<(), CancellationToken> {
|
||||
GLOBAL_BACKGROUND_SERVICES_CANCEL_TOKEN.set(cancel_token)
|
||||
}
|
||||
|
||||
/// Get the global background services cancellation token
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<&'static CancellationToken>` - The global cancellation token, if set
|
||||
///
|
||||
pub fn get_background_services_cancel_token() -> Option<&'static CancellationToken> {
|
||||
GLOBAL_BACKGROUND_SERVICES_CANCEL_TOKEN.get()
|
||||
}
|
||||
|
||||
/// Create and initialize the global background services cancellation token
|
||||
///
|
||||
/// # Returns
|
||||
/// * `CancellationToken` - The newly created global cancellation token
|
||||
///
|
||||
pub fn create_background_services_cancel_token() -> CancellationToken {
|
||||
let cancel_token = CancellationToken::new();
|
||||
init_background_services_cancel_token(cancel_token.clone()).expect("Background services cancel token already initialized");
|
||||
cancel_token
|
||||
}
|
||||
|
||||
/// Shutdown all background services gracefully
|
||||
///
|
||||
/// # Returns
|
||||
/// * None
|
||||
pub fn shutdown_background_services() {
|
||||
if let Some(cancel_token) = GLOBAL_BACKGROUND_SERVICES_CANCEL_TOKEN.get() {
|
||||
cancel_token.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the global lock client (first LocalClient created)
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `client` - The LockClient instance to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(())` if successful
|
||||
/// * `Err(Arc<dyn LockClient>)` if setting fails (client already set)
|
||||
///
|
||||
pub fn set_global_lock_client(
|
||||
client: Arc<dyn rustfs_lock::client::LockClient>,
|
||||
) -> Result<(), Arc<dyn rustfs_lock::client::LockClient>> {
|
||||
GLOBAL_LOCAL_LOCK_CLIENT.set(client)
|
||||
}
|
||||
|
||||
/// Get the global lock client
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<Arc<dyn LockClient>>` - The global lock client, if set
|
||||
///
|
||||
pub fn get_global_lock_client() -> Option<Arc<dyn rustfs_lock::client::LockClient>> {
|
||||
GLOBAL_LOCAL_LOCK_CLIENT.get().cloned()
|
||||
}
|
||||
|
||||
/// Set the global lock clients map
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `clients` - The HashMap of lock clients to set globally
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(())` if successful
|
||||
/// * `Err(HashMap<String, Arc<dyn LockClient>>)` if setting fails (clients already set)
|
||||
///
|
||||
pub fn set_global_lock_clients(
|
||||
clients: HashMap<String, Arc<dyn LockClient>>,
|
||||
) -> Result<(), HashMap<String, Arc<dyn LockClient>>> {
|
||||
GLOBAL_LOCK_CLIENTS.set(clients)
|
||||
}
|
||||
|
||||
/// Get the global lock clients map
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Option<&HashMap<String, Arc<dyn LockClient>>>` - The global lock clients map, if set
|
||||
///
|
||||
pub fn get_global_lock_clients() -> Option<&'static HashMap<String, Arc<dyn LockClient>>> {
|
||||
GLOBAL_LOCK_CLIENTS.get()
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
// 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 std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, OnceLock},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
use crate::bucket::bandwidth::monitor::Monitor;
|
||||
use crate::disk::endpoint::Endpoint;
|
||||
use crate::{
|
||||
batch_processor::{GlobalBatchProcessors, get_global_processors},
|
||||
bucket::lifecycle::bucket_lifecycle_ops::{ExpiryState, GLOBAL_ExpiryState, GLOBAL_TransitionState, TransitionState},
|
||||
bucket::metadata_sys::{BucketMetadataSys, get_global_bucket_metadata_sys},
|
||||
bucket::replication::{DynReplicationPool, GLOBAL_REPLICATION_POOL, GLOBAL_REPLICATION_STATS, ReplicationStats},
|
||||
config::{get_global_storage_class, set_global_storage_class, storageclass},
|
||||
disk::{DiskAPI, DiskOption, DiskStore, new_disk},
|
||||
endpoints::EndpointServerPools,
|
||||
endpoints::SetupType,
|
||||
error::Result,
|
||||
event_notification::EventNotifier,
|
||||
global::{
|
||||
GLOBAL_BOOT_TIME, GLOBAL_EventNotifier, GLOBAL_IsErasureSD, GLOBAL_LOCAL_DISK_ID_MAP, GLOBAL_LOCAL_DISK_MAP,
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES, GLOBAL_LifecycleSys, GLOBAL_LocalNodeName, GLOBAL_RootDiskThreshold, GLOBAL_TierConfigMgr,
|
||||
TypeLocalDiskSetDrives, get_global_bucket_monitor, get_global_deployment_id, get_global_endpoints,
|
||||
get_global_endpoints_opt, get_global_lock_clients, get_global_region, get_global_tier_config_mgr, global_rustfs_port,
|
||||
init_global_bucket_monitor, is_dist_erasure, is_erasure, is_first_cluster_node_local, resolve_object_store_handle,
|
||||
set_global_deployment_id, set_global_lock_client, set_global_lock_clients, set_object_layer, update_erasure_type,
|
||||
},
|
||||
notification_sys::{NotificationSys, get_global_notification_sys},
|
||||
store::ECStore,
|
||||
tier::tier::TierConfigMgr,
|
||||
};
|
||||
use rustfs_common::{GLOBAL_CONN_MAP, GLOBAL_LOCAL_NODE_NAME, GLOBAL_RUSTFS_ADDR, GLOBAL_RUSTFS_HOST};
|
||||
use rustfs_concurrency::WorkloadAdmissionSnapshotProvider;
|
||||
use rustfs_config::server_config::{Config, get_global_server_config, set_global_server_config};
|
||||
use rustfs_io_metrics::internode_metrics::global_internode_metrics;
|
||||
use rustfs_kms::{ObjectEncryptionService, get_global_encryption_service};
|
||||
use rustfs_lock::client::LockClient;
|
||||
use s3s::dto::BucketLifecycleConfiguration;
|
||||
use s3s::region::Region;
|
||||
use tokio::sync::RwLock;
|
||||
use tonic::transport::Channel;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[cfg(test)]
|
||||
const TEST_RPC_SECRET: &str = "test-rpc-secret";
|
||||
|
||||
pub(crate) type WorkloadSnapshotProviderRef = Arc<dyn WorkloadAdmissionSnapshotProvider + Send + Sync>;
|
||||
|
||||
static WORKLOAD_ADMISSION_SNAPSHOT_PROVIDER: OnceLock<WorkloadSnapshotProviderRef> = OnceLock::new();
|
||||
|
||||
pub(crate) fn set_workload_admission_snapshot_provider(
|
||||
provider: WorkloadSnapshotProviderRef,
|
||||
) -> std::result::Result<(), WorkloadSnapshotProviderRef> {
|
||||
WORKLOAD_ADMISSION_SNAPSHOT_PROVIDER.set(provider)
|
||||
}
|
||||
|
||||
pub(crate) fn workload_admission_snapshot_provider() -> Option<WorkloadSnapshotProviderRef> {
|
||||
WORKLOAD_ADMISSION_SNAPSHOT_PROVIDER.get().cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn record_erasure_write_quorum_failure(stage: &'static str, dominant_error: &'static str) {
|
||||
global_internode_metrics().record_erasure_write_quorum_failure(stage, dominant_error);
|
||||
}
|
||||
|
||||
pub(crate) async fn object_encryption_service() -> Option<Arc<ObjectEncryptionService>> {
|
||||
get_global_encryption_service().await
|
||||
}
|
||||
|
||||
pub(crate) fn object_store_handle() -> Option<Arc<ECStore>> {
|
||||
resolve_object_store_handle()
|
||||
}
|
||||
|
||||
pub(crate) fn endpoint_pools() -> Option<EndpointServerPools> {
|
||||
get_global_endpoints_opt()
|
||||
}
|
||||
|
||||
pub(crate) fn endpoint_pools_or_default() -> EndpointServerPools {
|
||||
get_global_endpoints()
|
||||
}
|
||||
|
||||
pub(crate) fn endpoint_erasure_set_count() -> Option<usize> {
|
||||
endpoint_pools().map(|endpoints| endpoints.es_count())
|
||||
}
|
||||
|
||||
pub(crate) fn endpoint_pool_is_local(pool_index: usize) -> bool {
|
||||
get_global_endpoints()
|
||||
.as_ref()
|
||||
.get(pool_index)
|
||||
.is_some_and(|pool| pool.endpoints.as_ref().first().is_some_and(|endpoint| endpoint.is_local))
|
||||
}
|
||||
|
||||
pub(crate) async fn first_cluster_node_is_local() -> bool {
|
||||
is_first_cluster_node_local().await
|
||||
}
|
||||
|
||||
pub(crate) async fn setup_is_erasure() -> bool {
|
||||
is_erasure().await
|
||||
}
|
||||
|
||||
pub(crate) async fn setup_is_dist_erasure() -> bool {
|
||||
is_dist_erasure().await
|
||||
}
|
||||
|
||||
pub(crate) async fn setup_is_erasure_sd() -> bool {
|
||||
*GLOBAL_IsErasureSD.read().await
|
||||
}
|
||||
|
||||
pub(crate) async fn current_setup_type() -> SetupType {
|
||||
if setup_is_dist_erasure().await {
|
||||
SetupType::DistErasure
|
||||
} else if setup_is_erasure_sd().await {
|
||||
SetupType::ErasureSD
|
||||
} else if setup_is_erasure().await {
|
||||
SetupType::Erasure
|
||||
} else {
|
||||
SetupType::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn set_setup_type(setup_type: SetupType) {
|
||||
update_erasure_type(setup_type).await;
|
||||
}
|
||||
|
||||
pub(crate) async fn local_node_name() -> String {
|
||||
GLOBAL_LOCAL_NODE_NAME.read().await.clone()
|
||||
}
|
||||
|
||||
pub(crate) async fn set_local_node_name(node_name: String) {
|
||||
*GLOBAL_LOCAL_NODE_NAME.write().await = node_name;
|
||||
}
|
||||
|
||||
pub(crate) fn default_local_node_name() -> String {
|
||||
GLOBAL_LocalNodeName.to_string()
|
||||
}
|
||||
|
||||
pub(crate) fn rustfs_port() -> u16 {
|
||||
global_rustfs_port()
|
||||
}
|
||||
|
||||
pub(crate) async fn rustfs_host() -> String {
|
||||
GLOBAL_RUSTFS_HOST.read().await.clone()
|
||||
}
|
||||
|
||||
pub(crate) async fn rustfs_addr() -> String {
|
||||
GLOBAL_RUSTFS_ADDR.read().await.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn boot_uptime_secs() -> u64 {
|
||||
GLOBAL_BOOT_TIME
|
||||
.get()
|
||||
.and_then(|boot_time| SystemTime::now().duration_since(*boot_time).ok())
|
||||
.unwrap_or_default()
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
pub(crate) async fn ensure_boot_time() {
|
||||
GLOBAL_BOOT_TIME.get_or_init(|| async { SystemTime::now() }).await;
|
||||
}
|
||||
|
||||
pub(crate) async fn scanner_init_time() -> Option<chrono::DateTime<chrono::Utc>> {
|
||||
rustfs_common::get_global_init_time().await
|
||||
}
|
||||
|
||||
pub(crate) async fn root_disk_threshold_for_erasure_disk() -> Option<u64> {
|
||||
if *GLOBAL_IsErasureSD.read().await {
|
||||
None
|
||||
} else {
|
||||
Some(*GLOBAL_RootDiskThreshold.read().await)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn cached_node_channel(addr: &str) -> Option<Channel> {
|
||||
GLOBAL_CONN_MAP.read().await.get(addr).cloned()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn cache_test_node_channel(addr: String, channel: Channel) {
|
||||
GLOBAL_CONN_MAP.write().await.insert(addr, channel);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn test_node_channel_is_cached(addr: &str) -> bool {
|
||||
GLOBAL_CONN_MAP.read().await.contains_key(addr)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn ensure_test_rpc_secret() {
|
||||
let _ = rustfs_credentials::GLOBAL_RUSTFS_RPC_SECRET.set(TEST_RPC_SECRET.to_owned());
|
||||
}
|
||||
|
||||
pub(crate) fn storage_class_parity(storage_class: Option<&str>) -> Option<usize> {
|
||||
get_global_storage_class().and_then(|sc| sc.get_parity_for_sc(storage_class.unwrap_or_default()))
|
||||
}
|
||||
|
||||
pub(crate) fn backend_storage_class_parities(default_standard_parity: usize) -> (Option<usize>, Option<usize>) {
|
||||
if let Some(sc) = get_global_storage_class() {
|
||||
let standard = sc
|
||||
.get_parity_for_sc(crate::config::storageclass::CLASS_STANDARD)
|
||||
.or(Some(default_standard_parity));
|
||||
let reduced_redundancy = sc.get_parity_for_sc(crate::config::storageclass::RRS);
|
||||
(standard, reduced_redundancy)
|
||||
} else {
|
||||
(Some(default_standard_parity), None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn storage_class_should_inline(shard_size: i64, versioned: bool) -> bool {
|
||||
get_global_storage_class().is_some_and(|sc| sc.should_inline(shard_size, versioned))
|
||||
}
|
||||
|
||||
pub(crate) fn deployment_upload_id(upload_id: &str) -> String {
|
||||
base64_simd::URL_SAFE_NO_PAD
|
||||
.encode_to_string(format!("{}.{}", get_global_deployment_id().unwrap_or_default(), upload_id).as_bytes())
|
||||
}
|
||||
|
||||
pub(crate) fn deployment_id() -> Option<String> {
|
||||
get_global_deployment_id()
|
||||
}
|
||||
|
||||
pub(crate) fn replication_pool() -> Option<Arc<DynReplicationPool>> {
|
||||
GLOBAL_REPLICATION_POOL.get().cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn replication_stats() -> Option<Arc<ReplicationStats>> {
|
||||
GLOBAL_REPLICATION_STATS.get().cloned()
|
||||
}
|
||||
|
||||
pub(crate) fn replication_runtime_initialized() -> bool {
|
||||
GLOBAL_REPLICATION_STATS.get().is_some() && GLOBAL_REPLICATION_POOL.get().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_deployment_id(deployment_id: Uuid) {
|
||||
if get_global_deployment_id().is_none() {
|
||||
set_global_deployment_id(deployment_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn global_lock_manager() -> Arc<rustfs_lock::GlobalLockManager> {
|
||||
rustfs_lock::get_global_lock_manager()
|
||||
}
|
||||
|
||||
pub(crate) fn global_lock_clients() -> Option<&'static HashMap<String, Arc<dyn LockClient>>> {
|
||||
get_global_lock_clients()
|
||||
}
|
||||
|
||||
pub(crate) fn set_primary_lock_client(client: Arc<dyn LockClient>) -> std::result::Result<(), Arc<dyn LockClient>> {
|
||||
set_global_lock_client(client)
|
||||
}
|
||||
|
||||
pub(crate) fn set_lock_clients(
|
||||
clients: HashMap<String, Arc<dyn LockClient>>,
|
||||
) -> std::result::Result<(), HashMap<String, Arc<dyn LockClient>>> {
|
||||
set_global_lock_clients(clients)
|
||||
}
|
||||
|
||||
pub(crate) async fn publish_object_store(store: Arc<ECStore>) {
|
||||
set_object_layer(store).await;
|
||||
}
|
||||
|
||||
pub(crate) fn notification_sys() -> Option<&'static NotificationSys> {
|
||||
get_global_notification_sys()
|
||||
}
|
||||
|
||||
pub(crate) fn bucket_metadata_sys() -> Option<Arc<RwLock<BucketMetadataSys>>> {
|
||||
get_global_bucket_metadata_sys()
|
||||
}
|
||||
|
||||
pub(crate) fn region() -> Option<Region> {
|
||||
get_global_region()
|
||||
}
|
||||
|
||||
pub(crate) fn server_config() -> Option<Config> {
|
||||
get_global_server_config()
|
||||
}
|
||||
|
||||
pub(crate) fn set_server_config(config: Config) {
|
||||
set_global_server_config(config);
|
||||
}
|
||||
|
||||
pub(crate) fn storage_class_config() -> Option<storageclass::Config> {
|
||||
get_global_storage_class()
|
||||
}
|
||||
|
||||
pub(crate) fn set_storage_class_config(config: storageclass::Config) {
|
||||
set_global_storage_class(config);
|
||||
}
|
||||
|
||||
pub(crate) fn batch_processors() -> &'static GlobalBatchProcessors {
|
||||
get_global_processors()
|
||||
}
|
||||
|
||||
pub(crate) fn global_tier_config_mgr() -> Arc<RwLock<TierConfigMgr>> {
|
||||
get_global_tier_config_mgr()
|
||||
}
|
||||
|
||||
pub(crate) async fn bucket_lifecycle_config(bucket: &str) -> Option<BucketLifecycleConfiguration> {
|
||||
GLOBAL_LifecycleSys.get(bucket).await
|
||||
}
|
||||
|
||||
pub(crate) fn delete_bucket_monitor_entry(bucket: &str) {
|
||||
if let Some(monitor) = get_global_bucket_monitor() {
|
||||
monitor.delete_bucket(bucket);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn bucket_monitor() -> Option<Arc<Monitor>> {
|
||||
get_global_bucket_monitor()
|
||||
}
|
||||
|
||||
pub(crate) fn init_bucket_monitor_for_current_endpoints() {
|
||||
let num_nodes = get_global_endpoints().get_nodes().len().try_into().unwrap_or(u64::MAX);
|
||||
init_global_bucket_monitor(num_nodes);
|
||||
}
|
||||
|
||||
pub(crate) fn local_disk_map_handle() -> Arc<RwLock<HashMap<String, Option<DiskStore>>>> {
|
||||
GLOBAL_LOCAL_DISK_MAP.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn local_disk_id_map_handle() -> Arc<RwLock<HashMap<Uuid, String>>> {
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn local_disk_set_drives_handle() -> Arc<RwLock<TypeLocalDiskSetDrives>> {
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn tier_config_mgr_handle() -> Arc<RwLock<TierConfigMgr>> {
|
||||
GLOBAL_TierConfigMgr.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn expiry_state_handle() -> Arc<RwLock<ExpiryState>> {
|
||||
GLOBAL_ExpiryState.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn transition_state_handle() -> Arc<TransitionState> {
|
||||
GLOBAL_TransitionState.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn event_notifier_handle() -> Arc<RwLock<EventNotifier>> {
|
||||
GLOBAL_EventNotifier.clone()
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_by_path(path: &str) -> Option<DiskStore> {
|
||||
GLOBAL_LOCAL_DISK_MAP.read().await.get(path).cloned().flatten()
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_path_by_id(disk_id: &Uuid) -> Option<String> {
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.read().await.get(disk_id).cloned()
|
||||
}
|
||||
|
||||
pub(crate) async fn record_local_disk_id(disk_id: Uuid, endpoint: String) {
|
||||
GLOBAL_LOCAL_DISK_ID_MAP.write().await.insert(disk_id, endpoint);
|
||||
}
|
||||
|
||||
pub(crate) async fn replace_local_disk_id(previous: Option<Uuid>, current: Option<Uuid>, endpoint: String) {
|
||||
let mut disk_id_map = GLOBAL_LOCAL_DISK_ID_MAP.write().await;
|
||||
if let Some(previous_id) = previous {
|
||||
disk_id_map.remove(&previous_id);
|
||||
}
|
||||
if let Some(current_id) = current {
|
||||
disk_id_map.insert(current_id, endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn record_local_disks(disks: Vec<DiskStore>) {
|
||||
let mut global_local_disk_map = GLOBAL_LOCAL_DISK_MAP.write().await;
|
||||
for disk in disks {
|
||||
let path = disk.endpoint().to_string();
|
||||
global_local_disk_map.insert(path, Some(disk.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_set_drive(pool_idx: usize, set_idx: usize, disk_idx: usize) -> Option<DiskStore> {
|
||||
GLOBAL_LOCAL_DISK_SET_DRIVES.read().await[pool_idx][set_idx][disk_idx].clone()
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_for_endpoint(endpoint: &Endpoint) -> Option<DiskStore> {
|
||||
let global_set_drives = GLOBAL_LOCAL_DISK_SET_DRIVES.read().await;
|
||||
if global_set_drives.is_empty() {
|
||||
return GLOBAL_LOCAL_DISK_MAP
|
||||
.read()
|
||||
.await
|
||||
.get(&endpoint.to_string())
|
||||
.cloned()
|
||||
.unwrap_or(None);
|
||||
}
|
||||
|
||||
let pool_idx = usize::try_from(endpoint.pool_idx).ok()?;
|
||||
let set_idx = usize::try_from(endpoint.set_idx).ok()?;
|
||||
let disk_idx = usize::try_from(endpoint.disk_idx).ok()?;
|
||||
|
||||
global_set_drives
|
||||
.get(pool_idx)
|
||||
.and_then(|sets| sets.get(set_idx))
|
||||
.and_then(|disks| disks.get(disk_idx))
|
||||
.cloned()
|
||||
.unwrap_or(None)
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_paths() -> Vec<String> {
|
||||
GLOBAL_LOCAL_DISK_MAP.read().await.keys().cloned().collect()
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disks() -> Vec<DiskStore> {
|
||||
GLOBAL_LOCAL_DISK_MAP
|
||||
.read()
|
||||
.await
|
||||
.values()
|
||||
.filter_map(|v| v.as_ref().cloned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) async fn local_disk_entries() -> Vec<Option<DiskStore>> {
|
||||
GLOBAL_LOCAL_DISK_MAP.read().await.values().cloned().collect()
|
||||
}
|
||||
|
||||
pub(crate) async fn initialize_local_disk_maps(endpoint_pools: EndpointServerPools, opt: &DiskOption) -> Result<()> {
|
||||
let mut global_set_drives = GLOBAL_LOCAL_DISK_SET_DRIVES.write().await;
|
||||
for pool_eps in endpoint_pools.as_ref().iter() {
|
||||
let mut set_count_drives = Vec::with_capacity(pool_eps.set_count);
|
||||
for _ in 0..pool_eps.set_count {
|
||||
set_count_drives.push(vec![None; pool_eps.drives_per_set]);
|
||||
}
|
||||
|
||||
global_set_drives.push(set_count_drives);
|
||||
}
|
||||
|
||||
let mut global_local_disk_map = GLOBAL_LOCAL_DISK_MAP.write().await;
|
||||
|
||||
for pool_eps in endpoint_pools.as_ref().iter() {
|
||||
for ep in pool_eps.endpoints.as_ref().iter() {
|
||||
if !ep.is_local {
|
||||
continue;
|
||||
}
|
||||
|
||||
let disk = new_disk(ep, opt).await?;
|
||||
let path = disk.endpoint().to_string();
|
||||
let pool_idx = usize::try_from(ep.pool_idx).map_err(|err| {
|
||||
crate::error::Error::other(format!("store init failed to convert pool index `{}`: {err}", ep.pool_idx))
|
||||
})?;
|
||||
let set_idx = usize::try_from(ep.set_idx).map_err(|err| {
|
||||
crate::error::Error::other(format!("store init failed to convert set index `{}`: {err}", ep.set_idx))
|
||||
})?;
|
||||
let disk_idx = usize::try_from(ep.disk_idx).map_err(|err| {
|
||||
crate::error::Error::other(format!("store init failed to convert disk index `{}`: {err}", ep.disk_idx))
|
||||
})?;
|
||||
|
||||
global_local_disk_map.insert(path, Some(disk.clone()));
|
||||
global_set_drives[pool_idx][set_idx][disk_idx] = Some(disk.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn init_tier_config_mgr(store: Arc<ECStore>) -> Result<()> {
|
||||
GLOBAL_TierConfigMgr.write().await.init(store).await
|
||||
}
|
||||
Reference in New Issue
Block a user