Connect store to indexes
This commit is contained in:
parent
f2c17d2e66
commit
8fd2d4ebf3
3 changed files with 64 additions and 36 deletions
|
|
@ -13,7 +13,7 @@ use crate::binary_coding::{encode, decode};
|
|||
use crate::entry::{Entry, EntryDetailed};
|
||||
use crate::entry_header::{EntryHeaderWithDataSize, EntryHeader};
|
||||
use crate::store_header::StoreHeader;
|
||||
use crate::storage_engine::{Store, FilePosition, Column, Result, ROWS_FILE_NAME, GARBAGE_COLLECTION_INTERMEDIATE_ROWS_FILE_NAME};
|
||||
use crate::storage_engine::{Store, FilePosition, Column, Result, StoreIndexes, ROWS_FILE_NAME, GARBAGE_COLLECTION_INTERMEDIATE_ROWS_FILE_NAME};
|
||||
use crate::index::Index;
|
||||
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ impl <'cursor, T> WriteCursor<'cursor, T>
|
|||
Ok(cursor)
|
||||
}
|
||||
|
||||
pub async fn connect<'header: 'cursor, 'indexes: 'cursor>(path_to_rows: &str, header: &'header mut StoreHeader, indexes: &'indexes mut Vec<Option<Index<T, FilePosition>>>) -> Result<Self>
|
||||
pub async fn connect<'header: 'cursor, 'indexes: 'cursor>(path_to_rows: &str, header: &'header mut StoreHeader, indexes: &'indexes mut StoreIndexes<T>) -> Result<Self>
|
||||
where T: Send
|
||||
{
|
||||
let file: File =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::marker::PhantomData;
|
||||
use std::path::Path;
|
||||
use tokio::fs::{DirBuilder, File, OpenOptions};
|
||||
use std::path::PathBuf;
|
||||
use tokio::fs::{File, OpenOptions};
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom};
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
|
@ -38,7 +38,7 @@ where
|
|||
K: Encode + Decode + Ord,
|
||||
V: Encode + Decode + Clone + Eq + Hash,
|
||||
{
|
||||
pub async fn new(file_name: &str) -> Result<Index<K, V>> {
|
||||
pub async fn new(file_name: PathBuf) -> Result<Index<K, V>> {
|
||||
let file: File = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
|
|
@ -56,7 +56,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
pub async fn connect(file_name: &str) -> Result<Index<K, V>> {
|
||||
pub async fn connect(file_name: PathBuf) -> Result<Index<K, V>> {
|
||||
let mut file: File = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
|
|
@ -124,7 +124,7 @@ mod tests {
|
|||
index.insert("bar".to_string(), 125).await.unwrap();
|
||||
index.insert("bar".to_string(), 126).await.unwrap();
|
||||
|
||||
let lookup = index.lookup("foo".to_string()).await.unwrap().unwrap();
|
||||
let lookup = index.lookup(&"foo".to_string()).await.unwrap().unwrap();
|
||||
assert_eq!(lookup.len(), 2);
|
||||
assert!(lookup.contains(&123));
|
||||
assert!(lookup.contains(&124));
|
||||
|
|
@ -139,7 +139,7 @@ mod tests {
|
|||
value_type: PhantomData::<u32>,
|
||||
};
|
||||
|
||||
let lookup = decoded.lookup("foo".to_string()).await.unwrap().unwrap();
|
||||
let lookup = decoded.lookup(&"foo".to_string()).await.unwrap().unwrap();
|
||||
assert_eq!(lookup.len(), 2);
|
||||
assert!(lookup.contains(&123));
|
||||
assert!(lookup.contains(&124));
|
||||
|
|
|
|||
|
|
@ -16,27 +16,16 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||
pub type Column = u64;
|
||||
pub type FilePosition = u64;
|
||||
|
||||
// TODO: Consider introducing a phantom type for the data that's used in the store.
|
||||
// TODO: Consider adding another type parameter for indexable values
|
||||
#[derive(Debug)]
|
||||
pub struct Store<T> {
|
||||
// TODO: This needs to track how many read-write cursors there are...?
|
||||
// RWMutex
|
||||
// {write: 0, read: n} ~> {write:0, read: n + 1} // create read
|
||||
// {write: 0, read: n + 1} ~> {write:0, read: n} // destroy read
|
||||
// {write: 0, read: 0} ~> {write: 1, read: 0} // create write
|
||||
// {write: 1, read: 0} ~> {write: 0, read: 0} // destroy write
|
||||
// primary_index: Vec<Index<T, FilePosition>>>,
|
||||
// indexes: Vec<Option<Index<T, HashSet<FilePosition>>>>,
|
||||
// primary_index: Index<PositionOfValue, PositionOfRow>,
|
||||
|
||||
// TODO: It's not good to have StoreHeader copied to all the cursors, since they may modify it.
|
||||
// How to sync?
|
||||
// All
|
||||
pub header: StoreHeader,
|
||||
pub data_type: PhantomData<T>,
|
||||
pub indexes: Vec<Option<Index<T, FilePosition>>>,
|
||||
pub indexes: StoreIndexes<T>,
|
||||
}
|
||||
|
||||
pub type StoreIndexes<T> = Vec<Option<Index<T, FilePosition>>>;
|
||||
|
||||
pub type PositionOfValue = FilePosition;
|
||||
pub type PositionOfRow = FilePosition;
|
||||
|
||||
|
|
@ -75,13 +64,7 @@ impl <T>Store<T> {
|
|||
// We don't need the file right now. Only cursors will later open it.
|
||||
Self::create_empty_rows_file(path_to_rows, &header).await?;
|
||||
|
||||
// TODO: I need to construct indexes
|
||||
// let primary_index: Index<T, FilePosition> = Index::new(
|
||||
// &format!("rows_{}", primary_column.to_string()),
|
||||
// ).await?;
|
||||
|
||||
// TODO
|
||||
let indexes = vec![];
|
||||
let indexes: StoreIndexes<T> = Self::create_initial_indexes(&header).await?;
|
||||
|
||||
let store = Self {
|
||||
header,
|
||||
|
|
@ -92,6 +75,42 @@ impl <T>Store<T> {
|
|||
Ok(store)
|
||||
}
|
||||
|
||||
pub fn path_to_index_file(header: &StoreHeader, column: Column) -> PathBuf {
|
||||
let path_to_table = Path::new(&header.table_folder);
|
||||
let path_to_index = path_to_table.join(&format!("{}_{}", ROWS_FILE_NAME, column.to_string()));
|
||||
path_to_index
|
||||
}
|
||||
|
||||
pub async fn create_empty_index_at(header: &StoreHeader, column: Column) -> Result<Index<T, FilePosition>>
|
||||
where T: Encode + Decode + Ord
|
||||
{
|
||||
let path_to_index = Self::path_to_index_file(&header, column);
|
||||
let index = Index::new(path_to_index).await?;
|
||||
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
pub async fn create_initial_indexes(header: &StoreHeader) -> Result<StoreIndexes<T>>
|
||||
where T: Encode + Decode + Ord
|
||||
{
|
||||
let mut result: StoreIndexes<T> = Vec::with_capacity(header.number_of_columns);
|
||||
for _ in 0..header.number_of_columns {
|
||||
result.push(None)
|
||||
}
|
||||
|
||||
result[header.primary_column as usize] = Some(Self::create_empty_index_at(&header, header.primary_column).await?);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn connect_index_at(header: &StoreHeader, column: Column) -> Result<Index<T, FilePosition>>
|
||||
where T: Encode + Decode + Ord
|
||||
{
|
||||
let path_to_index = Self::path_to_index_file(&header, column);
|
||||
let index: Index<T, FilePosition> = Index::connect(path_to_index).await?;
|
||||
Ok(index)
|
||||
}
|
||||
|
||||
pub async fn create_empty_rows_file(path_to_rows: PathBuf, header: &StoreHeader) -> Result<File> {
|
||||
let mut file: File =
|
||||
OpenOptions::new()
|
||||
|
|
@ -134,17 +153,26 @@ impl <T>Store<T> {
|
|||
};
|
||||
|
||||
|
||||
// let primary_index: Index<T, FilePosition> = Index::connect(
|
||||
// &format!("rows_{}", header.primary_column.to_string()),
|
||||
// ).await?;
|
||||
let indexes: StoreIndexes<T> = {
|
||||
let mut result = Vec::with_capacity(header.number_of_columns);
|
||||
for (column, &is_indexed) in header.indexed_columns.iter().enumerate() {
|
||||
if is_indexed {
|
||||
result.push(None)
|
||||
// TODO: Once index connect is working, uncomment this line (and remove the
|
||||
// above .push line
|
||||
// result.push(Some(Self::connect_index_at(&header, column as Column).await?))
|
||||
} else {
|
||||
result.push(None)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
let indexes = vec![];
|
||||
result
|
||||
};
|
||||
|
||||
let store = Self {
|
||||
header,
|
||||
data_type: PhantomData::<T>,
|
||||
indexes,
|
||||
indexes
|
||||
};
|
||||
Ok(store)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue