remdb/
config.rs

1use core::mem::size_of;
2use crate::types::TableDef;
3pub use crate::time_series::TimeSeriesConfig;
4#[cfg(feature = "ha")]
5pub use crate::ha::HAConfig;
6
7/// 默认内存分配器实现
8pub struct DefaultMemoryAllocator;
9
10impl MemoryAllocator for DefaultMemoryAllocator {
11    fn allocate(&self, size: usize) -> Option<core::ptr::NonNull<u8>> {
12        // 实际分配内存
13        #[cfg(feature = "std")] {
14            let mut vec = vec![0u8; size];
15            let ptr = vec.as_mut_ptr();
16            // 释放vec对内存的所有权,但不释放内存本身
17            std::mem::forget(vec);
18            Some(unsafe { core::ptr::NonNull::new_unchecked(ptr) })
19        }
20        #[cfg(not(feature = "std"))] {
21            // 非std环境下返回None
22            None
23        }
24    }
25    
26    fn deallocate(&self, ptr: core::ptr::NonNull<u8>, size: usize) {
27        // 释放内存
28        #[cfg(feature = "std")] {
29            unsafe {
30                let slice = core::slice::from_raw_parts_mut(ptr.as_ptr(), size);
31                let vec = Vec::from_raw_parts(slice.as_mut_ptr(), 0, size);
32                drop(vec);
33            }
34        }
35        // 非std环境下不做任何操作
36    }
37}
38
39/// 内存分配器接口
40pub trait MemoryAllocator: Sync {
41    /// 分配内存
42    fn allocate(&self, size: usize) -> Option<core::ptr::NonNull<u8>>;
43    
44    /// 释放内存
45    fn deallocate(&self, ptr: core::ptr::NonNull<u8>, size: usize);
46}
47
48/// 日志模式
49#[derive(Copy, Clone, PartialEq)]
50pub enum LogMode {
51    /// 同步模式:事务提交时立即写入日志
52    Sync,
53    /// 异步模式:日志先写入缓冲区,后台批量写入
54    Async,
55}
56
57/// WAL日志配置
58pub struct WALConfig {
59    /// 日志文件路径
60    pub log_path: &'static str,
61    /// 日志模式(同步/异步)
62    pub log_mode: LogMode,
63    /// 检查点间隔(毫秒,默认60秒)
64    pub checkpoint_interval_ms: u64,
65    /// 日志文件大小限制(字节,默认16MB)
66    pub log_file_size_limit: usize,
67    /// 日志预分配大小(字节)
68    pub log_prealloc_size: usize,
69    /// 日志分段大小(字节,默认16MB)
70    pub log_segment_size: usize,
71    /// 保留的检查点数量
72    pub retained_checkpoints: usize,
73}
74
75/// 数据库全局配置
76pub struct DbConfig {
77    /// 表定义列表
78    pub tables: &'static [TableDef],
79    /// 总内存大小
80    pub total_memory: usize,
81    /// 支持低功耗模式
82    pub low_power_mode_supported: bool,
83    /// 低功耗模式下的最大记录数(可选)
84    pub low_power_max_records: Option<usize>,
85    /// 单表的最大记录数(用于动态创建表)
86    pub default_max_records: usize,
87    /// 内存分配器
88    pub memory_allocator: &'static dyn MemoryAllocator,
89    /// WAL日志配置
90    pub wal_config: WALConfig,
91    /// 时序数据默认配置
92    pub time_series_defaults: TimeSeriesConfig,
93    
94    /// PubSub配置
95    #[cfg(feature = "pubsub")]
96    pub pubsub_config: Option<crate::pubsub::PubSubConfig>,
97    
98    /// HA配置
99    #[cfg(feature = "ha")]
100    pub ha_config: Option<HAConfig>,
101}
102
103
104
105/// 编译时配置检查
106pub const fn validate_config(config: &DbConfig) -> bool {
107    // 检查表数量
108    if config.tables.len() > 32 {
109        return false;
110    }
111    
112    // 检查低功耗模式配置
113    if let Some(low_power_max) = config.low_power_max_records {
114        if low_power_max > 100000 {
115            return false;
116        }
117    }
118    
119    // 检查默认最大记录数
120    if config.default_max_records > 500000 {
121        return false;
122    }
123    
124    // 检查WAL和检查点配置
125    if config.wal_config.checkpoint_interval_ms > 3600000 { // 最大1小时
126        return false;
127    }
128    
129    if config.wal_config.log_file_size_limit < 1024 * 1024 { // 最小1MB
130        return false;
131    }
132    
133    if config.wal_config.log_prealloc_size > config.wal_config.log_file_size_limit {
134        return false;
135    }
136    
137    if config.wal_config.log_segment_size < 1024 * 1024 { // 最小1MB
138        return false;
139    }
140    
141    if config.wal_config.retained_checkpoints > 10 {
142        return false;
143    }
144    
145    // 检查HA配置
146    #[cfg(feature = "ha")] {
147        if let Some(ha_config) = &config.ha_config {
148            if ha_config.heartbeat_interval_ms < 100 { // 最小100ms
149                return false;
150            }
151            
152            if ha_config.heartbeat_interval_ms > 60000 { // 最大60秒
153                return false;
154            }
155            
156            if ha_config.failure_detection_ms < ha_config.heartbeat_interval_ms { // 故障检测时间必须大于等于心跳间隔
157                return false;
158            }
159            
160            if ha_config.failure_detection_ms > 300000 { // 最大5分钟
161                return false;
162            }
163            
164            if ha_config.sync_timeout_ms < 100 { // 最小100ms
165                return false;
166            }
167            
168            if ha_config.sync_timeout_ms > 10000 { // 最大10秒
169                return false;
170            }
171        }
172    }
173    
174    // 检查每个表(使用常量兼容的方式)
175    let mut i = 0;
176    while i < config.tables.len() {
177        let table = &config.tables[i];
178        
179        // 检查记录大小
180        if table.record_size > 512 {
181            return false;
182        }
183        
184        // 检查最大记录数
185        if table.max_records > 500000 {
186            return false;
187        }
188        
189        // 检查主键存在
190        if table.primary_key >= table.fields.len() {
191            return false;
192        }
193        
194        // 检查辅助索引(如果有)
195        let has_secondary = table.secondary_index.is_some();
196        if has_secondary {
197            let secondary_index = table.secondary_index.unwrap();
198            if secondary_index >= table.fields.len() {
199                return false;
200            }
201        }
202        
203        i += 1;
204    }
205    
206    true
207}
208
209/// 计算表的内存占用
210pub const fn table_memory_usage(table: &TableDef) -> usize {
211    // 记录内存
212    let record_memory = table.record_size * table.max_records;
213    
214    // 索引内存
215    let index_memory = table.max_records * size_of::<u32>(); // 主键哈希表
216    
217    // 辅助索引内存(如果有)
218    let secondary_index_memory = if table.secondary_index.is_some() {
219        match table.secondary_index_type {
220            // 有序数组索引
221            crate::types::IndexType::SortedArray => {
222                let primary_key_field = &table.fields[table.primary_key];
223                table.max_records * (primary_key_field.size + size_of::<u16>())
224            },
225            // B-Tree索引
226            crate::types::IndexType::BTree => {
227                // B-Tree节点大小
228                const BTREE_NODE_SIZE: usize = 1 + 1 + (64 * 4) + ((size_of::<usize>() * 5) / 8);
229                // 假设每个节点平均使用50%的空间,每个节点平均2个键
230                let max_nodes = table.max_records / 2;
231                max_nodes * BTREE_NODE_SIZE
232            },
233            // T-Tree索引
234            crate::types::IndexType::TTree => {
235                // T-Tree节点大小
236                const TTREE_NODE_SIZE: usize = 1 + (64 * 3) + (size_of::<usize>() * 3);
237                // 假设每个节点平均使用50%的空间,每个节点平均2个键
238                let max_nodes = table.max_records / 2;
239                max_nodes * TTREE_NODE_SIZE
240            },
241            // 其他索引类型(默认)
242            _ => {
243                let primary_key_field = &table.fields[table.primary_key];
244                table.max_records * (primary_key_field.size + size_of::<u16>())
245            }
246        }
247    } else {
248        0
249    };
250    
251    record_memory + index_memory + secondary_index_memory
252}
253
254/// 计算数据库总内存占用
255pub const fn total_memory_usage(config: &DbConfig) -> usize {
256    let mut total = 0;
257    let mut i = 0;
258    while i < config.tables.len() {
259        total += table_memory_usage(&config.tables[i]);
260        i += 1;
261    }
262    total
263}