1use std::collections::{BTreeMap, HashMap};
22use std::fs::File;
23use std::io::{BufReader, Read};
24use std::path::{Path, PathBuf};
25use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, Ordering};
26use std::sync::Arc;
27
28use parking_lot::RwLock;
29
30use super::context_index::ContextIndex;
31use super::entity::{
32 CrossRef, EdgeData, EmbeddingSlot, EntityData, EntityId, EntityKind, GraphEdgeKind,
33 GraphNodeKind, NodeData, RefType, RowData, TimeSeriesPointKind, UnifiedEntity, VectorData,
34};
35use super::entity_cache::EntityCache;
36use super::manager::{ManagerConfig, ManagerStats, SegmentManager};
37use super::metadata::{Metadata, MetadataFilter, MetadataValue};
38use super::segment::SegmentError;
39use crate::api::{DurabilityMode, GroupCommitOptions};
40use crate::physical::{ManifestEvent, ManifestEventKind};
41use crate::storage::engine::pager::PagerError;
42use crate::storage::engine::{BTree, BTreeError, Pager, PagerConfig, PhysicalFileHeader};
43use crate::storage::primitives::encoding::{read_varu32, read_varu64, write_varu32, write_varu64};
44use crate::storage::schema::types::Value;
45
46pub use reddb_file::{
47 is_supported_store_version, NativeCatalogCollectionSummary, NativeCatalogSummary,
48 NativeExportSummary, NativeManifestEntrySummary, NativeManifestSummary,
49 NativeMetadataStateSummary, NativeRecoverySummary, NativeRegistryIndexSummary,
50 NativeRegistryJobSummary, NativeRegistryProjectionSummary, NativeRegistrySummary,
51 NativeSnapshotSummary, NativeVectorArtifactPageSummary, NativeVectorArtifactSummary,
52 ENTITY_RECORD_MAGIC, METADATA_MAGIC, METADATA_OVERFLOW_MAGIC, NATIVE_BLOB_MAGIC,
53 NATIVE_CATALOG_MAGIC, NATIVE_COLLECTION_ROOTS_MAGIC, NATIVE_MANIFEST_MAGIC,
54 NATIVE_MANIFEST_SAMPLE_LIMIT, NATIVE_METADATA_STATE_MAGIC, NATIVE_RECOVERY_MAGIC,
55 NATIVE_REGISTRY_MAGIC, NATIVE_VECTOR_ARTIFACT_MAGIC, STORE_MAGIC, STORE_VERSION_CURRENT,
56 STORE_VERSION_V1, STORE_VERSION_V11, STORE_VERSION_V2, STORE_VERSION_V3, STORE_VERSION_V4,
57 STORE_VERSION_V5, STORE_VERSION_V6, STORE_VERSION_V7, STORE_VERSION_V8, STORE_VERSION_V9,
58};
59
60#[derive(Debug, Clone, Default, PartialEq, Eq)]
61pub struct MvccVacuumStats {
62 pub scanned_versions: u64,
63 pub retained_versions: u64,
64 pub reclaimed_versions: u64,
65 pub retained_history_versions: u64,
66 pub reclaimed_history_versions: u64,
67 pub retained_tombstones: u64,
68 pub reclaimed_tombstones: u64,
69}
70
71impl MvccVacuumStats {
72 pub fn add(&mut self, other: &Self) {
73 self.scanned_versions += other.scanned_versions;
74 self.retained_versions += other.retained_versions;
75 self.reclaimed_versions += other.reclaimed_versions;
76 self.retained_history_versions += other.retained_history_versions;
77 self.reclaimed_history_versions += other.reclaimed_history_versions;
78 self.retained_tombstones += other.retained_tombstones;
79 self.reclaimed_tombstones += other.reclaimed_tombstones;
80 }
81}
82
83#[derive(Debug, Clone)]
84pub struct NativePhysicalState {
85 pub header: PhysicalFileHeader,
86 pub collection_roots: BTreeMap<String, u64>,
87 pub manifest: Option<NativeManifestSummary>,
88 pub registry: Option<NativeRegistrySummary>,
89 pub recovery: Option<NativeRecoverySummary>,
90 pub catalog: Option<NativeCatalogSummary>,
91 pub metadata_state: Option<NativeMetadataStateSummary>,
92 pub vector_artifact_pages: Option<Vec<NativeVectorArtifactPageSummary>>,
93}
94
95#[derive(Debug, Clone)]
101pub struct UnifiedStoreConfig {
102 pub manager_config: ManagerConfig,
104 pub auto_index_refs: bool,
106 pub auto_index_id: bool,
115 pub max_cross_refs: usize,
117 pub enable_wal: bool,
119 pub durability_mode: DurabilityMode,
121 pub group_commit: GroupCommitOptions,
123 pub data_dir: Option<std::path::PathBuf>,
125 pub embedded_wal_path: Option<std::path::PathBuf>,
127 pub page_cache_slots: Option<usize>,
132}
133
134impl Default for UnifiedStoreConfig {
135 fn default() -> Self {
136 Self {
137 manager_config: ManagerConfig::default(),
138 auto_index_refs: true,
139 auto_index_id: true,
140 max_cross_refs: 1000,
141 enable_wal: false,
142 durability_mode: DurabilityMode::WalDurableGrouped,
145 group_commit: GroupCommitOptions::default(),
146 data_dir: None,
147 embedded_wal_path: None,
148 page_cache_slots: None,
149 }
150 }
151}
152
153impl UnifiedStoreConfig {
154 pub fn with_data_dir(mut self, path: impl Into<std::path::PathBuf>) -> Self {
156 self.data_dir = Some(path.into());
157 self
158 }
159
160 pub fn with_wal(mut self) -> Self {
162 self.enable_wal = true;
163 self
164 }
165
166 pub fn with_durability_mode(mut self, mode: DurabilityMode) -> Self {
167 self.durability_mode = mode;
168 self
169 }
170
171 pub fn with_group_commit(mut self, options: GroupCommitOptions) -> Self {
172 self.group_commit = options;
173 self
174 }
175
176 pub fn with_embedded_wal_path(mut self, path: impl Into<std::path::PathBuf>) -> Self {
177 self.embedded_wal_path = Some(path.into());
178 self
179 }
180
181 pub fn with_page_cache_slots(mut self, slots: usize) -> Self {
183 self.page_cache_slots = Some(slots);
184 self
185 }
186
187 pub fn with_max_refs(mut self, max: usize) -> Self {
189 self.max_cross_refs = max;
190 self
191 }
192}
193
194#[derive(Debug)]
200pub enum StoreError {
201 CollectionExists(String),
203 CollectionNotFound(String),
205 EntityNotFound(EntityId),
207 TooManyRefs(EntityId),
209 Segment(SegmentError),
211 Io(std::io::Error),
213 StorageIntegrity(crate::api::StorageIntegrityError),
215 Serialization(String),
217 Internal(String),
219}
220
221impl std::fmt::Display for StoreError {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 match self {
224 Self::CollectionExists(name) => write!(f, "Collection already exists: {}", name),
225 Self::CollectionNotFound(name) => write!(f, "Collection not found: {}", name),
226 Self::EntityNotFound(id) => write!(f, "Entity not found: {}", id),
227 Self::TooManyRefs(id) => write!(f, "Too many cross-references for entity: {}", id),
228 Self::Segment(e) => write!(f, "Segment error: {:?}", e),
229 Self::Io(e) => write!(f, "I/O error: {}", e),
230 Self::StorageIntegrity(e) => write!(f, "{e}"),
231 Self::Serialization(msg) => write!(f, "Serialization error: {}", msg),
232 Self::Internal(msg) => write!(f, "Internal error: {}", msg),
233 }
234 }
235}
236
237impl std::error::Error for StoreError {}
238
239impl From<SegmentError> for StoreError {
240 fn from(e: SegmentError) -> Self {
241 Self::Segment(e)
242 }
243}
244
245impl From<std::io::Error> for StoreError {
246 fn from(e: std::io::Error) -> Self {
247 Self::Io(e)
248 }
249}
250
251#[derive(Debug, Clone, Default)]
257pub struct StoreStats {
258 pub collection_count: usize,
260 pub total_entities: usize,
262 pub total_memory_bytes: usize,
264 pub collections: HashMap<String, ManagerStats>,
266 pub cross_ref_count: usize,
268}
269
270impl StoreStats {
271 pub fn avg_entities_per_collection(&self) -> f64 {
273 if self.collection_count == 0 {
274 0.0
275 } else {
276 self.total_entities as f64 / self.collection_count as f64
277 }
278 }
279
280 pub fn memory_mb(&self) -> f64 {
282 self.total_memory_bytes as f64 / (1024.0 * 1024.0)
283 }
284}
285
286pub struct UnifiedStore {
323 config: UnifiedStoreConfig,
325 format_version: AtomicU32,
327 next_entity_id: AtomicU64,
329 collections: RwLock<HashMap<String, Arc<SegmentManager>>>,
331 cross_refs: RwLock<HashMap<EntityId, Vec<(EntityId, RefType, String)>>>,
333 reverse_refs: RwLock<HashMap<EntityId, Vec<(EntityId, RefType, String)>>>,
335 pager: Option<Arc<Pager>>,
337 db_path: Option<PathBuf>,
339 btree_indices: RwLock<HashMap<String, Arc<BTree>>>,
346 context_index: ContextIndex,
348 entity_cache: EntityCache,
352 graph_label_index: RwLock<HashMap<(String, String), Vec<EntityId>>>,
355 paged_registry_dirty: AtomicBool,
357 commit: Option<Arc<StoreCommitCoordinator>>,
359 unindex_cross_refs_fast_path: AtomicU64,
364 pub(crate) replayed_turbo_inserts: parking_lot::Mutex<HashMap<String, Vec<(u64, Vec<f32>)>>>,
371 pub(crate) replayed_probabilistic_deltas:
375 parking_lot::Mutex<Vec<(u8, u8, String, Vec<Vec<u8>>)>>,
376 pub(crate) aux_metadata: RwLock<Vec<u8>>,
382}
383
384mod builder;
385mod commit;
386mod impl_entities;
387mod impl_file;
388mod impl_native_a;
389mod impl_native_b;
390mod impl_native_c;
391mod impl_pages;
392mod native_helpers;
393
394pub use self::builder::EntityBuilder;
395pub(crate) use self::commit::DeferredStoreWalActions;
396use self::commit::{StoreCommitCoordinator, StoreWalAction};
397use self::native_helpers::*;