use std::borrow::Cow;
use std::fmt::Debug;
use std::path::{Path, PathBuf};
use blink_alloc::Blink;
use crate::common::counter::hardware_counter::HardwareCounterCell;
use crate::common::storage_version::StorageVersion;
use crate::common::types::PointOffsetType;
use crate::common::universal_io::{
UioResult, UniversalIoError, UniversalRead, UniversalReadFs, UniversalWrite, UserData,
};
use super::posting_list_common::PostingListIter;
use crate::sparse::common::sparse_vector::RemappedSparseVector;
use crate::sparse::common::types::DimOffset;
use crate::sparse::index::inverted_index::inverted_index_ram::InvertedIndexRam;
pub mod inverted_index_compressed_immutable_ram;
pub mod inverted_index_compressed_mmap;
pub mod inverted_index_ram;
pub mod inverted_index_ram_builder;
pub const INDEX_FILE_NAME: &str = "inverted_index.dat";
pub trait InvertedIndexReadOnly<S: UniversalRead>: InvertedIndex {
fn open_ro_impl<Fs: UniversalReadFs<File = S>>(fs: &Fs, path: &Path) -> UioResult<Self>;
}
pub trait InvertedIndexReadWrite<S: UniversalWrite>: InvertedIndex {
fn open_rw_impl(fs: &S::Fs, path: &Path) -> UioResult<Self>;
fn from_ram_index_impl<P: AsRef<Path>>(
fs: &S::Fs,
ram_index: Cow<InvertedIndexRam>,
path: P,
) -> UioResult<Self>;
}
pub trait InvertedIndex: Sized + Debug + 'static {
type Iter<'a>: PostingListIter + Clone
where
Self: 'a;
type Version: StorageVersion;
fn is_on_disk(&self) -> bool;
fn open_ro<Fs: UniversalReadFs>(fs: &Fs, path: &Path) -> UioResult<Self>
where
Self: InvertedIndexReadOnly<Fs::File>,
{
Self::open_ro_impl(fs, path)
}
fn open_rw<Fs: UniversalReadFs>(fs: &Fs, path: &Path) -> UioResult<Self>
where
Self: InvertedIndexReadWrite<Fs::File>,
Fs::File: UniversalWrite<Fs = Fs>,
{
Self::open_rw_impl(fs, path)
}
fn save(&self, path: &Path) -> UioResult<()>;
fn get_batch<'a, U: UserData>(
&'a self,
ids: impl Iterator<Item = (U, DimOffset)>,
arena: &'a Blink,
hw_counter: &'a HardwareCounterCell,
callback: impl FnMut(U, Self::Iter<'a>) -> UioResult<()>,
) -> UioResult<()>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn posting_list_len_batch<U: UserData>(
&self,
ids: impl Iterator<Item = (U, DimOffset)>,
hw_counter: &HardwareCounterCell,
callback: impl FnMut(U, usize) -> UioResult<()>,
) -> UioResult<()>;
fn files(path: &Path) -> Vec<PathBuf>;
fn immutable_files(path: &Path) -> Vec<PathBuf>;
fn remove(&mut self, id: PointOffsetType, old_vector: RemappedSparseVector);
fn upsert(
&mut self,
id: PointOffsetType,
vector: RemappedSparseVector,
old_vector: Option<RemappedSparseVector>,
);
fn from_ram_index<P: AsRef<Path>, Fs: UniversalReadFs>(
fs: &Fs,
ram_index: Cow<InvertedIndexRam>,
path: P,
) -> UioResult<Self>
where
Self: InvertedIndexReadWrite<Fs::File>,
Fs::File: UniversalWrite<Fs = Fs>,
{
Self::from_ram_index_impl(fs, ram_index, path)
}
fn vector_count(&self) -> usize;
fn total_sparse_vectors_size(&self) -> usize;
fn max_index(&self) -> Option<DimOffset>;
}
pub(crate) fn out_of_bounds(id: DimOffset, len: usize) -> UniversalIoError {
UniversalIoError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("DimOffset {id} out of bounds. Index contains {len} posting lists."),
))
}
pub(crate) fn corrupted_index() -> UniversalIoError {
UniversalIoError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Sparse index is corrupted",
))
}