Coverage Report

Created: 2026-01-04 13:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/runner/work/feoxdb/feoxdb/src/core/store/mod.rs
Line
Count
Source
1
use ahash::RandomState;
2
use crossbeam_skiplist::SkipMap;
3
use parking_lot::RwLock;
4
use scc::HashMap;
5
use std::sync::Arc;
6
7
use crate::core::record::Record;
8
use crate::core::ttl_sweep::TtlSweeper;
9
use crate::stats::Statistics;
10
use crate::storage::free_space::FreeSpaceManager;
11
use crate::storage::metadata::Metadata;
12
use crate::storage::write_buffer::WriteBuffer;
13
14
// Re-export public types
15
pub use self::builder::{StoreBuilder, StoreConfig};
16
17
// Module declarations
18
pub mod atomic;
19
pub mod builder;
20
pub mod init;
21
pub mod internal;
22
pub mod json_patch;
23
pub mod operations;
24
pub mod persistence;
25
pub mod range;
26
pub mod recovery;
27
pub mod ttl;
28
29
/// High-performance embedded key-value store.
30
///
31
/// `FeoxStore` provides ultra-fast key-value storage with optional persistence.
32
/// It uses lock-free data structures for concurrent access and achieves
33
/// sub-microsecond latencies for most operations.
34
///
35
/// # Thread Safety
36
///
37
/// All methods are thread-safe and can be called concurrently from multiple threads.
38
pub struct FeoxStore {
39
    // Main hash table with fine-grained locking using AHash
40
    pub(super) hash_table: HashMap<Vec<u8>, Arc<Record>, RandomState>,
41
42
    // Lock-free skip list for ordered access
43
    pub(super) tree: Arc<SkipMap<Vec<u8>, Arc<Record>>>,
44
45
    // Central statistics hub
46
    pub(super) stats: Arc<Statistics>,
47
48
    // Write buffering (optional for memory-only mode)
49
    pub(super) write_buffer: Option<Arc<WriteBuffer>>,
50
51
    // Free space management
52
    pub(super) free_space: Arc<RwLock<FreeSpaceManager>>,
53
54
    // Metadata
55
    pub(super) _metadata: Arc<RwLock<Metadata>>,
56
57
    // Configuration
58
    pub(super) memory_only: bool,
59
    pub(super) enable_caching: bool,
60
    pub(super) max_memory: Option<usize>,
61
62
    // Cache (if enabled)
63
    pub(super) cache: Option<Arc<super::cache::ClockCache>>,
64
    #[cfg(unix)]
65
    pub(super) device_fd: Option<i32>,
66
    pub(super) device_size: u64,
67
    pub(super) device_file: Option<std::fs::File>,
68
69
    // Disk I/O
70
    pub(super) disk_io: Option<Arc<RwLock<crate::storage::io::DiskIO>>>,
71
72
    // TTL sweeper (if enabled)
73
    pub(super) ttl_sweeper: Arc<RwLock<Option<TtlSweeper>>>,
74
75
    // TTL feature flag
76
    pub(super) enable_ttl: bool,
77
}
78
79
impl FeoxStore {
80
    /// Create a builder for configuring FeoxStore.
81
    ///
82
    /// # Example
83
    ///
84
    /// ```rust
85
    /// use feoxdb::FeoxStore;
86
    ///
87
    /// # fn main() -> feoxdb::Result<()> {
88
    /// let store = FeoxStore::builder()
89
    ///     .max_memory(2_000_000_000)
90
    ///     .build()?;
91
    /// # Ok(())
92
    /// # }
93
    /// ```
94
12
    pub fn builder() -> StoreBuilder {
95
12
        StoreBuilder::new()
96
12
    }
97
98
    // ============ Utility Methods ============
99
100
    /// Check if a key exists
101
28
    pub fn contains_key(&self, key: &[u8]) -> bool {
102
28
        self.hash_table.contains(key)
103
28
    }
104
105
    /// Get the number of records in the store
106
10
    pub fn len(&self) -> usize {
107
10
        self.stats
108
10
            .record_count
109
10
            .load(std::sync::atomic::Ordering::Acquire) as usize
110
10
    }
111
112
    /// Check if the store is empty
113
2
    pub fn is_empty(&self) -> bool {
114
2
        self.len() == 0
115
2
    }
116
117
    /// Get memory usage statistics
118
3
    pub fn memory_usage(&self) -> usize {
119
3
        self.stats
120
3
            .memory_usage
121
3
            .load(std::sync::atomic::Ordering::Acquire)
122
3
    }
123
124
    /// Get statistics snapshot
125
1
    pub fn stats(&self) -> crate::stats::StatsSnapshot {
126
1
        self.stats.snapshot()
127
1
    }
128
129
    /// Flush all pending writes to disk (for persistent mode)
130
2
    pub fn flush(&self) {
131
2
        self.flush_all()
132
2
    }
133
}