1+ use super :: rocksdb_preset:: RocksDbPreset ;
12use crate :: db:: DB ;
23use rocksdb:: { DBWithThreadMode , MultiThreaded } ;
34use std:: { path:: PathBuf , sync:: Arc } ;
@@ -13,6 +14,8 @@ pub struct ConnBuilder<Path, const STATS_ENABLED: bool, StatsPeriod, FDLimit> {
1314 files_limit : FDLimit ,
1415 mem_budget : usize ,
1516 stats_period : StatsPeriod ,
17+ preset : RocksDbPreset ,
18+ wal_dir : Option < PathBuf > ,
1619}
1720
1821impl Default for ConnBuilder < Unspecified , false , Unspecified , Unspecified > {
@@ -24,6 +27,8 @@ impl Default for ConnBuilder<Unspecified, false, Unspecified, Unspecified> {
2427 mem_budget : 64 * 1024 * 1024 ,
2528 stats_period : Unspecified ,
2629 files_limit : Unspecified ,
30+ preset : RocksDbPreset :: Default ,
31+ wal_dir : None ,
2732 }
2833 }
2934}
@@ -37,6 +42,8 @@ impl<Path, const STATS_ENABLED: bool, StatsPeriod, FDLimit> ConnBuilder<Path, ST
3742 parallelism : self . parallelism ,
3843 mem_budget : self . mem_budget ,
3944 stats_period : self . stats_period ,
45+ preset : self . preset ,
46+ wal_dir : self . wal_dir ,
4047 }
4148 }
4249 pub fn with_create_if_missing ( self , create_if_missing : bool ) -> ConnBuilder < Path , STATS_ENABLED , StatsPeriod , FDLimit > {
@@ -56,8 +63,16 @@ impl<Path, const STATS_ENABLED: bool, StatsPeriod, FDLimit> ConnBuilder<Path, ST
5663 parallelism : self . parallelism ,
5764 mem_budget : self . mem_budget ,
5865 stats_period : self . stats_period ,
66+ preset : self . preset ,
67+ wal_dir : self . wal_dir ,
5968 }
6069 }
70+ pub fn with_preset ( self , preset : RocksDbPreset ) -> ConnBuilder < Path , STATS_ENABLED , StatsPeriod , FDLimit > {
71+ ConnBuilder { preset, ..self }
72+ }
73+ pub fn with_wal_dir ( self , wal_dir : Option < PathBuf > ) -> ConnBuilder < Path , STATS_ENABLED , StatsPeriod , FDLimit > {
74+ ConnBuilder { wal_dir, ..self }
75+ }
6176}
6277
6378impl < Path , FDLimit > ConnBuilder < Path , false , Unspecified , FDLimit > {
@@ -69,6 +84,8 @@ impl<Path, FDLimit> ConnBuilder<Path, false, Unspecified, FDLimit> {
6984 files_limit : self . files_limit ,
7085 mem_budget : self . mem_budget ,
7186 stats_period : self . stats_period ,
87+ preset : self . preset ,
88+ wal_dir : self . wal_dir ,
7289 }
7390 }
7491}
@@ -82,6 +99,8 @@ impl<Path, StatsPeriod, FDLimit> ConnBuilder<Path, true, StatsPeriod, FDLimit> {
8299 files_limit : self . files_limit ,
83100 mem_budget : self . mem_budget ,
84101 stats_period : Unspecified ,
102+ preset : self . preset ,
103+ wal_dir : self . wal_dir ,
85104 }
86105 }
87106 pub fn with_stats_period ( self , stats_period : impl Into < u32 > ) -> ConnBuilder < Path , true , u32 , FDLimit > {
@@ -92,18 +111,39 @@ impl<Path, StatsPeriod, FDLimit> ConnBuilder<Path, true, StatsPeriod, FDLimit> {
92111 files_limit : self . files_limit ,
93112 mem_budget : self . mem_budget ,
94113 stats_period : stats_period. into ( ) ,
114+ preset : self . preset ,
115+ wal_dir : self . wal_dir ,
95116 }
96117 }
97118}
98119
99120macro_rules! default_opts {
100121 ( $self: expr) => { {
101122 let mut opts = rocksdb:: Options :: default ( ) ;
102- if $self. parallelism > 1 {
103- opts. increase_parallelism( $self. parallelism as i32 ) ;
123+
124+ // Apply the preset configuration (includes parallelism and compaction settings)
125+ $self. preset. apply_to_options( & mut opts, $self. parallelism, $self. mem_budget) ;
126+
127+ // Configure WAL directory if specified (for RAM cache / tmpfs)
128+ // Auto-generate unique subdirectory from database path to avoid conflicts
129+ if let Some ( ref wal_base) = $self. wal_dir {
130+ let db_name = $self
131+ . db_path
132+ . file_name( )
133+ . and_then( |n| n. to_str( ) )
134+ . expect( & format!( "Invalid database path: {}" , $self. db_path. display( ) ) ) ;
135+ let wal_subdir = wal_base. join( db_name) ;
136+
137+ // Create subdirectory if needed (each DB gets its own WAL space)
138+ std:: fs:: create_dir_all( & wal_subdir) . expect( & format!(
139+ "Failed to create WAL subdirectory {}: {}" ,
140+ wal_subdir. display( ) ,
141+ "error"
142+ ) ) ;
143+
144+ opts. set_wal_dir( & wal_subdir) ;
104145 }
105146
106- opts. optimize_level_style_compaction( $self. mem_budget) ;
107147 let guard = kaspa_utils:: fd_budget:: acquire_guard( $self. files_limit) ?;
108148 opts. set_max_open_files( $self. files_limit) ;
109149 opts. create_if_missing( $self. create_if_missing) ;
@@ -114,17 +154,19 @@ macro_rules! default_opts {
114154impl ConnBuilder < PathBuf , false , Unspecified , i32 > {
115155 pub fn build ( self ) -> Result < Arc < DB > , kaspa_utils:: fd_budget:: Error > {
116156 let ( opts, guard) = default_opts ! ( self ) ?;
117- let db = Arc :: new ( DB :: new ( <DBWithThreadMode < MultiThreaded > >:: open ( & opts, self . db_path . to_str ( ) . unwrap ( ) ) . unwrap ( ) , guard) ) ;
118- Ok ( db)
157+ let db_path_str = self . db_path . to_str ( ) . expect ( & format ! ( "Invalid UTF-8 in database path: {}" , self . db_path. display( ) ) ) ;
158+ let db = <DBWithThreadMode < MultiThreaded > >:: open ( & opts, db_path_str) . expect ( "Failed to open database" ) ;
159+ Ok ( Arc :: new ( DB :: new ( db, guard) ) )
119160 }
120161}
121162
122163impl ConnBuilder < PathBuf , true , Unspecified , i32 > {
123164 pub fn build ( self ) -> Result < Arc < DB > , kaspa_utils:: fd_budget:: Error > {
124165 let ( mut opts, guard) = default_opts ! ( self ) ?;
125166 opts. enable_statistics ( ) ;
126- let db = Arc :: new ( DB :: new ( <DBWithThreadMode < MultiThreaded > >:: open ( & opts, self . db_path . to_str ( ) . unwrap ( ) ) . unwrap ( ) , guard) ) ;
127- Ok ( db)
167+ let db_path_str = self . db_path . to_str ( ) . expect ( & format ! ( "Invalid UTF-8 in database path: {}" , self . db_path. display( ) ) ) ;
168+ let db = <DBWithThreadMode < MultiThreaded > >:: open ( & opts, db_path_str) . expect ( "Failed to open database" ) ;
169+ Ok ( Arc :: new ( DB :: new ( db, guard) ) )
128170 }
129171}
130172
@@ -134,7 +176,8 @@ impl ConnBuilder<PathBuf, true, u32, i32> {
134176 opts. enable_statistics ( ) ;
135177 opts. set_report_bg_io_stats ( true ) ;
136178 opts. set_stats_dump_period_sec ( self . stats_period ) ;
137- let db = Arc :: new ( DB :: new ( <DBWithThreadMode < MultiThreaded > >:: open ( & opts, self . db_path . to_str ( ) . unwrap ( ) ) . unwrap ( ) , guard) ) ;
138- Ok ( db)
179+ let db_path_str = self . db_path . to_str ( ) . expect ( & format ! ( "Invalid UTF-8 in database path: {}" , self . db_path. display( ) ) ) ;
180+ let db = <DBWithThreadMode < MultiThreaded > >:: open ( & opts, db_path_str) . expect ( "Failed to open database" ) ;
181+ Ok ( Arc :: new ( DB :: new ( db, guard) ) )
139182 }
140183}
0 commit comments