use crate::Result;
use crate::config::table::HudiTableConfig::{TimelineHistoryPath, TimelinePath};
use crate::error::CoreError;
use crate::metadata::HUDI_METADATA_DIR;
use crate::storage::Storage;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[cfg(not(tarpaulin_include))]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimelineManifest {
pub version: i64,
pub entries: Vec<ManifestEntry>,
}
#[cfg(not(tarpaulin_include))]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestEntry {
pub file_name: String,
pub min_instant: String,
pub max_instant: String,
pub level: i32,
pub file_size: i64,
}
#[cfg(not(tarpaulin_include))]
pub struct LSMTree {
storage: Arc<Storage>,
}
#[cfg(not(tarpaulin_include))]
impl LSMTree {
pub fn new(storage: Arc<Storage>) -> Self {
Self { storage }
}
pub fn timeline_dir(&self) -> String {
let timeline_path: String = self
.storage
.hudi_configs
.get_or_default(TimelinePath)
.into();
format!("{HUDI_METADATA_DIR}/{timeline_path}")
}
pub fn history_dir(&self) -> String {
let timeline_path: String = self
.storage
.hudi_configs
.get_or_default(TimelinePath)
.into();
let history_path: String = self
.storage
.hudi_configs
.get_or_default(TimelineHistoryPath)
.into();
format!("{HUDI_METADATA_DIR}/{timeline_path}/{history_path}")
}
pub async fn read_manifest(&self) -> Result<Option<TimelineManifest>> {
let history_dir = self.history_dir();
let version_path = format!("{history_dir}/_version_");
if let Ok(data) = self.storage.get_file_data(&version_path).await {
let version_str =
String::from_utf8(data.to_vec()).map_err(|e| CoreError::Timeline(e.to_string()))?;
let version = version_str
.trim()
.parse::<i64>()
.map_err(|e| CoreError::Timeline(e.to_string()))?;
let manifest_path = format!("{history_dir}/manifest_{version}");
let data = self.storage.get_file_data(&manifest_path).await?;
let manifest: TimelineManifest =
serde_json::from_slice(&data).map_err(|e| CoreError::Timeline(e.to_string()))?;
Ok(Some(manifest))
} else {
Ok(None)
}
}
}