1
+ use crate :: sql:: column_def:: ColumnDef ;
2
+ use crate :: sql:: data_value:: DataValue ;
3
+ use crate :: error:: ReefDBError ;
4
+ use crate :: indexes:: { IndexManager , IndexType } ;
5
+ use crate :: indexes:: index_manager:: { IndexUpdate , DefaultIndexManager } ;
6
+ use memmap2:: { MmapMut , MmapOptions } ;
7
+ use std:: collections:: HashMap ;
8
+ use std:: fs:: { File , OpenOptions } ;
9
+ use std:: path:: Path ;
10
+ use bincode:: { serialize, deserialize} ;
11
+ use std:: any:: Any ;
12
+ use super :: Storage ;
13
+ use crate :: sql:: data_type:: DataType ;
14
+
15
+ #[ derive( Debug ) ]
16
+ pub struct MmapStorage {
17
+ file_path : String ,
18
+ tables : HashMap < String , ( Vec < ColumnDef > , Vec < Vec < DataValue > > ) > ,
19
+ index_manager : DefaultIndexManager ,
20
+ #[ allow( dead_code) ]
21
+ mmap : Option < MmapMut > ,
22
+ }
23
+
24
+ impl Clone for MmapStorage {
25
+ fn clone ( & self ) -> Self {
26
+ MmapStorage {
27
+ file_path : self . file_path . clone ( ) ,
28
+ tables : self . tables . clone ( ) ,
29
+ index_manager : self . index_manager . clone ( ) ,
30
+ mmap : None ,
31
+ }
32
+ }
33
+ }
34
+
35
+ impl MmapStorage {
36
+ pub fn new ( file_path : String ) -> Self {
37
+ let tables = if Path :: new ( & file_path) . exists ( ) {
38
+ let file = OpenOptions :: new ( )
39
+ . read ( true )
40
+ . write ( true )
41
+ . create ( true )
42
+ . open ( & file_path)
43
+ . unwrap ( ) ;
44
+
45
+ // Ensure file has some content
46
+ file. set_len ( 1024 * 1024 ) . unwrap ( ) ; // 1MB initial size
47
+
48
+ let mmap = unsafe { MmapOptions :: new ( ) . map_mut ( & file) . unwrap ( ) } ;
49
+
50
+ if mmap. len ( ) > 0 {
51
+ match deserialize ( & mmap[ ..] ) {
52
+ Ok ( tables) => tables,
53
+ Err ( _) => HashMap :: new ( ) ,
54
+ }
55
+ } else {
56
+ HashMap :: new ( )
57
+ }
58
+ } else {
59
+ HashMap :: new ( )
60
+ } ;
61
+
62
+ MmapStorage {
63
+ file_path,
64
+ tables,
65
+ index_manager : DefaultIndexManager :: new ( ) ,
66
+ mmap : None ,
67
+ }
68
+ }
69
+
70
+ fn save ( & mut self ) -> Result < ( ) , ReefDBError > {
71
+ let serialized = serialize ( & self . tables )
72
+ . map_err ( |e| ReefDBError :: Other ( format ! ( "Serialization error: {}" , e) ) ) ?;
73
+
74
+ let file = OpenOptions :: new ( )
75
+ . read ( true )
76
+ . write ( true )
77
+ . create ( true )
78
+ . open ( & self . file_path )
79
+ . map_err ( |e| ReefDBError :: IoError ( e. to_string ( ) ) ) ?;
80
+
81
+ // Ensure file is large enough
82
+ let required_size = serialized. len ( ) as u64 ;
83
+ file. set_len ( required_size)
84
+ . map_err ( |e| ReefDBError :: IoError ( e. to_string ( ) ) ) ?;
85
+
86
+ // Create new memory mapping
87
+ let mut mmap = unsafe {
88
+ MmapOptions :: new ( )
89
+ . len ( serialized. len ( ) )
90
+ . map_mut ( & file)
91
+ . map_err ( |e| ReefDBError :: IoError ( e. to_string ( ) ) ) ?
92
+ } ;
93
+
94
+ // Write data to memory map
95
+ mmap. copy_from_slice ( & serialized) ;
96
+
97
+ // Sync changes to disk
98
+ mmap. flush ( )
99
+ . map_err ( |e| ReefDBError :: IoError ( e. to_string ( ) ) ) ?;
100
+
101
+ self . mmap = Some ( mmap) ;
102
+ Ok ( ( ) )
103
+ }
104
+
105
+ fn get_default_value ( data_type : & DataType ) -> DataValue {
106
+ match data_type {
107
+ DataType :: Integer => DataValue :: Integer ( 0 ) ,
108
+ DataType :: Text => DataValue :: Text ( String :: new ( ) ) ,
109
+ DataType :: TSVector => DataValue :: Text ( String :: new ( ) ) ,
110
+ }
111
+ }
112
+ }
113
+
114
+ impl Storage for MmapStorage {
115
+ type NewArgs = String ;
116
+
117
+ fn new ( args : Self :: NewArgs ) -> Self {
118
+ Self :: new ( args)
119
+ }
120
+
121
+ fn insert_table (
122
+ & mut self ,
123
+ table_name : String ,
124
+ columns : Vec < ColumnDef > ,
125
+ rows : Vec < Vec < DataValue > > ,
126
+ ) {
127
+ self . tables . insert ( table_name, ( columns, rows) ) ;
128
+ let _ = self . save ( ) ;
129
+ }
130
+
131
+ fn get_table (
132
+ & mut self ,
133
+ table_name : & str ,
134
+ ) -> Option < & mut ( Vec < ColumnDef > , Vec < Vec < DataValue > > ) > {
135
+ self . tables . get_mut ( table_name)
136
+ }
137
+
138
+ fn get_table_ref ( & self , table_name : & str ) -> Option < & ( Vec < ColumnDef > , Vec < Vec < DataValue > > ) > {
139
+ self . tables . get ( table_name)
140
+ }
141
+
142
+ fn table_exists ( & self , table_name : & str ) -> bool {
143
+ self . tables . contains_key ( table_name)
144
+ }
145
+
146
+ fn push_value ( & mut self , table_name : & str , row : Vec < DataValue > ) -> Result < usize , ReefDBError > {
147
+ let len = if let Some ( ( _, rows) ) = self . tables . get_mut ( table_name) {
148
+ rows. push ( row) ;
149
+ rows. len ( )
150
+ } else {
151
+ return Err ( ReefDBError :: TableNotFound ( table_name. to_string ( ) ) ) ;
152
+ } ;
153
+ let _ = self . save ( ) ;
154
+ Ok ( len)
155
+ }
156
+
157
+ fn update_table (
158
+ & mut self ,
159
+ table_name : & str ,
160
+ updates : Vec < ( String , DataValue ) > ,
161
+ where_clause : Option < ( String , DataValue ) > ,
162
+ ) -> usize {
163
+ let mut updated_count = 0 ;
164
+ if let Some ( ( columns, rows) ) = self . tables . get_mut ( table_name) {
165
+ for row in rows. iter_mut ( ) {
166
+ let should_update = where_clause. as_ref ( ) . map_or ( true , |( col, val) | {
167
+ if let Some ( col_idx) = columns. iter ( ) . position ( |c| c. name == * col) {
168
+ & row[ col_idx] == val
169
+ } else {
170
+ false
171
+ }
172
+ } ) ;
173
+
174
+ if should_update {
175
+ for ( col, val) in & updates {
176
+ if let Some ( col_idx) = columns. iter ( ) . position ( |c| c. name == * col) {
177
+ row[ col_idx] = val. clone ( ) ;
178
+ }
179
+ }
180
+ updated_count += 1 ;
181
+ }
182
+ }
183
+ let _ = self . save ( ) ;
184
+ }
185
+ updated_count
186
+ }
187
+
188
+ fn delete_table (
189
+ & mut self ,
190
+ table_name : & str ,
191
+ where_clause : Option < ( String , DataValue ) > ,
192
+ ) -> usize {
193
+ let mut deleted_count = 0 ;
194
+ if let Some ( ( columns, rows) ) = self . tables . get_mut ( table_name) {
195
+ let initial_len = rows. len ( ) ;
196
+ rows. retain ( |row| {
197
+ let should_keep = where_clause. as_ref ( ) . map_or ( true , |( col, val) | {
198
+ if let Some ( col_idx) = columns. iter ( ) . position ( |c| c. name == * col) {
199
+ & row[ col_idx] != val
200
+ } else {
201
+ true
202
+ }
203
+ } ) ;
204
+ should_keep
205
+ } ) ;
206
+ deleted_count = initial_len - rows. len ( ) ;
207
+ let _ = self . save ( ) ;
208
+ }
209
+ deleted_count
210
+ }
211
+
212
+ fn remove_table ( & mut self , table_name : & str ) -> bool {
213
+ let exists = self . tables . remove ( table_name) . is_some ( ) ;
214
+ if exists {
215
+ let _ = self . save ( ) ;
216
+ }
217
+ exists
218
+ }
219
+
220
+ fn add_column ( & mut self , table_name : & str , column_def : ColumnDef ) -> Result < ( ) , ReefDBError > {
221
+ if let Some ( ( columns, rows) ) = self . tables . get_mut ( table_name) {
222
+ let default_value = Self :: get_default_value ( & column_def. data_type ) ;
223
+ columns. push ( column_def. clone ( ) ) ;
224
+ for row in rows. iter_mut ( ) {
225
+ row. push ( default_value. clone ( ) ) ;
226
+ }
227
+ let _ = self . save ( ) ;
228
+ Ok ( ( ) )
229
+ } else {
230
+ Err ( ReefDBError :: TableNotFound ( table_name. to_string ( ) ) )
231
+ }
232
+ }
233
+
234
+ fn drop_column ( & mut self , table_name : & str , column_name : & str ) -> Result < ( ) , ReefDBError > {
235
+ if let Some ( ( columns, rows) ) = self . tables . get_mut ( table_name) {
236
+ if let Some ( index) = columns. iter ( ) . position ( |c| c. name == column_name) {
237
+ columns. remove ( index) ;
238
+ for row in rows. iter_mut ( ) {
239
+ row. remove ( index) ;
240
+ }
241
+ let _ = self . save ( ) ;
242
+ Ok ( ( ) )
243
+ } else {
244
+ Err ( ReefDBError :: ColumnNotFound ( column_name. to_string ( ) ) )
245
+ }
246
+ } else {
247
+ Err ( ReefDBError :: TableNotFound ( table_name. to_string ( ) ) )
248
+ }
249
+ }
250
+
251
+ fn rename_column ( & mut self , table_name : & str , old_name : & str , new_name : & str ) -> Result < ( ) , ReefDBError > {
252
+ if let Some ( ( columns, _) ) = self . tables . get_mut ( table_name) {
253
+ if let Some ( col) = columns. iter_mut ( ) . find ( |c| c. name == old_name) {
254
+ col. name = new_name. to_string ( ) ;
255
+ let _ = self . save ( ) ;
256
+ Ok ( ( ) )
257
+ } else {
258
+ Err ( ReefDBError :: ColumnNotFound ( old_name. to_string ( ) ) )
259
+ }
260
+ } else {
261
+ Err ( ReefDBError :: TableNotFound ( table_name. to_string ( ) ) )
262
+ }
263
+ }
264
+
265
+ fn drop_table ( & mut self , table_name : & str ) {
266
+ self . tables . remove ( table_name) ;
267
+ let _ = self . save ( ) ;
268
+ }
269
+
270
+ fn clear ( & mut self ) {
271
+ self . tables . clear ( ) ;
272
+ let _ = self . save ( ) ;
273
+ }
274
+
275
+ fn get_all_tables ( & self ) -> & HashMap < String , ( Vec < ColumnDef > , Vec < Vec < DataValue > > ) > {
276
+ & self . tables
277
+ }
278
+
279
+ fn as_any ( & self ) -> & dyn Any {
280
+ self
281
+ }
282
+ }
283
+
284
+ impl IndexManager for MmapStorage {
285
+ fn create_index ( & mut self , table : & str , column : & str , index_type : IndexType ) -> Result < ( ) , ReefDBError > {
286
+ self . index_manager . create_index ( table, column, index_type)
287
+ }
288
+
289
+ fn drop_index ( & mut self , table : & str , column : & str ) {
290
+ self . index_manager . drop_index ( table, column)
291
+ }
292
+
293
+ fn get_index ( & self , table : & str , column : & str ) -> Result < & IndexType , ReefDBError > {
294
+ self . index_manager . get_index ( table, column)
295
+ }
296
+
297
+ fn update_index ( & mut self , table : & str , column : & str , old_value : Vec < u8 > , new_value : Vec < u8 > , row_id : usize ) -> Result < ( ) , ReefDBError > {
298
+ self . index_manager . update_index ( table, column, old_value, new_value, row_id)
299
+ }
300
+
301
+ fn track_index_update ( & mut self , update : IndexUpdate ) -> Result < ( ) , ReefDBError > {
302
+ self . index_manager . track_index_update ( update)
303
+ }
304
+
305
+ fn commit_index_transaction ( & mut self , transaction_id : u64 ) -> Result < ( ) , ReefDBError > {
306
+ self . index_manager . commit_index_transaction ( transaction_id)
307
+ }
308
+
309
+ fn rollback_index_transaction ( & mut self , transaction_id : u64 ) -> Result < ( ) , ReefDBError > {
310
+ self . index_manager . rollback_index_transaction ( transaction_id)
311
+ }
312
+ }
313
+
314
+ #[ cfg( test) ]
315
+ mod tests {
316
+ use super :: * ;
317
+ use crate :: sql:: constraints:: constraint:: Constraint ;
318
+ use tempfile:: NamedTempFile ;
319
+
320
+ #[ test]
321
+ fn test_mmap_storage ( ) {
322
+ let temp_file = NamedTempFile :: new ( ) . unwrap ( ) ;
323
+ let file_path = temp_file. path ( ) . to_string_lossy ( ) . to_string ( ) ;
324
+
325
+ // Create and populate storage
326
+ {
327
+ let mut storage = MmapStorage :: new ( file_path. clone ( ) ) ;
328
+ let columns = vec ! [
329
+ ColumnDef :: new( "id" , DataType :: Integer , vec![ Constraint :: PrimaryKey ] ) ,
330
+ ColumnDef :: new( "name" , DataType :: Text , vec![ ] ) ,
331
+ ColumnDef :: new( "age" , DataType :: Integer , vec![ ] ) ,
332
+ ] ;
333
+ let rows = vec ! [
334
+ vec![
335
+ DataValue :: Integer ( 1 ) ,
336
+ DataValue :: Text ( "John" . to_string( ) ) ,
337
+ DataValue :: Integer ( 20 ) ,
338
+ ] ,
339
+ vec![
340
+ DataValue :: Integer ( 2 ) ,
341
+ DataValue :: Text ( "Jane" . to_string( ) ) ,
342
+ DataValue :: Integer ( 25 ) ,
343
+ ] ,
344
+ ] ;
345
+ storage. insert_table ( "users" . to_string ( ) , columns, rows) ;
346
+ }
347
+
348
+ // Create new storage instance and verify persistence
349
+ {
350
+ let mut storage = MmapStorage :: new ( file_path) ;
351
+ let ( schema, rows) = storage. get_table ( "users" ) . unwrap ( ) ;
352
+ assert_eq ! ( schema. len( ) , 3 ) ;
353
+ assert_eq ! ( rows. len( ) , 2 ) ;
354
+ assert_eq ! ( rows[ 0 ] . len( ) , 3 ) ;
355
+ assert_eq ! ( rows[ 1 ] . len( ) , 3 ) ;
356
+ assert_eq ! ( rows[ 0 ] [ 0 ] , DataValue :: Integer ( 1 ) ) ;
357
+ assert_eq ! ( rows[ 0 ] [ 1 ] , DataValue :: Text ( "John" . to_string( ) ) ) ;
358
+ assert_eq ! ( rows[ 0 ] [ 2 ] , DataValue :: Integer ( 20 ) ) ;
359
+ assert_eq ! ( rows[ 1 ] [ 0 ] , DataValue :: Integer ( 2 ) ) ;
360
+ assert_eq ! ( rows[ 1 ] [ 1 ] , DataValue :: Text ( "Jane" . to_string( ) ) ) ;
361
+ assert_eq ! ( rows[ 1 ] [ 2 ] , DataValue :: Integer ( 25 ) ) ;
362
+ }
363
+ }
364
+ }
0 commit comments