Rename cursor ~> file_position

This commit is contained in:
Yuriy Dupyn 2024-02-02 19:04:51 +01:00
parent cac34d95e0
commit 28741006e7
2 changed files with 81 additions and 46 deletions

View file

@ -15,7 +15,7 @@ use std::mem::size_of;
type Result<T> = std::result::Result<T, Error>;
pub type Column = u64;
pub type Cursor = u64;
pub type FilePosition = u64;
// TODO: Consider introducing a phantom type for the data that's used in the store.
#[derive(Debug)]
@ -24,6 +24,8 @@ pub struct Store<T> {
file: File,
header: StoreHeader,
data_type: PhantomData<T>,
eof_file_position: FilePosition,
// meta
// location of rows file
// locations of index files
@ -32,6 +34,10 @@ pub struct Store<T> {
// list
}
// TODO: Basically a pointer to Store + its own file position
// pub struct Cursor<'a, T> {
// }
#[derive(Debug)]
pub struct StoreHeader {
number_of_columns: usize,
@ -94,33 +100,41 @@ pub struct EntryDetailed<T> {
data: Vec<T>,
}
pub struct EntryIterator<'a> {
file: &'a mut File,
current_file_position: FilePosition
}
//===Store===
pub async fn store_exists(table_folder: &str) -> Result<bool> {
Ok(fs::metadata(table_folder).await.is_ok())
}
impl <T>Store<T> {
const ROWS_FILE_NAME: &'static str = "rows";
//===primitive file operations===
// Moves the cursor right.
// Moves the file cursor right.
async fn write_bytes(&mut self, bytes: &[u8]) -> Result<usize> {
Ok(self.file.write(bytes).await?)
}
// Moves the cursor right.
// Moves the file cursor right.
async fn read_bytes(&mut self, bytes: &mut [u8]) -> Result<()> {
self.file.read_exact(bytes).await?;
Ok(())
}
// Moves the cursor right.
// Moves the file cursor right.
async fn get_bytes(&mut self, count: usize) -> Result<Vec<u8>> {
let mut result: Vec<u8> = Vec::with_capacity(count);
self.read_bytes(&mut result).await?;
Ok(result)
}
async fn seek_to(&mut self, cursor: Cursor) -> Result<()>{
self.file.seek(SeekFrom::Start(cursor)).await?;
async fn seek_to(&mut self, file_position: FilePosition) -> Result<()>{
self.file.seek(SeekFrom::Start(file_position)).await?;
Ok(())
}
@ -138,13 +152,13 @@ impl <T>Store<T> {
self.seek_to(StoreHeader::SIZE as u64).await
}
async fn current_cursor(&mut self) -> Result<Cursor> {
let next_cursor: Cursor = self.file.stream_position().await?;
Ok(next_cursor)
async fn current_file_position(&mut self) -> Result<FilePosition> {
let next_file_position: FilePosition = self.file.stream_position().await?;
Ok(next_file_position)
}
// For debugging.
// Moves cursor to the end.
// Moves file cursor to the end.
pub async fn read_all_bytes(&mut self) -> std::result::Result<Vec<u8>, std::io::Error>{
let mut bytes: Vec<u8> = vec![];
self.seek_to_start().await.map_err(|e| e.to_io_or_panic())?;
@ -152,8 +166,6 @@ impl <T>Store<T> {
Ok(bytes)
}
const ROWS_FILE_NAME: &'static str = "rows";
// ===Creation===
pub async fn new(table_folder: &str, number_of_columns: usize, primary_column: Column) -> Result<Self> {
let path_to_table = Path::new(table_folder);
@ -177,15 +189,15 @@ impl <T>Store<T> {
};
let encoded_header: Vec<u8> = header.encode()?;
println!("ENCODED_HEADER: {:?}", encoded_header);
let mut store = Self {
table_folder: table_folder.to_string(),
file,
header,
data_type: PhantomData::<T>,
eof_file_position: 0,
};
store.write_bytes(&encoded_header).await?;
store.eof_file_position = store.current_file_position().await?;
Ok(store)
}
@ -208,13 +220,15 @@ impl <T>Store<T> {
file.read_exact(&mut header_bytes).await?;
let header = StoreHeader::decode(&mut header_bytes).await?;
let eof_file_position = file.seek(SeekFrom::End(0)).await?;
let store = Self {
table_folder: table_folder.to_string(),
file,
header,
data_type: PhantomData::<T>,
eof_file_position
};
println!("just connected TOOOOO {:?}", store);
Ok(store)
}
@ -236,24 +250,27 @@ impl <T>Store<T> {
}
// Moves cursor to the end.
pub async fn append_entry(&mut self, entry: &Entry<T>) -> Result<Cursor>
pub async fn append_entry(&mut self, entry: &Entry<T>) -> Result<FilePosition>
where T: Encode
{
self.increment_total_count().await?;
let encoded_entry: Vec<u8> = entry.encode()?;
self.seek_to_end().await?;
let cursor: Cursor = self.current_cursor().await?;
let file_position: FilePosition = self.current_file_position().await?;
self.write_bytes(&encoded_entry).await?;
Ok(cursor)
let eof_file_position: FilePosition = self.current_file_position().await?;
self.eof_file_position = eof_file_position;
Ok(file_position)
}
// ===Deletion===
pub async fn mark_deleted_at(&mut self, cursor: Cursor) -> Result<()> {
pub async fn mark_deleted_at(&mut self, file_position: FilePosition) -> Result<()> {
self.increment_deleted_count().await?;
self.seek_to(cursor).await?;
self.seek_to(file_position).await?;
// TODO: Now you need to mutate the entry itself
todo!()
@ -263,9 +280,8 @@ impl <T>Store<T> {
// ===Lookup===
// WARNING: The cursor has to be at the start of an entry. Otherwise garbage data will be
// decoded as an entry.
pub async fn read_entry_header_at(&mut self, cursor: Cursor) -> Result<EntryHeaderWithDataSize> {
self.seek_to(cursor).await?;
self.file.seek(SeekFrom::Start(cursor)).await?;
pub async fn read_entry_header_at(&mut self, file_position: FilePosition) -> Result<EntryHeaderWithDataSize> {
self.seek_to(file_position).await?;
let number_of_columns: usize = self.header.number_of_columns;
let mut header_bytes: Vec<u8> = vec![0; EntryHeaderWithDataSize::size(number_of_columns)];
@ -278,10 +294,15 @@ impl <T>Store<T> {
Ok(header)
}
pub async fn read_entry_at(&mut self, cursor: Cursor) -> Result<EntryDetailed<T>>
// Returns None when file_positoin == eof_file_position
pub async fn read_entry_at(&mut self, file_position: FilePosition) -> Result<Option<EntryDetailed<T>>>
where T: Decode
{
let header = self.read_entry_header_at(cursor).await?;
if file_position == self.eof_file_position {
return Ok(None)
}
let header = self.read_entry_header_at(file_position).await?;
let mut data_bytes: Vec<u8> = vec![0; header.size_of_data()];
// TODO: Get rid of the println's
@ -291,20 +312,31 @@ impl <T>Store<T> {
let entry: EntryDetailed<T> =
EntryDetailed::decode(header, self.header.number_of_columns, &mut data_bytes)?;
Ok(entry)
Ok(Some(entry))
}
pub async fn read_entries(&mut self, n: usize) -> Result<()>
// TODO: This needs to be some sort of an iterator
// pub async fn entries() -> EntryIterator<T> {
// todo!()
// }
pub async fn read_entries(&mut self) -> Result<()>
where T: Decode + std::fmt::Debug
{
self.seek_to_start_of_data().await?;
let mut cursor: Cursor = self.current_cursor().await?;
for i in 0..n {
let entry = self.read_entry_at(cursor).await?;
println!("({}, {:?})", i, entry);
cursor = self.current_cursor().await?;
let mut file_position: FilePosition = self.current_file_position().await?;
loop {
match self.read_entry_at(file_position).await? {
Some(entry) => {
println!("{:?}", entry);
file_position = self.current_file_position().await?;
},
None => {
println!("END of entries.");
return Ok(())
}
}
}
Ok(())
}
pub async fn search_for_entry_with_id(&mut self, id: T) -> Result<Option<EntryDetailed<T>>> {
@ -313,7 +345,7 @@ impl <T>Store<T> {
}
// TODO: This needs to be some sort of an iterator
pub async fn get_eq(&self, column: Column, value: T) -> Result<Option<EntryDetailed<T>>> {
pub async fn get_all_eq(&self, column: Column, value: T) -> Result<Option<EntryDetailed<T>>> {
todo!()
}