Make use of indexes

This commit is contained in:
Yuriy Dupyn 2024-02-04 23:54:22 +01:00
parent 2357ea8230
commit 8139112934
5 changed files with 120 additions and 27 deletions

View file

@ -245,18 +245,6 @@ pub trait CursorWithStoreHeader<T>: PrimitiveCursor<T> {
}
}
#[async_trait]
pub trait CursorWithAccessToIndex<T>: CursorWithStoreHeader<T> {
fn indexes(&mut self) -> &[Option<Index<T, FilePosition>>];
async fn find_in_index(&mut self, k: &T) -> Result<Option<FilePosition>>
where T: Encode + Decode + Ord + Send + Sync
{
// let x = self.primary_index().lookup(k).await?;
todo!()
}
}
#[async_trait]
pub trait CursorWithWriteStoreHeader<T>: CursorWithStoreHeader<T> + PrimitiveWriteCursor<T> {
fn header_mut(&mut self) -> &mut StoreHeader;
@ -287,7 +275,7 @@ pub trait CursorWithWriteStoreHeader<T>: CursorWithStoreHeader<T> + PrimitiveWri
// Moves cursor to the end.
// Returns file position to the start of the new entry.
async fn append_entry(&mut self, entry: &Entry<T>) -> Result<FilePosition>
async fn append_entry_no_indexing(&mut self, entry: &Entry<T>) -> Result<FilePosition>
where T: Encode + Send + Sync
{
self.increment_total_count().await?;
@ -303,6 +291,94 @@ pub trait CursorWithWriteStoreHeader<T>: CursorWithStoreHeader<T> + PrimitiveWri
}
}
#[async_trait]
pub trait CursorWithAccessToIndex<T>: CursorWithStoreHeader<T> {
fn indexes(&mut self) -> &[Option<Index<T, FilePosition>>];
async fn index_lookup(&mut self, column: Column, k: &T) -> Result<Vec<EntryDetailed<T>>>
where T: Encode + Decode + Ord + Send + Sync
{
match &self.indexes()[column as usize] {
Some(index) => {
let file_positions = index.lookup(k).await?.unwrap_or_else(|| HashSet::new());
let mut entries: Vec<EntryDetailed<T>> = vec![];
for &file_position in file_positions.iter() {
match self.read_entry_at(file_position).await? {
Some(entry) => {
entries.push(entry)
},
None => {
return Err(Error::IndexIsStoringEofFilePosition(column))
}
}
}
Ok(entries)
},
None =>
Err(Error::AttemptToIndexNonIndexableColumn(column))
}
}
// TODO: I also need the global find
async fn lookup(&mut self, column: Column, k: &T) -> Result<Vec<EntryDetailed<T>>> {
todo!()
}
}
#[async_trait]
pub trait CursorWithWriteAccessToIndex<T>: CursorWithAccessToIndex<T> + CursorWithWriteStoreHeader<T> {
fn indexes_mut(&mut self) -> &mut [Option<Index<T, FilePosition>>];
// Assumes that the column is indexable.
fn mut_index_at(&mut self, column: Column) -> &mut Index<T, FilePosition> {
match &mut self.indexes_mut()[column as usize] {
Some(index) => {
index
},
None => {
unreachable!()
}
}
}
// Assumes that the column is indexable.
async fn insert_into_index(&mut self, column: Column, value: T, file_position: FilePosition) -> Result<()>
where T: Encode + Decode + Ord + Send + Sync + 'async_trait
{
let index = self.mut_index_at(column as Column);
index.insert(value, file_position).await?;
Ok(())
}
// Assumes that the column is indexable.
async fn delete_from_index(&mut self, column: Column, value: T, file_position: FilePosition) -> Result<()>
where T: Encode + Decode + Ord + Send + Sync + 'async_trait
{
let index = self.mut_index_at(column as Column);
index.delete(value, file_position).await?;
Ok(())
}
async fn insert_entry(&mut self, entry: Entry<T>) -> Result<FilePosition>
// TODO: Why is 'async_trait necessary?
where T: Encode + Decode + Ord + Send + Sync + 'async_trait
{
let file_position = self.append_entry_no_indexing(&entry).await?;
// insert the indexable values of the entry into corresponding indexes.
for (column, (value, should_index)) in entry.data.into_iter().zip(self.header().indexed_columns.clone()).enumerate() {
if should_index {
// SAFETY: If should_index is true, then the column is indexable.
self.insert_into_index(column as Column, value, file_position).await?
}
}
Ok(file_position)
}
}
// ===========Implementations=============
// ===PrimitiveCursor===
impl <T>PrimitiveCursor<T> for ReadCursor<'_, T> {
@ -373,6 +449,10 @@ impl <T>CursorWithAccessToIndex<T> for WriteCursor<'_, T> {
fn indexes(&mut self) -> &[Option<Index<T, FilePosition>>] { &self.indexes }
}
// ===CursorWithWriteAccessToIndex===
impl <T>CursorWithWriteAccessToIndex<T> for WriteCursor<'_, T> {
fn indexes_mut(&mut self) -> &mut [Option<Index<T, FilePosition>>] { self.indexes }
}
impl <'cursor, T> ReadCursor<'cursor, T> {
@ -526,7 +606,7 @@ impl <'cursor, T> WriteCursor<'cursor, T>
{
while let Some(live_entry) = self.next_alive().await? {
entries_deleted += 1;
let file_position = cursor_to_intermediate.append_entry(&live_entry.forget()).await?;
let file_position = cursor_to_intermediate.append_entry_no_indexing(&live_entry.forget()).await?;
// TODO: Start indexing all of the indexable columns from scratch.
}
}