Implement remove for blockfile.

This commit is contained in:
yukirij 2025-04-15 17:48:03 -07:00
parent 48a62fc165
commit 2bb32e75b7
2 changed files with 116 additions and 9 deletions

View File

@ -6,17 +6,30 @@ async fn main()
{
std::fs::create_dir_all("data").ok();
println!("BLOCKFILE");
//println!("BLOCKFILE");
if let Ok(mut bf) = BlockFile::<16>::open("data/cache_data.bin").await {
if let Ok(id) = bf.insert("This is a test of the block file system.".as_bytes()).await {
let data = String::from_utf8(bf.get(id).await.unwrap()).unwrap();
println!("id {} = '{}'", id, data);
let op = 0;
if let Ok(mut bf) = BlockFile::<32>::open("data/cache_data.bin").await {
match op {
0 => {
for i in 0..1 {
if let Ok(id) = bf.insert(format!("{} This is a test of the block file system {}.", i, i).as_bytes()).await {
let data = String::from_utf8(bf.get(id).await.unwrap()).unwrap();
println!("id {} = '{}'", id, data);
}
}
}
1 => {
bf.remove(12).await.ok();
}
_ => { }
}
} else {
println!("Failed to open.");
}
/*
println!("TRIEFILE");
if let Ok(mut tf) = TrieFile::<8>::open("data/cache_index.bin").await {
@ -62,4 +75,5 @@ async fn main()
} else {
println!("Failed to open index.");
}
*/
}

View File

@ -4,6 +4,7 @@
** [Header:16]
** {AllocTable Head: <Depth:1> <Block:4> } (initial 0, 0)
** {ObjectTable Head: <Depth:1> <Block:4> } (initial 0, 1)
** {NextObject <Id:4>}
**
** [Object Table]
** { <Pointer:4> <Length:4> }*
@ -106,10 +107,7 @@ impl<const Z:usize> BlockFile<Z> {
// Allocate storage blocks
let block_count = Self::block_count_from_size(data.len());
//println!("block_count {}", block_count);
let blocks = self.allocate(block_count.max(1)).await?;
//println!("blocks {}", blocks.len());
// Get object id
let id = self.acquire_object(blocks[0], data.len()).await?;
@ -200,10 +198,28 @@ impl<const Z:usize> BlockFile<Z> {
Ok(())
}
pub async fn remove(&mut self, _id:usize) -> Result<(), std::io::Error>
pub async fn remove(&mut self, id:usize) -> Result<(), std::io::Error>
// Remove the object with the specified identifier and release its allocation.
//
{
let mut block_data = [0u8; Z];
let mut blocks = Vec::new();
let (mut block_id, _) = self.get_object(id).await?;
while block_id != 0 {
blocks.push(block_id);
self.read_block(block_id, &mut block_data).await?;
block_id = u32::unpack(&block_data, &mut (Z - 4)).unwrap_or_default();
}
// Remove object listing.
self.free_object(id).await?;
// Free allocated blocks.
self.release(&blocks).await?;
Ok(())
}
@ -466,6 +482,7 @@ impl<const Z:usize> BlockFile<Z> {
let mut b32 = [0u8; 4];
let mut block_data = [0u8; Z];
let zero = [0u8; Z];
// Read allocation table root block and depth from file.
self.file.seek(SeekFrom::Start(0)).await?;
@ -499,6 +516,8 @@ impl<const Z:usize> BlockFile<Z> {
block_data[byte as usize] &= !(1 << bit);
self.write_block(page, &block_data).await?;
self.write_block(block, &zero).await.ok();
}
Ok(())
@ -661,6 +680,80 @@ impl<const Z:usize> BlockFile<Z> {
Ok(object_id)
}
async fn free_object(&mut self, id:usize) -> Result<(),std::io::Error>
{
let mut block_data = [0u8; Z];
let mut b8 = [0u8; 1];
let mut b32 = [0u8; 4];
// Read allocation table root block and depth from file.
self.file.seek(SeekFrom::Start(5)).await?;
self.file.read_exact(&mut b8).await?;
let mut depth = b8[0] as u32;
self.file.read_exact(&mut b32).await?;
let mut block_id = u32::unpack(&b32, &mut 0).unwrap_or_default();
self.file.read_exact(&mut b32).await?;
let object_id = u32::unpack(&b32, &mut 0).unwrap_or_default() as usize;
let mut basis = 0;
// Search table for first vacant or unallocated child.
while depth > 0 {
/*
** Select child tables containing object_id until depth is 0.
*/
self.read_block(block_id, &mut block_data).await?;
let cell_index = (id - basis) / Self::table_offset(depth) as usize;
let cell_start = cell_index * 4;
let cell_data = u32::unpack(&block_data, &mut cell_start.clone()).unwrap_or_default();
let child_id = if cell_data != 0 {
u32::unpack(&block_data, &mut cell_start.clone()).unwrap_or_default()
} else {
return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "object id not valid"));
};
// Update frame of reference to child table.
block_id = child_id;
basis = Self::table_cell_offset(depth, cell_index as u32, basis as u32) as usize;
depth -= 1;
}
// Get object pointer and length from cell.
self.read_block(block_id, &mut block_data).await?;
let cell_index = (id - basis) / Self::table_offset(depth) as usize;
let cell_start = cell_index * 8;
// Set Id
let pack_location = (object_id as u32).pack();
block_data[cell_start] = pack_location[0];
block_data[cell_start + 1] = pack_location[1];
block_data[cell_start + 2] = pack_location[2];
block_data[cell_start + 3] = pack_location[3];
// Set Length
block_data[cell_start + 4] = 0;
block_data[cell_start + 5] = 0;
block_data[cell_start + 6] = 0;
block_data[cell_start + 7] = 0;
self.write_block(block_id, &block_data).await?;
// Update header with new pointer.
let pack_pointer = (id as u32).pack();
self.file.seek(SeekFrom::Start(10)).await?;
self.file.write(&pack_pointer).await?;
Ok(())
}
async fn get_object(&self, id:usize) -> Result<(u32, usize), std::io::Error>
// Find initial block and data size of an object.
//