mirror of
https://github.com/qdrant/qdrant.git
synced 2026-08-02 08:00:55 -05:00
[UIO] Genericize ChunkedVectors.status (#8928)
* genericize ChunkedVectors.status, remove `Sized` bound * check exists with `UniversalReadFileOps` * Inline UioChunkedVectors bound, drop the alias (#8952) The empty trait + blanket impl was a stable-Rust trait-alias workaround that hid a fairly short bound (UniversalWrite<T> + UniversalWrite<Status> + Send + 'static) at the cost of an indirection readers had to mentally unwind. Spelling it out at the three sites that need it is shorter overall and immediately tells the reader what is required. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Andrey Vasnetsov <andrey@vasnetsov.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ fn check_mmap_file_name_pattern(file_name: &str) -> Option<usize> {
|
||||
.and_then(|file_name| file_name.parse::<usize>().ok())
|
||||
}
|
||||
|
||||
pub fn read_chunks<T: Sized + Copy + 'static, S: UniversalRead<T>>(
|
||||
pub fn read_chunks<T: Copy + 'static, S: UniversalRead<T>>(
|
||||
directory: &Path,
|
||||
advice: AdviceSetting,
|
||||
populate: bool,
|
||||
|
||||
@@ -7,6 +7,7 @@ pub(super) const MMAP_CHUNKS_PATTERN_START: &str = "chunk_";
|
||||
// TODO: rename for other storages?
|
||||
pub(super) const MMAP_CHUNKS_PATTERN_END: &str = ".mmap";
|
||||
|
||||
#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct Status {
|
||||
pub len: usize,
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::vector_storage::{VectorOffset, VectorOffsetType};
|
||||
/// not refreshed afterwards. Mutating storage uses [`super::ChunkedVectors`]
|
||||
/// which wraps this and adds a writable status mmap.
|
||||
#[derive(Debug)]
|
||||
pub struct ChunkedVectorsRead<T: Copy + Sized + 'static, S: UniversalRead<T>> {
|
||||
pub struct ChunkedVectorsRead<T: Copy + 'static, S: UniversalRead<T>> {
|
||||
pub(super) config: ChunkedVectorsConfig,
|
||||
/// Number of vectors currently stored. Snapshot for read-only mode; for
|
||||
/// [`super::ChunkedVectors`] this is kept in sync with the writable status
|
||||
@@ -35,7 +35,7 @@ pub struct ChunkedVectorsRead<T: Copy + Sized + 'static, S: UniversalRead<T>> {
|
||||
pub(super) directory: PathBuf,
|
||||
}
|
||||
|
||||
impl<T: Sized + Copy + 'static, S: UniversalRead<T>> ChunkedVectorsRead<T, S> {
|
||||
impl<T: Copy + 'static, S: UniversalRead<T>> ChunkedVectorsRead<T, S> {
|
||||
pub(super) fn config_file(directory: &Path) -> PathBuf {
|
||||
directory.join(CONFIG_FILE_NAME)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use std::cmp::max;
|
||||
use std::ops::Deref;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use common::counter::hardware_counter::HardwareCounterCell;
|
||||
use common::fs::atomic_save_json;
|
||||
use common::mmap::{Advice, AdviceSetting, MmapType, open_write_mmap};
|
||||
use common::universal_io::UniversalWrite;
|
||||
use common::mmap::AdviceSetting;
|
||||
use common::universal_io::{OpenOptions, StoredStruct, UniversalWrite};
|
||||
use fs_err as fs;
|
||||
use memmap2::MmapMut;
|
||||
use num_traits::AsPrimitive;
|
||||
|
||||
use super::chunks::{create_chunk, read_chunks};
|
||||
@@ -19,12 +18,20 @@ use crate::vector_storage::VectorOffsetType;
|
||||
use crate::vector_storage::common::CHUNK_SIZE;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChunkedVectors<T: Copy + Sized + 'static, S: UniversalWrite<T>> {
|
||||
pub struct ChunkedVectors<T, S>
|
||||
where
|
||||
T: Copy + 'static,
|
||||
S: UniversalWrite<T> + UniversalWrite<Status> + Send + 'static,
|
||||
{
|
||||
inner: ChunkedVectorsRead<T, S>,
|
||||
status: MmapType<Status>,
|
||||
status: StoredStruct<S, Status>,
|
||||
}
|
||||
|
||||
impl<T: Copy + Sized + 'static, S: UniversalWrite<T>> Deref for ChunkedVectors<T, S> {
|
||||
impl<T, S> Deref for ChunkedVectors<T, S>
|
||||
where
|
||||
T: Copy + 'static,
|
||||
S: UniversalWrite<T> + UniversalWrite<Status> + Send + 'static,
|
||||
{
|
||||
type Target = ChunkedVectorsRead<T, S>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@@ -32,20 +39,21 @@ impl<T: Copy + Sized + 'static, S: UniversalWrite<T>> Deref for ChunkedVectors<T
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sized + Copy + 'static, S: UniversalWrite<T>> ChunkedVectors<T, S> {
|
||||
pub fn ensure_status_file(directory: &Path) -> OperationResult<MmapMut> {
|
||||
impl<T, S> ChunkedVectors<T, S>
|
||||
where
|
||||
T: Copy + 'static,
|
||||
S: UniversalWrite<T> + UniversalWrite<Status> + Send + 'static,
|
||||
{
|
||||
pub fn ensure_status_file(directory: &Path) -> OperationResult<PathBuf> {
|
||||
let status_file = ChunkedVectorsRead::<T, S>::status_file(directory);
|
||||
if !status_file.exists() {
|
||||
if !S::exists(&status_file)? {
|
||||
{
|
||||
let length = std::mem::size_of::<usize>() as u64;
|
||||
common::mmap::create_and_ensure_length(&status_file, length as usize)?;
|
||||
let length = std::mem::size_of::<Status>();
|
||||
// TODO(uio): migrate when UniversalWriteFileOps is available
|
||||
common::mmap::create_and_ensure_length(&status_file, length)?;
|
||||
}
|
||||
}
|
||||
Ok(open_write_mmap(
|
||||
&status_file,
|
||||
AdviceSetting::from(Advice::Normal),
|
||||
false, // Status file is write-only
|
||||
)?)
|
||||
Ok(status_file)
|
||||
}
|
||||
|
||||
fn ensure_config(
|
||||
@@ -107,8 +115,19 @@ impl<T: Sized + Copy + 'static, S: UniversalWrite<T>> ChunkedVectors<T, S> {
|
||||
populate: Option<bool>,
|
||||
) -> OperationResult<Self> {
|
||||
fs::create_dir_all(directory)?;
|
||||
let status_mmap = Self::ensure_status_file(directory)?;
|
||||
let status: MmapType<Status> = unsafe { MmapType::from(status_mmap) };
|
||||
let status_path = Self::ensure_status_file(directory)?;
|
||||
|
||||
let status: StoredStruct<S, Status> = StoredStruct::open(
|
||||
status_path,
|
||||
OpenOptions {
|
||||
writeable: true,
|
||||
need_sequential: false,
|
||||
disk_parallel: None,
|
||||
populate,
|
||||
advice: None,
|
||||
prevent_caching: None,
|
||||
},
|
||||
)?;
|
||||
|
||||
let config = Self::ensure_config(directory, dim, populate)?;
|
||||
let chunks = read_chunks(directory, advice, populate.unwrap_or_default(), true)?;
|
||||
|
||||
Reference in New Issue
Block a user