Make use of indexes
This commit is contained in:
parent
2357ea8230
commit
8139112934
5 changed files with 120 additions and 27 deletions
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue