@@ -13,7 +13,7 @@ use libsql_sys::rusqlite;
13
13
use libsql_sys:: wal:: { Result , Vfs , Wal , WalManager } ;
14
14
use rpc:: storage_client:: StorageClient ;
15
15
use tonic:: transport:: Channel ;
16
- use tracing:: { error, trace} ;
16
+ use tracing:: { error, trace, warn } ;
17
17
18
18
pub mod rpc {
19
19
#![ allow( clippy:: all) ]
@@ -23,12 +23,7 @@ pub mod rpc {
23
23
// What does (not) work:
24
24
// - there are no read txn locks nor upgrades
25
25
// - no lock stealing
26
- // - write set is kept in mem
27
- // - txns don't use max_frame_no yet
28
26
// - no savepoints, yet
29
- // - no multi tenancy, uses `default` namespace
30
- // - txn can read new frames after it started (since there are no read locks)
31
- // - requires huge memory as it assumes all the txn data fits in the memory
32
27
33
28
#[ derive( Clone , Default ) ]
34
29
pub struct DurableWalConfig {
@@ -178,17 +173,6 @@ impl DurableWal {
178
173
. flatten ( ) ;
179
174
Ok ( frame_no)
180
175
}
181
-
182
- async fn frames_count ( & self ) -> u64 {
183
- let req = rpc:: FramesInWalRequest {
184
- namespace : self . namespace . to_string ( ) ,
185
- } ;
186
- let mut binding = self . client . clone ( ) ;
187
- let resp = binding. frames_in_wal ( req) . await . unwrap ( ) ;
188
- let count = resp. into_inner ( ) . count ;
189
- trace ! ( "DurableWal::frames_in_wal() = {}" , count) ;
190
- count
191
- }
192
176
}
193
177
194
178
impl Wal for DurableWal {
@@ -200,9 +184,7 @@ impl Wal for DurableWal {
200
184
// - create a read lock
201
185
// - save the current max_frame_no for this txn
202
186
trace ! ( "DurableWal::begin_read_txn()" ) ;
203
- let rt = tokio:: runtime:: Handle :: current ( ) ;
204
- let frame_no = tokio:: task:: block_in_place ( || rt. block_on ( self . frames_count ( ) ) ) ;
205
- self . max_frame_no = frame_no;
187
+ self . max_frame_no = self . local_cache . get_max_frame_num ( ) . unwrap ( ) ;
206
188
Ok ( true )
207
189
}
208
190
@@ -232,21 +214,14 @@ impl Wal for DurableWal {
232
214
if self . max_frame_no == 0 {
233
215
return Ok ( None ) ;
234
216
}
235
- let rt = tokio:: runtime:: Handle :: current ( ) ;
236
- // TODO: find_frame should account for `max_frame_no` of this txn
237
- let frame_no =
238
- tokio:: task:: block_in_place ( || rt. block_on ( self . find_frame_by_page_no ( page_no) ) )
239
- . unwrap ( ) ;
240
- if frame_no. is_none ( ) {
241
- return Ok ( None ) ;
242
- }
243
217
return Ok ( Some ( page_no) ) ;
244
218
}
245
219
246
220
#[ tracing:: instrument( skip_all, fields( page_no) ) ]
247
221
fn read_frame ( & mut self , page_no : std:: num:: NonZeroU32 , buffer : & mut [ u8 ] ) -> Result < ( ) > {
248
222
trace ! ( "DurableWal::read_frame()" ) ;
249
- let rt = tokio:: runtime:: Handle :: current ( ) ;
223
+ // to read a frame, first we check in transaction cache, then frames cache and lastly
224
+ // storage server
250
225
if let Ok ( Some ( frame) ) = self
251
226
. local_cache
252
227
. get_page ( self . conn_id . as_str ( ) , u32:: from ( page_no) )
@@ -258,20 +233,23 @@ impl Wal for DurableWal {
258
233
buffer. copy_from_slice ( & frame) ;
259
234
return Ok ( ( ) ) ;
260
235
}
261
- // TODO: this call is unnecessary since `read_frame` is always called after `find_frame`
262
- let frame_no =
263
- tokio:: task:: block_in_place ( || rt. block_on ( self . find_frame_by_page_no ( page_no) ) )
264
- . unwrap ( )
265
- . unwrap ( ) ;
266
236
// check if the frame exists in the local cache
267
- if let Ok ( Some ( frame) ) = self . local_cache . get_frame ( frame_no. into ( ) ) {
237
+ if let Ok ( Some ( frame) ) = self
238
+ . local_cache
239
+ . get_frame_by_page ( u32:: from ( page_no) , self . max_frame_no )
240
+ {
268
241
trace ! (
269
242
"DurableWal::read_frame(page_no: {:?}) -- read cache hit" ,
270
243
page_no
271
244
) ;
272
245
buffer. copy_from_slice ( & frame) ;
273
246
return Ok ( ( ) ) ;
274
247
}
248
+ let rt = tokio:: runtime:: Handle :: current ( ) ;
249
+ let frame_no =
250
+ tokio:: task:: block_in_place ( || rt. block_on ( self . find_frame_by_page_no ( page_no) ) )
251
+ . unwrap ( )
252
+ . unwrap ( ) ;
275
253
let req = rpc:: ReadFrameRequest {
276
254
namespace : self . namespace . to_string ( ) ,
277
255
frame_no : frame_no. get ( ) ,
@@ -281,17 +259,17 @@ impl Wal for DurableWal {
281
259
let resp = tokio:: task:: block_in_place ( || rt. block_on ( resp) ) . unwrap ( ) ;
282
260
let frame = resp. into_inner ( ) . frame . unwrap ( ) ;
283
261
buffer. copy_from_slice ( & frame) ;
284
- let _ = self . local_cache . insert_frame ( frame_no. into ( ) , & frame) ;
262
+ let _ = self
263
+ . local_cache
264
+ . insert_frame ( frame_no. into ( ) , u32:: from ( page_no) , & frame) ;
285
265
Ok ( ( ) )
286
266
}
287
267
288
268
fn db_size ( & self ) -> u32 {
289
- let rt = tokio:: runtime:: Handle :: current ( ) ;
290
- let size = tokio:: task:: block_in_place ( || rt. block_on ( self . frames_count ( ) ) )
291
- . try_into ( )
292
- . unwrap ( ) ;
269
+ let size = self . local_cache . get_max_frame_num ( ) . unwrap ( ) ;
293
270
trace ! ( "DurableWal::db_size() => {}" , size) ;
294
- size
271
+ // TODO: serve the db size from the meta table
272
+ size as u32
295
273
}
296
274
297
275
fn begin_write_txn ( & mut self ) -> Result < ( ) > {
@@ -379,7 +357,7 @@ impl Wal for DurableWal {
379
357
380
358
let req = rpc:: InsertFramesRequest {
381
359
namespace : self . namespace . to_string ( ) ,
382
- frames,
360
+ frames : frames . clone ( ) ,
383
361
max_frame_no : self . max_frame_no ,
384
362
} ;
385
363
let mut binding = self . client . clone ( ) ;
@@ -392,6 +370,10 @@ impl Wal for DurableWal {
392
370
}
393
371
return Err ( rusqlite:: ffi:: Error :: new ( SQLITE_ABORT ) ) ;
394
372
}
373
+ // TODO: fix parity with storage server frame num with local cache
374
+ self . local_cache
375
+ . insert_frames ( self . max_frame_no , frames)
376
+ . unwrap ( ) ;
395
377
Ok ( resp. unwrap ( ) . into_inner ( ) . num_frames as usize )
396
378
}
397
379
0 commit comments