use wkv::{RANGE_INDEX_STUB_SIZE, RangeIndexStub, TreeTuning};
use super::range_index_manager__migration::MigrationError;
pub struct RangeIndexManager_Index;
impl RangeIndexManager_Index {
pub fn create_index(
tuning: TreeTuning,
storage_backend: u8,
tree_handle: u64,
value_span: &mut [u8],
) -> Result<(), MigrationError> {
if value_span.len() < RANGE_INDEX_STUB_SIZE {
return Err(MigrationError::Invalid(format!(
"CreateIndex: value span too small: {} < {RANGE_INDEX_STUB_SIZE}",
value_span.len()
)));
}
let stub = RangeIndexStub::new(
tree_handle,
tuning.cache_size as u64,
tuning.min_record_size as u32,
tuning.max_record_size as u32,
tuning.max_key_len as u32,
tuning.leaf_page_size as u32,
wkv::StorageBackendType::from_u8(storage_backend),
);
stub
.encode_into(&mut value_span[..RANGE_INDEX_STUB_SIZE])
.map_err(|e| MigrationError::Invalid(e.to_string()))
}
#[inline]
pub fn read_index(value: &[u8]) -> Option<RangeIndexStub> {
RangeIndexStub::decode_opt(value)
}
pub fn clear_flushed_flag(value_span: &mut [u8]) -> Result<(), MigrationError> {
RangeIndexStub::slice_set_flushed(value_span, false)
.map_err(|e| MigrationError::Invalid(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
const DISK: u8 = 0;
fn tuning(cache: usize, min: usize, max: usize, key_len: usize, leaf: usize) -> TreeTuning {
TreeTuning {
cache_size: cache,
min_record_size: min,
max_record_size: max,
max_key_len: key_len,
leaf_page_size: leaf,
}
}
#[test]
fn create_then_read_roundtrip() {
let mut span = [0u8; 64];
RangeIndexManager_Index::create_index(
tuning(16 * 1024 * 1024, 64, 1024, 128, 4096),
DISK,
0xDEAD_BEEF,
&mut span,
)
.unwrap();
let stub = RangeIndexManager_Index::read_index(&span).expect("stub decodable");
assert_eq!(stub.tree_handle, 0xDEAD_BEEF);
assert_eq!(stub.cache_size, 16 * 1024 * 1024);
assert_eq!(stub.min_record_size, 64);
assert_eq!(stub.max_record_size, 1024);
assert_eq!(stub.max_key_len, 128);
assert_eq!(stub.leaf_page_size, 4096);
assert_eq!(stub.storage_backend, DISK);
assert_eq!(stub.flags, 0);
assert_eq!(stub.serialization_phase, 0);
assert!(!stub.is_flushed());
}
#[test]
fn create_index_rejects_short_span() {
let mut span = [0u8; RANGE_INDEX_STUB_SIZE - 1];
let err =
RangeIndexManager_Index::create_index(TreeTuning::default(), DISK, 0, &mut span).unwrap_err();
assert!(err.to_string().contains("value span too small"));
}
#[test]
fn read_index_returns_none_for_non_stub_span() {
assert!(RangeIndexManager_Index::read_index(&[]).is_none());
assert!(RangeIndexManager_Index::read_index(&[0u8; 8]).is_none());
}
#[test]
fn clear_flushed_flag_flips_only_that_bit() {
let mut span = [0u8; 64];
RangeIndexManager_Index::create_index(tuning(1, 8, 64, 16, 512), DISK, 7, &mut span).unwrap();
RangeIndexStub::slice_set_flushed(&mut span, true).unwrap();
assert!(
RangeIndexManager_Index::read_index(&span)
.unwrap()
.is_flushed()
);
RangeIndexManager_Index::clear_flushed_flag(&mut span).unwrap();
let stub = RangeIndexManager_Index::read_index(&span).unwrap();
assert!(!stub.is_flushed());
assert_eq!(stub.tree_handle, 7);
assert_eq!(stub.max_key_len, 16);
let mut short = [0u8; 4];
assert!(RangeIndexManager_Index::clear_flushed_flag(&mut short).is_err());
}
}