Add overflow error handling to WritableDataPage. Add IO tests.

This commit is contained in:
femsci 2023-03-09 16:11:43 +01:00
parent 53e5bd81af
commit de6287c6c5
Signed by: femsci
GPG key ID: 08F7911F0E650C67
3 changed files with 58 additions and 6 deletions

View file

@ -3,7 +3,7 @@ use std::io::{Read, Seek, SeekFrom, Write};
pub trait DataPager { pub trait DataPager {
fn get_page(&mut self, offset: usize) -> Result<&mut DataPage, String>; fn get_page(&mut self, offset: usize) -> Result<&mut DataPage, String>;
fn update_page(&mut self, page: WritableDataPage) -> Result<u64, ()>; fn update_page(&mut self, page: DataPage) -> Result<u64, ()>;
} }
#[derive(PartialEq, Eq, Hash)] #[derive(PartialEq, Eq, Hash)]
@ -67,6 +67,16 @@ impl Seek for DataPage {
} }
} }
impl Clone for DataPage {
fn clone(&self) -> Self {
Self {
offset: self.offset,
pos: self.pos,
data: self.data.clone(),
}
}
}
impl DataPage { impl DataPage {
pub(crate) fn load(offset: usize, data: Vec<u8>) -> Self { pub(crate) fn load(offset: usize, data: Vec<u8>) -> Self {
DataPage { DataPage {
@ -108,6 +118,13 @@ impl Write for WritableDataPage<'_> {
return Ok(0); return Ok(0);
} }
if pos + buf.len() > self.page.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::OutOfMemory,
"A write operation would overflow the block.",
));
}
self.page.data[pos..pos + len].copy_from_slice(&buf); self.page.data[pos..pos + len].copy_from_slice(&buf);
Ok(len) Ok(len)
@ -118,6 +135,12 @@ impl Write for WritableDataPage<'_> {
} }
} }
impl Seek for WritableDataPage<'_> {
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
self.page.seek(pos)
}
}
impl WritableDataPage<'_> { impl WritableDataPage<'_> {
pub fn data(&self) -> &[u8] { pub fn data(&self) -> &[u8] {
self.page.buffer() self.page.buffer()
@ -126,6 +149,10 @@ impl WritableDataPage<'_> {
pub fn offset(&self) -> usize { pub fn offset(&self) -> usize {
self.page.offset() self.page.offset()
} }
pub fn finish(&self) -> DataPage {
self.page.clone()
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -1,7 +1,7 @@
use std::{ use std::{
collections::hash_map::DefaultHasher, collections::hash_map::DefaultHasher,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
io::{Read, Seek, SeekFrom}, io::{Read, Seek, SeekFrom, Write},
}; };
use crate::data::{DataPage, DataPager}; use crate::data::{DataPage, DataPager};
@ -179,10 +179,12 @@ impl LocalStore {
node.children.push(entry); node.children.push(entry);
let mut block = block.mutate();
block.seek(SeekFrom::Start(position)).unwrap(); block.seek(SeekFrom::Start(position)).unwrap();
node.serialize(&self.meta); block.write(&node.serialize(&self.meta)).unwrap();
let page = block.finish();
//todo serialize self.io.update_page(page).unwrap();
todo!() todo!()
} }

View file

@ -32,9 +32,9 @@ impl DataPager for DataAccessor {
Ok(self.cache.get_mut(&offset).unwrap()) Ok(self.cache.get_mut(&offset).unwrap())
} }
fn update_page(&mut self, page: crate::data::WritableDataPage) -> Result<u64, ()> { fn update_page(&mut self, page: crate::data::DataPage) -> Result<u64, ()> {
self.dirty_pages self.dirty_pages
.push(DataPage::load(page.offset(), page.data().to_vec())); .push(DataPage::load(page.offset(), page.buffer().to_vec()));
return Ok(1); return Ok(1);
} }
} }
@ -60,3 +60,26 @@ impl DataAccessor {
} }
} }
} }
#[cfg(test)]
mod tests {
use std::io::{Seek, Write};
use crate::data::DataPage;
#[test]
fn data_page_update() {
let data = vec![2, 1, 3, 7, 0, 0, 0];
let mut page = DataPage::load(127, data);
page.seek(std::io::SeekFrom::Start(2)).unwrap();
let mut writable = page.mutate();
writable.write(&[4, 8, 6, 9, 5]).unwrap();
let page_mod = writable.finish();
println!("{:?}", page.buffer());
assert!(page.buffer().eq(&[2, 1, 4, 8, 6, 9, 5]));
assert!(page_mod.buffer().eq(&[2, 1, 4, 8, 6, 9, 5]));
}
}