1- use std:: collections:: HashMap ;
1+ use std:: collections:: { BTreeSet , HashMap , HashSet } ;
22use std:: fs:: File ;
33use std:: ops:: Bound ;
44use std:: path:: { Path , PathBuf } ;
55use std:: sync:: atomic:: AtomicUsize ;
66use std:: sync:: Arc ;
77
8- use anyhow:: Result ;
8+ use anyhow:: { Context , Result } ;
99use bytes:: Bytes ;
1010use parking_lot:: { Mutex , RwLock } ;
1111
@@ -20,7 +20,7 @@ use crate::iterators::StorageIterator;
2020use crate :: lsm_iterator:: { FusedIterator , LsmIterator } ;
2121use crate :: manifest:: { Manifest , ManifestRecord } ;
2222use crate :: mem_table:: { map_bound, MemTable } ;
23- use crate :: table:: { SsTable , SsTableBuilder , SsTableIterator } ;
23+ use crate :: table:: { self , FileObject , SsTable , SsTableBuilder , SsTableIterator } ;
2424
2525pub type BlockCache = moka:: sync:: Cache < ( usize , usize ) , Arc < Block > > ;
2626
@@ -103,6 +103,7 @@ impl Drop for MiniLsm {
103103
104104impl MiniLsm {
105105 pub fn close ( & self ) -> Result < ( ) > {
106+ self . inner . sync_dir ( ) ?;
106107 self . compaction_notifier . send ( ( ) ) . ok ( ) ;
107108 let mut compaction_thread = self . compaction_thread . lock ( ) ;
108109 if let Some ( compaction_thread) = compaction_thread. take ( ) {
@@ -157,36 +158,101 @@ impl LsmStorageInner {
157158 }
158159
159160 pub ( crate ) fn open ( path : impl AsRef < Path > , options : LsmStorageOptions ) -> Result < Self > {
161+ let mut state = LsmStorageState :: create ( & options) ;
160162 let path = path. as_ref ( ) ;
163+ let mut next_sst_id = 1 ;
164+ let block_cache = Arc :: new ( BlockCache :: new ( 1 << 20 ) ) ; // 4GB block cache,
165+ let manifest;
166+
167+ let compaction_controller = match & options. compaction_options {
168+ CompactionOptions :: Leveled ( options) => {
169+ CompactionController :: Leveled ( LeveledCompactionController :: new ( options. clone ( ) ) )
170+ }
171+ CompactionOptions :: Tiered ( options) => {
172+ CompactionController :: Tiered ( TieredCompactionController :: new ( options. clone ( ) ) )
173+ }
174+ CompactionOptions :: Simple ( options) => CompactionController :: Simple (
175+ SimpleLeveledCompactionController :: new ( options. clone ( ) ) ,
176+ ) ,
177+ CompactionOptions :: NoCompaction => CompactionController :: NoCompaction ,
178+ } ;
179+
161180 if !path. exists ( ) {
162- std:: fs:: create_dir_all ( path) ?;
163- }
164- let mut state = LsmStorageState :: create ( & options) ;
165- if options. enable_wal {
166- state. memtable = Arc :: new ( MemTable :: create_with_wal (
167- state. memtable . id ( ) ,
168- Self :: path_of_wal_static ( path, state. memtable . id ( ) ) ,
169- ) ?) ;
170- }
181+ std:: fs:: create_dir_all ( path) . context ( "failed to create DB dir" ) ?;
182+ if options. enable_wal {
183+ state. memtable = Arc :: new ( MemTable :: create_with_wal (
184+ state. memtable . id ( ) ,
185+ Self :: path_of_wal_static ( path, state. memtable . id ( ) ) ,
186+ ) ?) ;
187+ }
188+ manifest =
189+ Manifest :: create ( path. join ( "MANIFEST" ) ) . context ( "failed to create manifest" ) ?;
190+ manifest. add_record_when_init ( ManifestRecord :: NewMemtable ( state. memtable . id ( ) ) ) ?;
191+ } else {
192+ let ( m, records) = Manifest :: recover ( path. join ( "MANIFEST" ) ) ?;
193+ let mut memtables = BTreeSet :: new ( ) ;
194+ for record in records {
195+ match record {
196+ ManifestRecord :: Flush ( sst_id) => {
197+ let res = memtables. remove ( & sst_id) ;
198+ assert ! ( res, "memtable not exist?" ) ;
199+ state. l0_sstables . insert ( 0 , sst_id) ;
200+ }
201+ ManifestRecord :: NewMemtable ( x) => {
202+ next_sst_id = x + 1 ;
203+ memtables. insert ( x) ;
204+ }
205+ ManifestRecord :: Compaction ( task, output) => {
206+ let ( new_state, _) =
207+ compaction_controller. apply_compaction_result ( & state, & task, & output) ;
208+ // TODO: apply remove again
209+ state = new_state;
210+ }
211+ }
212+ }
213+ // recover SSTs
214+ for table_id in state
215+ . l0_sstables
216+ . iter ( )
217+ . chain ( state. levels . iter ( ) . map ( |( _, files) | files) . flatten ( ) )
218+ {
219+ let table_id = * table_id;
220+ let sst = SsTable :: open (
221+ table_id,
222+ Some ( block_cache. clone ( ) ) ,
223+ FileObject :: open ( & Self :: path_of_sst_static ( path, table_id) )
224+ . context ( "failed to open SST" ) ?,
225+ ) ?;
226+ state. sstables . insert ( table_id, Arc :: new ( sst) ) ;
227+ }
228+ // recover memtables
229+ if options. enable_wal {
230+ for id in memtables. iter ( ) {
231+ let memtable =
232+ MemTable :: recover_from_wal ( * id, Self :: path_of_wal_static ( path, * id) ) ?;
233+ state. imm_memtables . insert ( 0 , Arc :: new ( memtable) ) ;
234+ next_sst_id = * id + 1 ;
235+ }
236+ state. memtable = Arc :: new ( MemTable :: create_with_wal (
237+ next_sst_id,
238+ Self :: path_of_wal_static ( path, next_sst_id) ,
239+ ) ?) ;
240+ } else {
241+ state. memtable = Arc :: new ( MemTable :: create ( next_sst_id) ) ;
242+ }
243+ m. add_record_when_init ( ManifestRecord :: NewMemtable ( state. memtable . id ( ) ) ) ?;
244+ next_sst_id += 1 ;
245+ manifest = m;
246+ } ;
247+
171248 let storage = Self {
172249 state : Arc :: new ( RwLock :: new ( Arc :: new ( state) ) ) ,
173250 state_lock : Mutex :: new ( ( ) ) ,
174251 path : path. to_path_buf ( ) ,
175- block_cache : Arc :: new ( BlockCache :: new ( 1 << 20 ) ) , // 4GB block cache,
176- next_sst_id : AtomicUsize :: new ( 1 ) ,
177- compaction_controller : match & options. compaction_options {
178- CompactionOptions :: Leveled ( options) => {
179- CompactionController :: Leveled ( LeveledCompactionController :: new ( options. clone ( ) ) )
180- }
181- CompactionOptions :: Tiered ( options) => {
182- CompactionController :: Tiered ( TieredCompactionController :: new ( options. clone ( ) ) )
183- }
184- CompactionOptions :: Simple ( options) => CompactionController :: Simple (
185- SimpleLeveledCompactionController :: new ( options. clone ( ) ) ,
186- ) ,
187- CompactionOptions :: NoCompaction => CompactionController :: NoCompaction ,
188- } ,
189- manifest : Manifest :: create ( path. join ( "MANIFEST" ) ) ?,
252+ block_cache,
253+ next_sst_id : AtomicUsize :: new ( next_sst_id) ,
254+ compaction_controller,
255+ manifest,
190256 options : options. into ( ) ,
191257 } ;
192258 storage. sync_dir ( ) ?;
@@ -259,8 +325,12 @@ impl LsmStorageInner {
259325 Ok ( ( ) )
260326 }
261327
328+ pub ( crate ) fn path_of_sst_static ( path : impl AsRef < Path > , id : usize ) -> PathBuf {
329+ path. as_ref ( ) . join ( format ! ( "{:05}.sst" , id) )
330+ }
331+
262332 pub ( crate ) fn path_of_sst ( & self , id : usize ) -> PathBuf {
263- self . path . join ( format ! ( "{:05}.sst" , id) )
333+ Self :: path_of_sst_static ( & self . path , id)
264334 }
265335
266336 pub ( crate ) fn path_of_wal_static ( path : impl AsRef < Path > , id : usize ) -> PathBuf {
@@ -303,7 +373,7 @@ impl LsmStorageInner {
303373 old_memtable. sync_wal ( ) ?;
304374
305375 self . manifest
306- . add_record ( & state_lock, ManifestRecord :: NewWal ( memtable_id) ) ?;
376+ . add_record ( & state_lock, ManifestRecord :: NewMemtable ( memtable_id) ) ?;
307377
308378 Ok ( ( ) )
309379 }
0 commit comments