use std::collections::{BTreeSet, HashMap};
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use ahash::AHashMap;
use crate::common::counter::hardware_counter::HardwareCounterCell;
use crate::common::types::{DeferredBehavior, TelemetryDetail};
use uuid::Uuid;
use crate::segment::common::Flusher;
use crate::segment::common::operation_error::{OperationError, OperationResult, SegmentFailedState};
use crate::segment::data_types::build_index_result::BuildFieldIndexResult;
use crate::segment::data_types::facets::{FacetParams, FacetValue};
use crate::segment::data_types::named_vectors::NamedVectors;
use crate::segment::data_types::order_by::{OrderBy, OrderValue};
use crate::segment::data_types::query_context::{FormulaContext, QueryContext, SegmentQueryContext};
use crate::segment::data_types::segment_record::{SegmentRecord, SegmentRecordRaw};
use crate::segment::data_types::vector_name_config::VectorNameConfig;
use crate::segment::data_types::vectors::{QueryVector, VectorInternal};
use crate::segment::entry::snapshot_entry::SnapshotEntry;
use crate::segment::index::field_index::{CardinalityEstimation, FieldIndex};
use crate::segment::json_path::JsonPath;
use crate::segment::telemetry::SegmentTelemetry;
use crate::segment::types::{
ExtendedPointId, Filter, Payload, PayloadFieldSchema, PayloadKeyType, PayloadKeyTypeRef,
PointIdType, ScoredPoint, SearchParams, SegmentConfig, SegmentInfo, SegmentType, SeqNumberType,
VectorName, VectorNameBuf, WithPayload, WithVector,
};
pub trait ReadSegmentEntry {
fn is_proxy(&self) -> bool;
fn point_version(&self, point_id: PointIdType) -> Option<SeqNumberType>;
#[allow(clippy::too_many_arguments)]
fn search_batch(
&self,
vector_name: &VectorName,
query_vectors: &[&QueryVector],
with_payload: &WithPayload,
with_vector: &WithVector,
filter: Option<&Filter>,
top: usize,
params: Option<&SearchParams>,
query_context: &SegmentQueryContext,
) -> OperationResult<Vec<Vec<ScoredPoint>>>;
fn rescore_with_formula(
&self,
formula_ctx: Arc<FormulaContext>,
hw_counter: &HardwareCounterCell,
) -> OperationResult<Vec<ScoredPoint>>;
fn vector(
&self,
vector_name: &VectorName,
point_id: PointIdType,
hw_counter: &HardwareCounterCell,
) -> OperationResult<Option<VectorInternal>>;
fn vector_with_behavior(
&self,
vector_name: &VectorName,
point_id: PointIdType,
deferred_behavior: DeferredBehavior,
hw_counter: &HardwareCounterCell,
) -> OperationResult<Option<VectorInternal>>;
fn all_vectors(
&self,
point_id: PointIdType,
hw_counter: &HardwareCounterCell,
) -> OperationResult<NamedVectors<'_>>;
fn retrieve(
&self,
point_ids: &[PointIdType],
with_payload: &WithPayload,
with_vector: &WithVector,
hw_counter: &HardwareCounterCell,
is_stopped: &AtomicBool,
deferred_behavior: DeferredBehavior,
) -> OperationResult<AHashMap<ExtendedPointId, SegmentRecord>>;
fn retrieve_raw(
&self,
point_ids: &[PointIdType],
with_payload: &WithPayload,
with_vector: &WithVector,
hw_counter: &HardwareCounterCell,
is_stopped: &AtomicBool,
deferred_behavior: DeferredBehavior,
) -> OperationResult<AHashMap<ExtendedPointId, SegmentRecordRaw>>;
fn payload(
&self,
point_id: PointIdType,
hw_counter: &HardwareCounterCell,
) -> OperationResult<Payload>;
fn read_filtered(
&self,
offset: Option<PointIdType>,
limit: Option<usize>,
filter: Option<&Filter>,
is_stopped: &AtomicBool,
hw_counter: &HardwareCounterCell,
deferred_behavior: DeferredBehavior,
) -> OperationResult<Vec<PointIdType>>;
fn read_ordered_filtered<'a>(
&'a self,
limit: Option<usize>,
filter: Option<&'a Filter>,
order_by: &'a OrderBy,
is_stopped: &AtomicBool,
hw_counter: &HardwareCounterCell,
deferred_behavior: DeferredBehavior,
) -> OperationResult<Vec<(OrderValue, PointIdType)>>;
fn read_random_filtered(
&self,
limit: usize,
filter: Option<&Filter>,
is_stopped: &AtomicBool,
hw_counter: &HardwareCounterCell,
) -> OperationResult<Vec<PointIdType>>;
fn read_range(&self, from: Option<PointIdType>, to: Option<PointIdType>) -> Vec<PointIdType>;
fn unique_values(
&self,
key: &JsonPath,
filter: Option<&Filter>,
is_stopped: &AtomicBool,
hw_counter: &HardwareCounterCell,
) -> OperationResult<BTreeSet<FacetValue>>;
fn facet(
&self,
request: &FacetParams,
is_stopped: &AtomicBool,
hw_counter: &HardwareCounterCell,
) -> OperationResult<HashMap<FacetValue, usize>>;
fn has_point(&self, point_id: PointIdType, deferred_behavior: DeferredBehavior) -> bool;
fn estimate_point_count<'a>(
&'a self,
filter: Option<&'a Filter>,
hw_counter: &HardwareCounterCell,
) -> OperationResult<CardinalityEstimation>;
fn vector_names(&self) -> Vec<VectorNameBuf>;
fn is_empty(&self) -> bool;
fn available_point_count(&self) -> usize;
fn deleted_point_count(&self) -> usize;
fn available_point_count_without_deferred(&self) -> usize;
fn available_vectors_size_in_bytes(&self, vector_name: &VectorName) -> OperationResult<usize>;
fn max_available_vectors_size_in_bytes(&self) -> OperationResult<usize> {
let mut max_size = 0;
for vector_name in self.vector_names() {
let inner_size = self.available_vectors_size_in_bytes(&vector_name)?;
max_size = std::cmp::max(max_size, inner_size);
}
Ok(max_size)
}
fn segment_uuid(&self) -> Uuid;
fn segment_type(&self) -> SegmentType;
fn info(&self) -> OperationResult<SegmentInfo>;
fn size_info(&self) -> SegmentInfo;
fn config(&self) -> &SegmentConfig;
fn is_appendable(&self) -> bool;
fn get_indexed_fields(&self) -> HashMap<PayloadKeyType, PayloadFieldSchema>;
fn get_telemetry_data(&self, detail: TelemetryDetail) -> OperationResult<SegmentTelemetry>;
fn fill_query_context(&self, query_context: &mut QueryContext) -> OperationResult<()>;
fn point_is_deferred(&self, point_id: PointIdType) -> bool;
fn deferred_point_ids(&self) -> Vec<PointIdType>;
fn deferred_point_count(&self) -> usize;
fn has_deferred_points(&self) -> bool;
}
pub trait StorageSegmentEntry: ReadSegmentEntry + SnapshotEntry {
fn version(&self) -> SeqNumberType;
fn check_error(&self) -> Option<SegmentFailedState>;
fn persistent_version(&self) -> SeqNumberType;
fn flusher(&self, force: bool) -> Option<Flusher>;
fn flush(&self, force: bool) -> OperationResult<SeqNumberType> {
if let Some(flusher) = self.flusher(force) {
flusher()?;
}
Ok(self.persistent_version())
}
fn drop_data(self) -> OperationResult<()>;
fn data_path(&self) -> PathBuf;
}
pub trait NonAppendableSegmentEntry: StorageSegmentEntry {
fn delete_point(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn delete_field_index(
&mut self,
op_num: SeqNumberType,
key: PayloadKeyTypeRef,
) -> OperationResult<bool>;
fn delete_field_index_if_incompatible(
&mut self,
op_num: SeqNumberType,
key: PayloadKeyTypeRef,
field_schema: &PayloadFieldSchema,
) -> OperationResult<bool>;
fn build_field_index(
&self,
op_num: SeqNumberType,
key: PayloadKeyTypeRef,
field_type: &PayloadFieldSchema,
hw_counter: &HardwareCounterCell,
) -> OperationResult<BuildFieldIndexResult>;
fn apply_field_index(
&mut self,
op_num: SeqNumberType,
key: PayloadKeyType,
field_schema: PayloadFieldSchema,
field_index: Vec<FieldIndex>,
) -> OperationResult<bool>;
fn create_field_index(
&mut self,
op_num: SeqNumberType,
key: PayloadKeyTypeRef,
field_schema: Option<&PayloadFieldSchema>,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool> {
let Some(field_schema) = field_schema else {
return Err(OperationError::TypeInferenceError {
field_name: key.clone(),
});
};
self.delete_field_index_if_incompatible(op_num, key, field_schema)?;
let (schema, indexes) =
match self.build_field_index(op_num, key, field_schema, hw_counter)? {
BuildFieldIndexResult::SkippedByVersion => {
return Ok(false);
}
BuildFieldIndexResult::AlreadyExists => {
return Ok(false);
}
BuildFieldIndexResult::IncompatibleSchema => {
return Err(OperationError::service_error(format!(
"Incompatible schema for field index on field {key}",
)));
}
BuildFieldIndexResult::Built { schema, indexes } => (schema, indexes),
};
self.apply_field_index(op_num, key.to_owned(), schema, indexes)
}
fn create_vector_name(
&mut self,
op_num: SeqNumberType,
vector_name: &VectorName,
vector_config: &VectorNameConfig,
) -> OperationResult<bool>;
fn delete_vector_name(
&mut self,
op_num: SeqNumberType,
vector_name: &VectorName,
) -> OperationResult<bool>;
}
pub trait SegmentEntry: NonAppendableSegmentEntry {
fn upsert_point(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
vectors: NamedVectors,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn upsert_point_raw(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
vectors: &[(VectorNameBuf, Vec<u8>)],
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn upsert_moved_point(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
raw_vectors: &[(VectorNameBuf, Vec<u8>)],
updated_vectors: NamedVectors,
payload: &Payload,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn update_vectors(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
vectors: NamedVectors,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn delete_vector(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
vector_name: &VectorName,
) -> OperationResult<bool>;
fn set_payload(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
payload: &Payload,
key: &Option<JsonPath>,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn set_full_payload(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
full_payload: &Payload,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn delete_payload(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
key: PayloadKeyTypeRef,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
fn clear_payload(
&mut self,
op_num: SeqNumberType,
point_id: PointIdType,
hw_counter: &HardwareCounterCell,
) -> OperationResult<bool>;
}