Skip to main content

qdrant_edge/edge/read_view/
handle.rs

1use std::sync::Arc;
2
3use parking_lot::{RwLock, RwLockReadGuard};
4use crate::segment::entry::ReadSegmentEntry;
5use crate::segment::index::UniversalReadExt;
6use crate::segment::segment::read_only::ReadOnlySegment;
7use crate::shard::locked_segment::LockedSegment;
8
9/// A handle to a single segment that can be read-locked to yield a [`ReadSegmentEntry`].
10///
11/// Abstracting over the handle (rather than the segment type) keeps the read path monomorphic for
12/// homogeneous callers — a read-only follower's handle is the concrete
13/// `Arc<RwLock<ReadOnlySegment<S>>>` — while the read-write shard, whose holder is intrinsically
14/// heterogeneous (`Segment` and `ProxySegment` coexist during optimization), uses the
15/// [`LockedSegment`] enum. Dynamic dispatch is confined to the `LockedSegment` impl, mirroring the
16/// pre-existing [`LockedSegment::get_read`].
17///
18/// `Send + Sync` so a snapshot of handles can be shared across the shard's search thread pool and
19/// read in parallel (see [`EdgeReadView::par_map_segments`]). Both concrete handles —
20/// `Arc<RwLock<ReadOnlySegment<S>>>` and [`LockedSegment`] — already satisfy this.
21///
22/// [`EdgeReadView::par_map_segments`]: crate::read_view::EdgeReadView::par_map_segments
23pub trait ReadSegmentHandle: Send + Sync {
24    type Segment: ReadSegmentEntry + ?Sized;
25
26    /// Acquire a read guard. One guard is held for the whole per-segment operation, so reads that
27    /// call several methods on the same segment observe a consistent state.
28    fn read_segment(&self) -> RwLockReadGuard<'_, Self::Segment>;
29
30    /// Owned handle for the retrieval / version-dedup path ([`retrieve_over`]).
31    ///
32    /// [`retrieve_over`]: shard::retrieve::retrieve_blocking::retrieve_over
33    fn segment_arc(&self) -> Arc<RwLock<Self::Segment>>;
34}
35
36impl<S: UniversalReadExt + 'static> ReadSegmentHandle for Arc<RwLock<ReadOnlySegment<S>>>
37where
38    S::Fs: Send + Sync,
39{
40    type Segment = ReadOnlySegment<S>;
41
42    fn read_segment(&self) -> RwLockReadGuard<'_, ReadOnlySegment<S>> {
43        self.read()
44    }
45
46    fn segment_arc(&self) -> Arc<RwLock<ReadOnlySegment<S>>> {
47        self.clone()
48    }
49}
50
51impl ReadSegmentHandle for LockedSegment {
52    type Segment = dyn ReadSegmentEntry;
53
54    fn read_segment(&self) -> RwLockReadGuard<'_, dyn ReadSegmentEntry> {
55        self.get_read().read()
56    }
57
58    fn segment_arc(&self) -> Arc<RwLock<dyn ReadSegmentEntry>> {
59        self.get_read_arc()
60    }
61}