use super::*;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[repr(u8)]
pub enum SegmentLevel {
#[default]
Unleveled = 0,
L0 = 1,
L1 = 2,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SegmentMeta {
pub segment_id: u64,
pub file_path: PathBuf,
pub row_count: usize,
pub min_row_id: i64,
pub max_row_id: i64,
pub seal_seq: u64,
pub schema_version: u64,
pub level: SegmentLevel,
pub creation_epoch: u64,
}
#[cfg(any(test, feature = "test-hooks"))]
impl Default for SegmentMeta {
fn default() -> Self {
Self {
segment_id: 0,
file_path: PathBuf::new(),
row_count: 0,
min_row_id: 0,
max_row_id: 0,
seal_seq: 0,
schema_version: 0,
level: SegmentLevel::Unleveled,
creation_epoch: 0,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CompactionToken {
pub(super) table_name: SmartString,
pub(super) schema_epoch: u64,
pub(super) inputs: Vec<SegmentMeta>,
pub(super) tombstone_boundary: Option<u64>,
pub(super) target_level: SegmentLevel,
}
impl CompactionToken {
pub fn input_ids(&self) -> impl Iterator<Item = u64> + '_ {
self.inputs.iter().map(|input| input.segment_id)
}
pub fn schema_epoch(&self) -> u64 {
self.schema_epoch
}
pub fn tombstone_boundary(&self) -> Option<u64> {
self.tombstone_boundary
}
pub fn target_level(&self) -> SegmentLevel {
self.target_level
}
}
#[derive(Clone, Copy)]
pub(super) enum ReplacementExpectation<'a> {
Unchecked,
#[cfg(test)]
SegmentGeneration(u64),
Compaction(&'a CompactionToken),
}
pub struct SegmentRegistration {
pub segment_id: u64,
pub volume: Arc<FrozenVolume>,
pub meta: SegmentMeta,
}
impl SegmentRegistration {
pub fn new(segment_id: u64, volume: Arc<FrozenVolume>, meta: SegmentMeta) -> Self {
Self {
segment_id,
volume,
meta,
}
}
}
#[derive(Debug, Clone)]
pub struct TableManifest {
pub table_name: SmartString,
pub segments: Vec<SegmentMeta>,
pub next_segment_id: u64,
pub tombstones: Vec<(i64, u64)>,
pub column_renames: Vec<(SmartString, SmartString)>,
pub dropped_columns: Vec<(SmartString, u64)>,
}
impl TableManifest {
pub fn new(table_name: &str) -> Self {
Self {
table_name: SmartString::from(table_name),
segments: Vec::new(),
next_segment_id: 1,
tombstones: Vec::new(),
column_renames: Vec::new(),
dropped_columns: Vec::new(),
}
}
pub fn allocate_segment_id(&mut self) -> u64 {
let id = self.next_segment_id;
self.next_segment_id = self.next_segment_id.saturating_add(1);
id
}
pub fn add_segment(&mut self, meta: SegmentMeta) {
self.next_segment_id = self.next_segment_id.max(meta.segment_id.saturating_add(1));
self.segments.push(meta);
}
pub fn remove_segments(&mut self, ids: &[u64]) {
let id_set: FxHashSet<u64> = ids.iter().copied().collect();
self.segments
.retain(|segment| !id_set.contains(&segment.segment_id));
}
pub fn table_name(&self) -> &str {
self.table_name.as_str()
}
pub fn segments(&self) -> &[SegmentMeta] {
&self.segments
}
pub fn next_segment_id(&self) -> u64 {
self.next_segment_id
}
pub fn tombstones(&self) -> &[(i64, u64)] {
&self.tombstones
}
pub fn column_renames(&self) -> &[(SmartString, SmartString)] {
&self.column_renames
}
pub fn dropped_columns(&self) -> &[(SmartString, u64)] {
&self.dropped_columns
}
}