use crate::engine::property::{H5P__decode_hdfs_fapl_config, H5P__decode_ros3_fapl_config};
use crate::engine::vfd::{
CoreFileConfig, DirectFileConfig, FamilyFileConfig, H5FD__family_sb_decode,
H5FD__hdfs_validate_config, H5FD__log_sb_decode, H5FD__onion_sb_decode,
H5FD__ros3_validate_config, H5FD__splitter_sb_decode, H5FD__subfiling_sb_decode,
H5FD_multi_sb_decode, HdfsConfig, IocConfig, LogFileConfig, MultiFileConfig, OnionHeader,
Ros3Config, SplitterFileConfig, SubfilingConfig,
};
const ROS3_DEFAULT_PAGE_BUFFER_SIZE: usize = 64 * 1024 * 1024;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileAccess {
driver: String,
hdfs_config: Option<HdfsConfig>,
direct_config: Option<DirectFileConfig>,
family_config: Option<FamilyFileConfig>,
family_offset: Option<u64>,
multi_config: Option<MultiFileConfig>,
multi_type: Option<u32>,
ioc_config: Option<IocConfig>,
subfiling_config: Option<SubfilingConfig>,
splitter_config: Option<SplitterFileConfig>,
log_config: Option<LogFileConfig>,
onion_config: Option<OnionHeader>,
core_config: Option<CoreFileConfig>,
ros3_config: Option<Ros3Config>,
userblock: u64,
alignment: (u64, u64),
cache: (usize, usize, usize, u64),
gc_references: bool,
fclose_degree: FileCloseDegree,
meta_block_size: u64,
sieve_buf_size: usize,
small_data_block_size: u64,
libver_bounds: (LibverBound, LibverBound),
evict_on_close: bool,
file_locking: (bool, bool),
mdc_config: MetadataCacheConfig,
mdc_image_config: MetadataCacheImageConfig,
mdc_log_options: MetadataCacheLogOptions,
all_coll_metadata_ops: bool,
coll_metadata_write: bool,
page_buffer_size: (usize, u32, u32),
ros3_default_page_buffer_applied: bool,
core_write_tracking: bool,
map_iterate_hints: Option<String>,
object_flush_cb: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileCloseDegree {
Weak,
Semi,
Strong,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LibverBound {
Earliest,
V18,
V110,
V112,
V114,
Latest,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MetadataCacheConfig {
pub enabled: bool,
pub max_size: usize,
pub min_clean_size: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MetadataCacheImageConfig {
pub enabled: bool,
pub generation_enabled: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MetadataCacheLogOptions {
pub enabled: bool,
pub location: Option<String>,
pub start_on_access: bool,
}
impl Default for FileAccess {
fn default() -> Self {
Self {
driver: "sec2".to_string(),
hdfs_config: None,
direct_config: None,
family_config: None,
family_offset: None,
multi_config: None,
multi_type: None,
ioc_config: None,
subfiling_config: None,
splitter_config: None,
log_config: None,
onion_config: None,
core_config: None,
ros3_config: None,
userblock: 0,
alignment: (1, 1),
cache: (0, 521, 1024 * 1024, 0.75f64.to_bits()),
gc_references: false,
fclose_degree: FileCloseDegree::Weak,
meta_block_size: 2048,
sieve_buf_size: 64 * 1024,
small_data_block_size: 2048,
libver_bounds: (LibverBound::Earliest, LibverBound::Latest),
evict_on_close: false,
file_locking: (true, false),
mdc_config: MetadataCacheConfig {
enabled: false,
max_size: 0,
min_clean_size: 0,
},
mdc_image_config: MetadataCacheImageConfig {
enabled: false,
generation_enabled: false,
},
mdc_log_options: MetadataCacheLogOptions {
enabled: false,
location: None,
start_on_access: false,
},
all_coll_metadata_ops: false,
coll_metadata_write: false,
page_buffer_size: (0, 0, 0),
ros3_default_page_buffer_applied: false,
core_write_tracking: false,
map_iterate_hints: None,
object_flush_cb: false,
}
}
}
impl FileAccess {
fn clear_driver_specific_state(&mut self) {
if self.ros3_default_page_buffer_applied {
self.page_buffer_size = (0, 0, 0);
self.ros3_default_page_buffer_applied = false;
}
self.hdfs_config = None;
self.direct_config = None;
self.family_config = None;
self.family_offset = None;
self.multi_config = None;
self.multi_type = None;
self.ioc_config = None;
self.subfiling_config = None;
self.splitter_config = None;
self.log_config = None;
self.onion_config = None;
self.core_config = None;
self.core_write_tracking = false;
self.ros3_config = None;
}
pub(crate) fn from_file(file: &crate::hl::file::File) -> Self {
let mut plist = file.access_plist_snapshot();
plist.userblock = file.userblock();
plist
}
pub fn driver(&self) -> &str {
&self.driver
}
pub fn ensure_runtime_supported_driver(&self) -> crate::Result<()> {
match self.driver.as_str() {
"sec2" | "stdio" | "windows" => Ok(()),
driver => Err(crate::Error::Unsupported(format!(
"file access driver '{driver}' is not supported by the pure Rust local backend"
))),
}
}
pub fn set_driver<S: Into<String>>(&mut self, driver: S) {
self.clear_driver_specific_state();
self.driver = driver.into();
}
pub fn set_driver_by_name<S: Into<String>>(&mut self, driver: S) {
self.set_driver(driver);
}
pub fn set_driver_by_value(&mut self, driver_value: u64) {
self.clear_driver_specific_state();
self.driver = format!("driver_{driver_value}");
}
pub fn set_fapl_sec2(&mut self) {
self.clear_driver_specific_state();
self.driver = "sec2".to_string();
}
pub fn set_fapl_windows(&mut self) {
self.clear_driver_specific_state();
self.driver = "windows".to_string();
}
pub fn set_fapl_stdio(&mut self) {
self.clear_driver_specific_state();
self.driver = "stdio".to_string();
}
pub fn set_fapl_direct(&mut self, config: DirectFileConfig) {
self.clear_driver_specific_state();
self.driver = "direct".to_string();
self.direct_config = Some(config);
}
pub fn set_fapl_core(&mut self, config: CoreFileConfig) {
self.clear_driver_specific_state();
self.driver = "core".to_string();
self.core_config = Some(config);
}
pub fn set_fapl_family(&mut self, config: FamilyFileConfig) {
self.clear_driver_specific_state();
self.driver = "family".to_string();
self.family_config = Some(config);
}
pub fn set_fapl_family_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD__family_sb_decode(bytes)?;
self.set_fapl_family(config);
Ok(())
}
pub fn set_family_offset(&mut self, offset: Option<u64>) {
self.family_offset = offset;
}
pub fn set_fapl_multi(&mut self, config: MultiFileConfig) {
self.clear_driver_specific_state();
self.driver = "multi".to_string();
self.multi_config = Some(config);
}
pub fn set_fapl_multi_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD_multi_sb_decode(bytes)?;
self.set_fapl_multi(config);
Ok(())
}
pub fn set_multi_type(&mut self, memory_type: Option<u32>) {
self.multi_type = memory_type;
}
pub fn set_fapl_ioc(&mut self, config: IocConfig) {
self.clear_driver_specific_state();
self.driver = "ioc".to_string();
self.ioc_config = Some(config);
}
pub fn set_fapl_subfiling(&mut self, config: SubfilingConfig) {
self.clear_driver_specific_state();
self.driver = "subfiling".to_string();
self.subfiling_config = Some(config);
}
pub fn set_fapl_subfiling_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD__subfiling_sb_decode(bytes)?;
self.set_fapl_subfiling(config);
Ok(())
}
pub fn set_fapl_splitter(&mut self, config: SplitterFileConfig) {
self.clear_driver_specific_state();
self.driver = "splitter".to_string();
self.splitter_config = Some(config);
}
pub fn set_fapl_splitter_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD__splitter_sb_decode(bytes)?;
self.set_fapl_splitter(config);
Ok(())
}
pub fn set_fapl_log(&mut self, config: LogFileConfig) {
self.clear_driver_specific_state();
self.driver = "log".to_string();
self.log_config = Some(config);
}
pub fn set_fapl_log_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD__log_sb_decode(bytes)?;
self.set_fapl_log(config);
Ok(())
}
pub fn set_fapl_onion(&mut self, config: OnionHeader) {
self.clear_driver_specific_state();
self.driver = "onion".to_string();
self.onion_config = Some(config);
}
pub fn set_fapl_onion_from_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let config = H5FD__onion_sb_decode(bytes)?;
self.set_fapl_onion(config);
Ok(())
}
pub fn set_fapl_hdfs(&mut self, config: HdfsConfig) {
self.clear_driver_specific_state();
self.driver = "hdfs".to_string();
self.hdfs_config = Some(config);
}
pub fn set_fapl_hdfs_from_fapl_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let decoded = H5P__decode_hdfs_fapl_config(bytes)?;
let config = HdfsConfig {
namenode_name: decoded.namenode_name,
namenode_port: decoded.namenode_port,
user_name: decoded.user_name,
buffer_size: decoded.buffer_size,
};
if !H5FD__hdfs_validate_config(&config) {
return Err(crate::Error::InvalidFormat(
"invalid HDFS VFD config".into(),
));
}
self.set_fapl_hdfs(config);
Ok(())
}
pub fn set_fapl_ros3(&mut self, config: Ros3Config) {
self.clear_driver_specific_state();
self.driver = "ros3".to_string();
self.ros3_config = Some(config);
if self.page_buffer_size.0 == 0 {
self.page_buffer_size.0 = ROS3_DEFAULT_PAGE_BUFFER_SIZE;
self.ros3_default_page_buffer_applied = true;
}
}
pub fn set_fapl_ros3_from_fapl_config_image(&mut self, bytes: &[u8]) -> crate::Result<()> {
let decoded = H5P__decode_ros3_fapl_config(bytes)?;
let config = Ros3Config {
endpoint: decoded.endpoint,
region: decoded.region,
token: decoded.token,
};
if !H5FD__ros3_validate_config(&config) {
return Err(crate::Error::InvalidFormat(
"invalid ROS3 VFD config".into(),
));
}
self.set_fapl_ros3(config);
Ok(())
}
pub fn driver_info(&self) -> Option<()> {
None
}
pub fn userblock(&self) -> u64 {
self.userblock
}
pub fn set_userblock(&mut self, userblock: u64) -> bool {
if !crate::hl::plist::file_create::FileCreate::valid_userblock_size(userblock) {
return false;
}
self.userblock = userblock;
true
}
pub fn alignment(&self) -> (u64, u64) {
self.alignment
}
pub fn set_alignment(&mut self, threshold: u64, alignment: u64) -> bool {
if alignment == 0 {
return false;
}
self.alignment = (threshold, alignment);
true
}
pub fn cache(&self) -> (usize, usize, usize, f64) {
(
self.cache.0,
self.cache.1,
self.cache.2,
f64::from_bits(self.cache.3),
)
}
pub fn set_cache(
&mut self,
metadata_elements: usize,
raw_chunk_elements: usize,
raw_chunk_bytes: usize,
raw_chunk_preemption: f64,
) {
self.cache = (
metadata_elements,
raw_chunk_elements,
raw_chunk_bytes,
raw_chunk_preemption.to_bits(),
);
}
pub fn gc_references(&self) -> bool {
self.gc_references
}
pub fn set_gc_references(&mut self, enabled: bool) {
self.gc_references = enabled;
}
pub fn fclose_degree(&self) -> FileCloseDegree {
self.fclose_degree
}
pub fn set_fclose_degree(&mut self, degree: FileCloseDegree) {
self.fclose_degree = degree;
}
pub fn meta_block_size(&self) -> u64 {
self.meta_block_size
}
pub fn set_meta_block_size(&mut self, size: u64) {
self.meta_block_size = size;
}
pub fn sieve_buf_size(&self) -> usize {
self.sieve_buf_size
}
pub fn set_sieve_buf_size(&mut self, size: usize) {
self.sieve_buf_size = size;
}
pub fn small_data_block_size(&self) -> u64 {
self.small_data_block_size
}
pub fn set_small_data_block_size(&mut self, size: u64) {
self.small_data_block_size = size;
}
pub fn libver_bounds(&self) -> (LibverBound, LibverBound) {
self.libver_bounds
}
pub fn set_libver_bounds(&mut self, low: LibverBound, high: LibverBound) {
self.libver_bounds = (low, high);
}
pub fn evict_on_close(&self) -> bool {
self.evict_on_close
}
pub fn set_evict_on_close(&mut self, enabled: bool) {
self.evict_on_close = enabled;
}
pub fn file_locking(&self) -> (bool, bool) {
self.file_locking
}
pub fn set_file_locking(&mut self, enabled: bool, ignore_when_disabled: bool) {
self.file_locking = (enabled, ignore_when_disabled);
}
pub fn mdc_config(&self) -> MetadataCacheConfig {
self.mdc_config
}
pub fn mdc_config_ref(&self) -> &MetadataCacheConfig {
&self.mdc_config
}
pub fn set_mdc_config(&mut self, config: MetadataCacheConfig) {
self.mdc_config = config;
}
pub fn mdc_image_config(&self) -> MetadataCacheImageConfig {
self.mdc_image_config
}
pub fn mdc_image_config_ref(&self) -> &MetadataCacheImageConfig {
&self.mdc_image_config
}
pub fn set_mdc_image_config(&mut self, config: MetadataCacheImageConfig) {
self.mdc_image_config = config;
}
pub fn mdc_log_options(&self) -> MetadataCacheLogOptions {
self.mdc_log_options.clone()
}
pub fn mdc_log_options_ref(&self) -> &MetadataCacheLogOptions {
&self.mdc_log_options
}
pub fn set_mdc_log_options(&mut self, options: MetadataCacheLogOptions) {
self.mdc_log_options = options;
}
pub fn all_coll_metadata_ops(&self) -> bool {
self.all_coll_metadata_ops
}
pub fn set_all_coll_metadata_ops(&mut self, enabled: bool) {
self.all_coll_metadata_ops = enabled;
}
pub fn coll_metadata_write(&self) -> bool {
self.coll_metadata_write
}
pub fn set_coll_metadata_write(&mut self, enabled: bool) {
self.coll_metadata_write = enabled;
}
pub fn page_buffer_size(&self) -> (usize, u32, u32) {
self.page_buffer_size
}
pub fn set_page_buffer_size(
&mut self,
size: usize,
min_metadata_percent: u32,
min_raw_data_percent: u32,
) -> bool {
if (size == 0 && (min_metadata_percent != 0 || min_raw_data_percent != 0))
|| min_metadata_percent > 100
|| min_raw_data_percent > 100
|| min_metadata_percent.saturating_add(min_raw_data_percent) > 100
{
return false;
}
self.page_buffer_size = (size, min_metadata_percent, min_raw_data_percent);
self.ros3_default_page_buffer_applied = false;
true
}
pub fn fapl_hdfs(&self) -> Option<&HdfsConfig> {
self.hdfs_config.as_ref()
}
pub fn fapl_direct(&self) -> Option<&DirectFileConfig> {
self.direct_config.as_ref()
}
pub fn fapl_mirror(&self) -> Option<()> {
None
}
pub fn fapl_mpio(&self) -> Option<()> {
None
}
pub fn dxpl_mpio(&self) -> Option<()> {
None
}
pub fn fapl_family(&self) -> Option<&FamilyFileConfig> {
self.family_config.as_ref()
}
pub fn family_offset(&self) -> Option<u64> {
self.family_offset
}
pub fn multi_type(&self) -> Option<u32> {
self.multi_type
}
pub fn fapl_ioc(&self) -> Option<&IocConfig> {
self.ioc_config.as_ref()
}
pub fn fapl_subfiling(&self) -> Option<&SubfilingConfig> {
self.subfiling_config.as_ref()
}
pub fn fapl_splitter(&self) -> Option<&SplitterFileConfig> {
self.splitter_config.as_ref()
}
pub fn fapl_log(&self) -> Option<&LogFileConfig> {
self.log_config.as_ref()
}
pub fn fapl_multi(&self) -> Option<&MultiFileConfig> {
self.multi_config.as_ref()
}
pub fn fapl_onion(&self) -> Option<&OnionHeader> {
self.onion_config.as_ref()
}
pub fn core_write_tracking(&self) -> bool {
self.core_write_tracking
}
pub fn set_core_write_tracking(&mut self, enabled: bool) {
self.core_write_tracking = enabled;
}
pub fn fapl_core(&self) -> Option<&CoreFileConfig> {
self.core_config.as_ref()
}
pub fn fapl_ros3(&self) -> Option<&Ros3Config> {
self.ros3_config.as_ref()
}
pub fn fapl_ros3_endpoint(&self) -> Option<&str> {
self.ros3_config
.as_ref()
.and_then(|config| config.endpoint.as_deref())
}
pub fn object_flush_cb(&self) -> Option<()> {
self.object_flush_cb.then_some(())
}
pub fn set_object_flush_cb(&mut self, installed: bool) {
self.object_flush_cb = installed;
}
pub fn mpi_params(&self) -> Option<()> {
None
}
pub fn vol_id(&self) -> Option<()> {
None
}
pub fn vol_info(&self) -> Option<()> {
None
}
pub fn vol_cap_flags(&self) -> u64 {
0
}
pub fn relax_file_integrity_checks(&self) -> u64 {
0
}
pub fn map_iterate_hints(&self) -> Option<()> {
self.map_iterate_hints.as_ref().map(|_| ())
}
pub fn map_iterate_hints_ref(&self) -> Option<&str> {
self.map_iterate_hints.as_deref()
}
pub fn set_map_iterate_hints<S: Into<String>>(&mut self, hints: Option<S>) {
self.map_iterate_hints = hints.map(Into::into);
}
}