use std::io::Read;
use diskann::ANNResult;
use diskann_providers::storage::StorageReadProvider;
use tracing::info;
use crate::search::provider::aligned_file_reader::{traits::AlignedFileReader, AlignedRead, A1};
pub struct StorageProviderAlignedFileReader {
data: Vec<u8>,
}
impl StorageProviderAlignedFileReader {
pub fn new(
storage_provider: &impl StorageReadProvider,
file_name: &str,
) -> ANNResult<StorageProviderAlignedFileReader> {
info!("Loading data from {}", file_name);
let file_length = storage_provider.get_length(file_name)?;
let mut data = vec![0u8; file_length as usize];
storage_provider
.open_reader(file_name)?
.read_exact(&mut data)?;
Ok(StorageProviderAlignedFileReader { data })
}
}
impl AlignedFileReader for StorageProviderAlignedFileReader {
type Alignment = A1;
fn read(&mut self, read_requests: &mut [AlignedRead<u8, A1>]) -> ANNResult<()> {
for read in read_requests {
let offset = read.offset();
let len = read.aligned_buf().len();
let aligned_buf = read.aligned_buf_mut();
aligned_buf.copy_from_slice(&self.data[offset as usize..offset as usize + len]);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::io::{Seek, SeekFrom};
use diskann_providers::storage::VirtualStorageProvider;
use diskann_utils::test_data_root;
use super::*;
use diskann_quantization::alloc::{AlignedAllocator, Poly};
fn test_index_path() -> String {
"/disk_index_misc/disk_index_siftsmall_learn_256pts_R4_L50_A1.2_aligned_reader_test.index"
.to_string()
}
fn setup_reader() -> StorageProviderAlignedFileReader {
let storage_provider = VirtualStorageProvider::new_overlay(test_data_root());
StorageProviderAlignedFileReader::new(&storage_provider, &test_index_path()).unwrap()
}
#[test]
fn test_new_aligned_file_reader() {
let reader = setup_reader();
assert!(!(reader.data.is_empty()));
}
#[test]
fn test_read() {
let mut reader = setup_reader();
let read_length = 512;
let num_read = 10;
let mut aligned_mem =
Poly::broadcast(0u8, read_length * num_read, AlignedAllocator::A512).unwrap();
let mut mem_slices: Vec<&mut [u8]> = aligned_mem.chunks_mut(read_length).collect();
let mut aligned_reads: Vec<AlignedRead<'_, u8>> = mem_slices
.iter_mut()
.enumerate()
.map(|(i, slice)| {
let offset = (i * read_length) as u64;
AlignedRead::new(offset, slice).unwrap()
})
.collect();
let result = reader.read(&mut aligned_reads);
assert!(result.is_ok());
let file_system = VirtualStorageProvider::new_overlay(test_data_root());
let mut file = file_system.open_reader(&test_index_path()).unwrap();
for current_read in aligned_reads {
let offset = current_read.offset();
let mut expected = vec![0; current_read.aligned_buf().len()];
file.seek(SeekFrom::Start(offset)).unwrap();
file.read_exact(&mut expected).unwrap();
assert_eq!(
expected,
current_read.aligned_buf(),
"aligned_buf did not contain the expected data"
);
}
}
}