use super::*;
impl FileMeta {
pub fn is_compatible_with_meta(&self) -> bool {
if self.meta_ver != XL_META_VERSION {
return false;
}
true
}
pub fn validate_integrity(&self) -> Result<()> {
if !self.is_sorted_by_mod_time() {
return Err(Error::other("versions not sorted by modification time"));
}
self.data.validate()?;
Ok(())
}
pub(crate) fn is_sorted_by_mod_time(&self) -> bool {
if self.versions.len() <= 1 {
return true;
}
for i in 1..self.versions.len() {
let prev_time = self.versions[i - 1].header.mod_time;
let curr_time = self.versions[i].header.mod_time;
match (prev_time, curr_time) {
(Some(prev), Some(curr)) => {
if prev < curr {
return false;
}
}
(None, Some(_)) => return false,
_ => continue,
}
}
true
}
pub fn get_version_stats(&self) -> VersionStats {
let mut stats = VersionStats {
total_versions: self.versions.len(),
..Default::default()
};
for version in &self.versions {
match version.header.version_type {
VersionType::Object => stats.object_versions += 1,
VersionType::Delete => stats.delete_markers += 1,
VersionType::Invalid | VersionType::Legacy => stats.invalid_versions += 1,
}
if version.header.free_version() {
stats.free_versions += 1;
}
}
stats
}
}
#[derive(Debug, Default, Clone)]
pub struct VersionStats {
pub total_versions: usize,
pub object_versions: usize,
pub delete_markers: usize,
pub invalid_versions: usize,
pub free_versions: usize,
}
impl FileMetaVersionHeader {
pub fn is_valid(&self) -> bool {
if !self.version_type.valid() {
return false;
}
if let Some(mod_time) = self.mod_time {
let now = OffsetDateTime::now_utc();
let future_limit = now + time::Duration::hours(24); if mod_time > future_limit {
return false;
}
}
if self.has_ec() && (self.ec_n == 0 || self.ec_m == 0 || self.ec_m < self.ec_n) {
return false;
}
true
}
}
#[derive(Debug, Default, Clone)]
pub struct DetailedVersionStats {
pub total_versions: usize,
pub object_versions: usize,
pub delete_markers: usize,
pub invalid_versions: usize,
pub legacy_versions: usize,
pub free_versions: usize,
pub versions_with_data_dir: usize,
pub versions_with_inline_data: usize,
pub total_size: i64,
pub latest_mod_time: Option<OffsetDateTime>,
}
impl FileMeta {
pub fn get_detailed_version_stats(&self) -> DetailedVersionStats {
let mut stats = DetailedVersionStats {
total_versions: self.versions.len(),
..Default::default()
};
for version in &self.versions {
match version.header.version_type {
VersionType::Object => {
stats.object_versions += 1;
if let Ok(ver) = FileMetaVersion::try_from(version.meta.as_slice())
&& let Some(obj) = &ver.object
{
stats.total_size += obj.size;
if obj.uses_data_dir() {
stats.versions_with_data_dir += 1;
}
if obj.inlinedata() {
stats.versions_with_inline_data += 1;
}
}
}
VersionType::Delete => stats.delete_markers += 1,
VersionType::Legacy => stats.legacy_versions += 1,
VersionType::Invalid => stats.invalid_versions += 1,
}
if version.header.free_version() {
stats.free_versions += 1;
}
if stats.latest_mod_time.is_none()
|| (version.header.mod_time.is_some() && version.header.mod_time > stats.latest_mod_time)
{
stats.latest_mod_time = version.header.mod_time;
}
}
stats
}
}