use crate::collection::{GraphCollection, MetadataCollection, VectorCollection};
use crate::observer::DatabaseObserver;
use crate::simd_dispatch;
use crate::{ColumnStore, Error, Result};
mod admin_executor;
mod collection_ops;
mod cross_collection;
mod ddl_executor;
mod dml_executor;
mod graph_ops;
mod introspection_executor;
mod join_pushdown;
mod metadata_ops;
mod persistence;
mod query_engine;
mod query_engine_dml;
mod query_join;
mod stats;
mod training;
mod vector_ops;
#[cfg(feature = "persistence")]
mod database_helpers;
#[cfg(all(test, feature = "persistence"))]
mod collection_ops_tests;
#[cfg(all(test, feature = "persistence"))]
mod database_helpers_tests;
#[cfg(all(test, feature = "persistence"))]
mod database_tests;
#[cfg(all(test, feature = "persistence"))]
mod ddl_executor_tests;
#[cfg(all(test, feature = "persistence"))]
mod graph_ops_tests;
#[cfg(all(test, feature = "persistence"))]
mod query_engine_tests;
#[cfg(all(test, feature = "persistence"))]
mod stats_tests;
#[cfg(feature = "persistence")]
pub struct Database {
data_dir: std::path::PathBuf,
_lock_file: std::fs::File,
config: std::sync::Arc<crate::config::VelesConfig>,
vector_colls: parking_lot::RwLock<std::collections::HashMap<String, VectorCollection>>,
graph_colls: parking_lot::RwLock<std::collections::HashMap<String, GraphCollection>>,
metadata_colls: parking_lot::RwLock<std::collections::HashMap<String, MetadataCollection>>,
collection_stats: parking_lot::RwLock<
std::collections::HashMap<String, crate::collection::stats::CollectionStats>,
>,
observer: Option<std::sync::Arc<dyn DatabaseObserver>>,
schema_version: std::sync::atomic::AtomicU64,
compiled_plan_cache: crate::cache::CompiledPlanCache,
}
#[cfg(feature = "persistence")]
impl Database {
pub fn open<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
Self::open_impl(path, None, None)
}
pub fn open_with_config<P: AsRef<std::path::Path>>(
path: P,
config: crate::config::VelesConfig,
) -> Result<Self> {
Self::open_impl(path, None, Some(config))
}
pub fn open_with_observer<P: AsRef<std::path::Path>>(
path: P,
observer: std::sync::Arc<dyn DatabaseObserver>,
) -> Result<Self> {
Self::open_impl(path, Some(observer), None)
}
pub fn open_with_observer_and_config<P: AsRef<std::path::Path>>(
path: P,
observer: std::sync::Arc<dyn DatabaseObserver>,
config: crate::config::VelesConfig,
) -> Result<Self> {
Self::open_impl(path, Some(observer), Some(config))
}
fn open_impl<P: AsRef<std::path::Path>>(
path: P,
observer: Option<std::sync::Arc<dyn DatabaseObserver>>,
config: Option<crate::config::VelesConfig>,
) -> Result<Self> {
let data_dir = path.as_ref().to_path_buf();
std::fs::create_dir_all(&data_dir)?;
let lock_path = data_dir.join("velesdb.lock");
let lock_file = std::fs::File::create(&lock_path)?;
fs2::FileExt::try_lock_exclusive(&lock_file)
.map_err(|_| Error::DatabaseLocked(data_dir.display().to_string()))?;
let features = simd_dispatch::simd_features_info();
tracing::info!(
avx512 = features.avx512f,
avx2 = features.avx2,
"SIMD features detected - direct dispatch enabled"
);
let db = Self {
data_dir,
_lock_file: lock_file,
config: std::sync::Arc::new(config.unwrap_or_default()),
vector_colls: parking_lot::RwLock::new(std::collections::HashMap::new()),
graph_colls: parking_lot::RwLock::new(std::collections::HashMap::new()),
metadata_colls: parking_lot::RwLock::new(std::collections::HashMap::new()),
collection_stats: parking_lot::RwLock::new(std::collections::HashMap::new()),
observer,
schema_version: std::sync::atomic::AtomicU64::new(0),
compiled_plan_cache: crate::cache::CompiledPlanCache::new(1_000, 10_000),
};
db.load_collections()?;
Ok(db)
}
#[must_use]
pub fn config(&self) -> &crate::config::VelesConfig {
&self.config
}
#[must_use]
pub fn config_arc(&self) -> std::sync::Arc<crate::config::VelesConfig> {
std::sync::Arc::clone(&self.config)
}
#[must_use]
pub fn data_dir(&self) -> &std::path::Path {
&self.data_dir
}
#[must_use]
pub fn schema_version(&self) -> u64 {
self.schema_version
.load(std::sync::atomic::Ordering::Relaxed)
}
#[must_use]
pub fn plan_cache(&self) -> &crate::cache::CompiledPlanCache {
&self.compiled_plan_cache
}
pub fn notify_upsert(&self, collection: &str, point_count: usize) {
if let Some(ref obs) = self.observer {
obs.on_upsert(collection, point_count);
}
}
pub fn notify_query(&self, collection: &str, duration_us: u64) {
if let Some(ref obs) = self.observer {
obs.on_query(collection, duration_us);
}
}
}