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_V12, STORE_VERSION_V2, STORE_VERSION_V3,
57 STORE_VERSION_V4, STORE_VERSION_V5, STORE_VERSION_V6, STORE_VERSION_V7, STORE_VERSION_V8,
58 STORE_VERSION_V9,
59};
60
61#[derive(Debug, Clone, Default, PartialEq, Eq)]
62pub struct MvccVacuumStats {
63 pub scanned_versions: u64,
64 pub retained_versions: u64,
65 pub reclaimed_versions: u64,
66 pub retained_history_versions: u64,
67 pub reclaimed_history_versions: u64,
68 pub retained_tombstones: u64,
69 pub reclaimed_tombstones: u64,
70}
71
72impl MvccVacuumStats {
73 pub fn add(&mut self, other: &Self) {
74 self.scanned_versions += other.scanned_versions;
75 self.retained_versions += other.retained_versions;
76 self.reclaimed_versions += other.reclaimed_versions;
77 self.retained_history_versions += other.retained_history_versions;
78 self.reclaimed_history_versions += other.reclaimed_history_versions;
79 self.retained_tombstones += other.retained_tombstones;
80 self.reclaimed_tombstones += other.reclaimed_tombstones;
81 }
82}
83
84#[derive(Debug, Clone)]
85pub struct NativePhysicalState {
86 pub header: PhysicalFileHeader,
87 pub collection_roots: BTreeMap<String, u64>,
88 pub manifest: Option<NativeManifestSummary>,
89 pub registry: Option<NativeRegistrySummary>,
90 pub recovery: Option<NativeRecoverySummary>,
91 pub catalog: Option<NativeCatalogSummary>,
92 pub metadata_state: Option<NativeMetadataStateSummary>,
93 pub vector_artifact_pages: Option<Vec<NativeVectorArtifactPageSummary>>,
94}
95
96#[derive(Debug, Clone)]
102pub struct UnifiedStoreConfig {
103 pub manager_config: ManagerConfig,
105 pub auto_index_refs: bool,
107 pub auto_index_id: bool,
116 pub max_cross_refs: usize,
118 pub enable_wal: bool,
120 pub durability_mode: DurabilityMode,
122 pub group_commit: GroupCommitOptions,
124 pub data_dir: Option<std::path::PathBuf>,
126 pub embedded_wal_path: Option<std::path::PathBuf>,
128 pub page_cache_slots: Option<usize>,
133}
134
135impl Default for UnifiedStoreConfig {
136 fn default() -> Self {
137 Self {
138 manager_config: ManagerConfig::default(),
139 auto_index_refs: true,
140 auto_index_id: true,
141 max_cross_refs: 1000,
142 enable_wal: false,
143 durability_mode: DurabilityMode::WalDurableGrouped,
146 group_commit: GroupCommitOptions::default(),
147 data_dir: None,
148 embedded_wal_path: None,
149 page_cache_slots: None,
150 }
151 }
152}
153
154impl UnifiedStoreConfig {
155 pub fn with_data_dir(mut self, path: impl Into<std::path::PathBuf>) -> Self {
157 self.data_dir = Some(path.into());
158 self
159 }
160
161 pub fn with_wal(mut self) -> Self {
163 self.enable_wal = true;
164 self
165 }
166
167 pub fn with_durability_mode(mut self, mode: DurabilityMode) -> Self {
168 self.durability_mode = mode;
169 self
170 }
171
172 pub fn with_group_commit(mut self, options: GroupCommitOptions) -> Self {
173 self.group_commit = options;
174 self
175 }
176
177 pub fn with_embedded_wal_path(mut self, path: impl Into<std::path::PathBuf>) -> Self {
178 self.embedded_wal_path = Some(path.into());
179 self
180 }
181
182 pub fn with_page_cache_slots(mut self, slots: usize) -> Self {
184 self.page_cache_slots = Some(slots);
185 self
186 }
187
188 pub fn with_max_refs(mut self, max: usize) -> Self {
190 self.max_cross_refs = max;
191 self
192 }
193}
194
195#[derive(Debug)]
201pub enum StoreError {
202 CollectionExists(String),
204 CollectionNotFound(String),
206 EntityNotFound(EntityId),
208 TooManyRefs(EntityId),
210 Segment(SegmentError),
212 Io(std::io::Error),
214 StorageIntegrity(crate::api::StorageIntegrityError),
216 Serialization(String),
218 Internal(String),
220}
221
222impl std::fmt::Display for StoreError {
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 match self {
225 Self::CollectionExists(name) => write!(f, "Collection already exists: {}", name),
226 Self::CollectionNotFound(name) => write!(f, "Collection not found: {}", name),
227 Self::EntityNotFound(id) => write!(f, "Entity not found: {}", id),
228 Self::TooManyRefs(id) => write!(f, "Too many cross-references for entity: {}", id),
229 Self::Segment(e) => write!(f, "Segment error: {:?}", e),
230 Self::Io(e) => write!(f, "I/O error: {}", e),
231 Self::StorageIntegrity(e) => write!(f, "{e}"),
232 Self::Serialization(msg) => write!(f, "Serialization error: {}", msg),
233 Self::Internal(msg) => write!(f, "Internal error: {}", msg),
234 }
235 }
236}
237
238impl std::error::Error for StoreError {}
239
240impl From<SegmentError> for StoreError {
241 fn from(e: SegmentError) -> Self {
242 Self::Segment(e)
243 }
244}
245
246impl From<std::io::Error> for StoreError {
247 fn from(e: std::io::Error) -> Self {
248 Self::Io(e)
249 }
250}
251
252#[derive(Debug, Clone, Default)]
258pub struct StoreStats {
259 pub collection_count: usize,
261 pub total_entities: usize,
263 pub total_memory_bytes: usize,
265 pub collections: HashMap<String, ManagerStats>,
267 pub cross_ref_count: usize,
269}
270
271impl StoreStats {
272 pub fn avg_entities_per_collection(&self) -> f64 {
274 if self.collection_count == 0 {
275 0.0
276 } else {
277 self.total_entities as f64 / self.collection_count as f64
278 }
279 }
280
281 pub fn memory_mb(&self) -> f64 {
283 self.total_memory_bytes as f64 / (1024.0 * 1024.0)
284 }
285}
286
287pub struct UnifiedStore {
324 config: UnifiedStoreConfig,
326 format_version: AtomicU32,
328 next_entity_id: AtomicU64,
330 collections: RwLock<HashMap<String, Arc<SegmentManager>>>,
332 cross_refs: RwLock<HashMap<EntityId, Vec<(EntityId, RefType, String)>>>,
334 reverse_refs: RwLock<HashMap<EntityId, Vec<(EntityId, RefType, String)>>>,
336 pager: Option<Arc<Pager>>,
338 db_path: Option<PathBuf>,
340 btree_indices: RwLock<HashMap<String, Arc<BTree>>>,
347 context_index: ContextIndex,
349 entity_cache: EntityCache,
353 graph_label_index: RwLock<HashMap<(String, String), Vec<EntityId>>>,
356 paged_registry_dirty: AtomicBool,
358 commit: Option<Arc<StoreCommitCoordinator>>,
360 unindex_cross_refs_fast_path: AtomicU64,
365 pub(crate) replayed_turbo_inserts: parking_lot::Mutex<HashMap<String, Vec<(u64, Vec<f32>)>>>,
372 pub(crate) replayed_probabilistic_deltas:
376 parking_lot::Mutex<Vec<(u8, u8, String, Vec<Vec<u8>>)>>,
377 pub(crate) aux_metadata: RwLock<Vec<u8>>,
383}
384
385mod builder;
386mod commit;
387mod impl_entities;
388mod impl_file;
389mod impl_native_a;
390mod impl_native_b;
391mod impl_native_c;
392mod impl_pages;
393mod native_helpers;
394
395pub use self::builder::EntityBuilder;
396pub(crate) use self::commit::DeferredStoreWalActions;
397use self::commit::{StoreCommitCoordinator, StoreWalAction};
398use self::native_helpers::*;