use std::{fs, path::Path}; use brk_core::Result; use brk_vecs::{File, PAGE_SIZE}; fn main() -> Result<()> { let _ = fs::remove_dir_all("vecs"); let file = File::open(Path::new("vecs"))?; // file.set_min_len(PAGE_SIZE * 1_000_000)?; let region1_i = file.create_region_if_needed("region1")?; { let layout = file.layout(); assert!(layout.start_to_index().len() == 1); assert!(layout.start_to_index().first_key_value() == Some((&0, &0))); assert!(layout.start_to_hole().is_empty()); let regions = file.regions(); assert!( regions .get_region_index_from_id("region1") .is_some_and(|i| i == region1_i) ); let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 0); assert!(region.reserved() == PAGE_SIZE); } file.write_all_to_region(region1_i, &[0, 1, 2, 3, 4])?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 5); assert!(region.reserved() == PAGE_SIZE); assert!(file.mmap()[0..10] == [0, 1, 2, 3, 4, 0, 0, 0, 0, 0]); } file.write_all_to_region(region1_i, &[5, 6, 7, 8, 9])?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 10); assert!(region.reserved() == PAGE_SIZE); assert!(file.mmap()[0..10] == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); } file.write_all_to_region_at(region1_i, &[1, 2], 0)?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 10); assert!(region.reserved() == PAGE_SIZE); assert!(file.mmap()[0..10] == [1, 2, 2, 3, 4, 5, 6, 7, 8, 9]); } file.write_all_to_region_at(region1_i, &[10, 11, 12, 13, 14, 15, 16, 17, 18], 4)?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 13); assert!(region.reserved() == PAGE_SIZE); assert!( file.mmap()[0..20] == [ 1, 2, 2, 3, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0 ] ); } file.write_all_to_region_at(region1_i, &[1], 18)?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 19); assert!(region.reserved() == PAGE_SIZE); assert!( file.mmap()[0..20] == [ 1, 2, 2, 3, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0, 0, 0, 0, 0, 1, 0 ] ); } file.write_all_to_region_at(region1_i, &[1; 8000], 0)?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 8000); assert!(region.reserved() == PAGE_SIZE * 2); assert!(file.mmap()[0..8000] == [1; 8000]); assert!(file.mmap()[8000..8001] == [0]); } println!("Disk usage - pre sync: {}", file.disk_usage()); file.sync_data()?; println!("Disk usage - post sync: {}", file.disk_usage()); file.truncate_region(region1_i, 10)?; { let region = file.get_region(region1_i)?; assert!(region.start() == 0); assert!(region.len() == 10); assert!(region.reserved() == PAGE_SIZE * 2); // We only punch a hole in whole pages (4096 bytes) // Thus the last byte of the page where the is still data wasn't overwritten when truncating // And the first byte of the punched page was set to 0 assert!(file.mmap()[4095..=4096] == [1, 0]); } file.sync_data()?; println!("Disk usage - post trunc: {}", file.disk_usage()); file.remove_region(region1_i)?; println!("Disk usage - post remove: {}", file.disk_usage()); { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 1); assert!(index_to_region[0].is_none()); assert!(regions.id_to_index().is_empty()); let layout = file.layout(); assert!(layout.start_to_index().is_empty()); assert!(layout.start_to_hole().is_empty()); } let region1_i = file.create_region_if_needed("region1")?; let region2_i = file.create_region_if_needed("region2")?; let region3_i = file.create_region_if_needed("region3")?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 0); assert!(region1.reserved() == PAGE_SIZE); let region2 = file.get_region(region2_i)?; assert!(region2.start() == PAGE_SIZE); assert!(region2.len() == 0); assert!(region2.reserved() == PAGE_SIZE); let region3 = file.get_region(region3_i)?; assert!(region3.start() == PAGE_SIZE * 2); assert!(region3.len() == 0); assert!(region3.reserved() == PAGE_SIZE); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 3); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2") == Some(&1)); assert!(id_to_index.get("region3") == Some(&2)); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 3); assert!(start_to_index.get(&0) == Some(&0)); assert!(start_to_index.get(&PAGE_SIZE) == Some(&1)); assert!(start_to_index.get(&(PAGE_SIZE * 2)) == Some(&2)); assert!(layout.start_to_hole().is_empty()); } file.remove_region(region2_i)?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 0); assert!(region1.reserved() == PAGE_SIZE); assert!(file.get_region(region2_i).is_err()); assert!( index_to_region .get(region2_i) .is_some_and(|opt| opt.is_none()) ); let region3 = file.get_region(region3_i)?; assert!(region3.start() == PAGE_SIZE * 2); assert!(region3.len() == 0); assert!(region3.reserved() == PAGE_SIZE); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 2); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2").is_none()); assert!(id_to_index.get("region3") == Some(&2)); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 2); assert!(start_to_index.get(&0) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 2)) == Some(®ion3_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.len() == 1); assert!(start_to_hole.get(&PAGE_SIZE) == Some(&PAGE_SIZE)); drop(regions); drop(layout); assert!(file.remove_region(region2_i).is_ok_and(|o| o.is_none())); } let region2_i = file.create_region_if_needed("region2")?; { assert!(region2_i == 1) } file.remove_region(region2_i)?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 0); assert!(region1.reserved() == PAGE_SIZE); assert!(file.get_region(region2_i).is_err()); assert!( index_to_region .get(region2_i) .is_some_and(|opt| opt.is_none()) ); let region3 = file.get_region(region3_i)?; assert!(region3.start() == PAGE_SIZE * 2); assert!(region3.len() == 0); assert!(region3.reserved() == PAGE_SIZE); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 2); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2").is_none()); assert!(id_to_index.get("region3") == Some(&2)); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 2); assert!(start_to_index.get(&0) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 2)) == Some(®ion3_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.len() == 1); assert!(start_to_hole.get(&PAGE_SIZE) == Some(&PAGE_SIZE)); drop(regions); drop(layout); assert!(file.remove_region(region2_i).is_ok_and(|o| o.is_none())); } file.write_all_to_region_at(region1_i, &[1; 8000], 0)?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 8000); assert!(region1.reserved() == 2 * PAGE_SIZE); assert!(file.get_region(region2_i).is_err()); assert!( index_to_region .get(region2_i) .is_some_and(|opt| opt.is_none()) ); let region3 = file.get_region(region3_i)?; assert!(region3.start() == PAGE_SIZE * 2); assert!(region3.len() == 0); assert!(region3.reserved() == PAGE_SIZE); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 2); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2").is_none()); assert!(id_to_index.get("region3") == Some(&2)); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 2); assert!(start_to_index.get(&0) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 2)) == Some(®ion3_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.is_empty()); } let region2_i = file.create_region_if_needed("region2")?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 8000); assert!(region1.reserved() == 2 * PAGE_SIZE); let region2 = file.get_region(region2_i)?; assert!(region2.start() == PAGE_SIZE * 3); assert!(region2.len() == 0); assert!(region2.reserved() == PAGE_SIZE); let region3 = file.get_region(region3_i)?; assert!(region3.start() == PAGE_SIZE * 2); assert!(region3.len() == 0); assert!(region3.reserved() == PAGE_SIZE); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 3); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2") == Some(&1)); assert!(id_to_index.get("region3") == Some(&2)); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 3); assert!(start_to_index.get(&0) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 2)) == Some(®ion3_i)); assert!(start_to_index.get(&(PAGE_SIZE * 3)) == Some(®ion2_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.is_empty()); } file.remove_region(region3_i)?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == 0); assert!(region1.len() == 8000); assert!(region1.reserved() == 2 * PAGE_SIZE); let region2 = file.get_region(region2_i)?; assert!(region2.start() == PAGE_SIZE * 3); assert!(region2.len() == 0); assert!(region2.reserved() == PAGE_SIZE); assert!(file.get_region(region3_i).is_err()); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 2); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2") == Some(&1)); assert!(id_to_index.get("region3").is_none()); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 2); assert!(start_to_index.get(&0) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 3)) == Some(®ion2_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.get(&(PAGE_SIZE * 2)) == Some(&PAGE_SIZE)); } file.write_all_to_region(region1_i, &[1; 8000])?; { let regions = file.regions(); let index_to_region = regions.index_to_region(); assert!(index_to_region.len() == 3); let region1 = file.get_region(region1_i)?; assert!(region1.start() == PAGE_SIZE * 4); assert!(region1.len() == 16_000); assert!(region1.reserved() == 4 * PAGE_SIZE); let region2 = file.get_region(region2_i)?; assert!(region2.start() == PAGE_SIZE * 3); assert!(region2.len() == 0); assert!(region2.reserved() == PAGE_SIZE); assert!(file.get_region(region3_i).is_err()); let id_to_index = regions.id_to_index(); assert!(id_to_index.len() == 2); assert!(id_to_index.get("region1") == Some(&0)); assert!(id_to_index.get("region2") == Some(&1)); assert!(id_to_index.get("region3").is_none()); let layout = file.layout(); let start_to_index = layout.start_to_index(); assert!(start_to_index.len() == 2); assert!(start_to_index.get(&(PAGE_SIZE * 4)) == Some(®ion1_i)); assert!(start_to_index.get(&(PAGE_SIZE * 3)) == Some(®ion2_i)); let start_to_hole = layout.start_to_hole(); assert!(start_to_hole.get(&0) == Some(&(PAGE_SIZE * 3))); } file.write_all_to_region(region2_i, &[1; 6000])?; let region4_i = file.create_region_if_needed("region4")?; file.remove_region(region2_i); file.remove_region(region4_i); dbg!(file.regions()); dbg!(file.layout()); Ok(()) }