11use std:: collections:: HashMap ;
2+ use std:: fs:: File ;
3+ use std:: io:: { BufWriter , Write } ;
24use std:: path:: Path ;
35
46use redb:: { Database , Error , TableDefinition } ;
@@ -15,8 +17,10 @@ pub struct Cache {
1517 metadata : HashMap < String , CacheMetadataItem > , // Dictionary of metadata (and occasionally data [mostly for very small files])
1618 db : Option < Database > , // Pointer to database instance; None if not yet initialized or if failed to initialize
1719 db_ok : Option < bool > , // None by default, Some(true) if was able to initialize database, Some (false) if an error occured
20+ db_file_path : Option < String > , // Filesystem path to file used for storing database
1821}
1922
23+ const FILE_WRITE_BUF_LEN : usize = 1024 * 100 ; // On-disk cache file write buffer size (in bytes)
2024const TABLE : TableDefinition < & str , & [ u8 ] > = TableDefinition :: new ( "_" ) ;
2125
2226impl Cache {
@@ -26,6 +30,7 @@ impl Cache {
2630 metadata : HashMap :: new ( ) ,
2731 db : None ,
2832 db_ok : None ,
33+ db_file_path : db_file_path. clone ( ) ,
2934 } ;
3035
3136 if db_file_path. is_some ( ) {
@@ -52,14 +57,14 @@ impl Cache {
5257 data : if self . db_ok . is_some ( ) && self . db_ok . unwrap ( ) {
5358 None
5459 } else {
55- Some ( ( data. to_owned ( ) ) . to_vec ( ) )
60+ Some ( data. to_owned ( ) . to_vec ( ) )
5661 } ,
5762 media_type : Some ( media_type. to_owned ( ) ) ,
5863 charset : Some ( charset) ,
5964 } ;
6065
6166 if ( self . db_ok . is_none ( ) || !self . db_ok . unwrap ( ) ) || data. len ( ) <= self . min_file_size {
62- cache_metadata_item. data = Some ( ( data. to_owned ( ) ) . to_vec ( ) ) ;
67+ cache_metadata_item. data = Some ( data. to_owned ( ) . to_vec ( ) ) ;
6368 } else {
6469 match self . db . as_ref ( ) . unwrap ( ) . begin_write ( ) {
6570 Ok ( write_txn) => {
@@ -71,7 +76,7 @@ impl Cache {
7176 }
7277 Err ( ..) => {
7378 // Fall back to caching everything in memory
74- cache_metadata_item. data = Some ( ( data. to_owned ( ) ) . to_vec ( ) ) ;
79+ cache_metadata_item. data = Some ( data. to_owned ( ) . to_vec ( ) ) ;
7580 }
7681 }
7782 }
@@ -110,4 +115,40 @@ impl Cache {
110115 pub fn contains_key ( & self , key : & str ) -> bool {
111116 self . metadata . contains_key ( key)
112117 }
118+
119+ pub fn destroy_database_file ( & mut self ) {
120+ if self . db_ok . is_none ( ) || !self . db_ok . unwrap ( ) {
121+ return ;
122+ }
123+
124+ // Destroy database instance (prevents writes into file)
125+ self . db = None ;
126+ self . db_ok = Some ( false ) ;
127+
128+ // Wipe database file
129+ if let Some ( db_file_path) = self . db_file_path . to_owned ( ) {
130+ // Overwrite file with zeroes
131+ if let Ok ( temp_file) = File :: options ( )
132+ . read ( true )
133+ . write ( true )
134+ . open ( db_file_path. clone ( ) )
135+ {
136+ let mut buffer = [ 0 ; FILE_WRITE_BUF_LEN ] ;
137+ let mut remaining_size: usize = temp_file. metadata ( ) . unwrap ( ) . len ( ) as usize ;
138+ let mut writer = BufWriter :: new ( temp_file) ;
139+
140+ while remaining_size > 0 {
141+ let bytes_to_write: usize = if remaining_size < FILE_WRITE_BUF_LEN {
142+ remaining_size
143+ } else {
144+ FILE_WRITE_BUF_LEN
145+ } ;
146+ let buffer = & mut buffer[ ..bytes_to_write] ;
147+ writer. write ( buffer) . unwrap ( ) ;
148+
149+ remaining_size -= bytes_to_write;
150+ }
151+ }
152+ }
153+ }
113154}
0 commit comments