@@ -11,6 +11,7 @@ use parking_lot::Mutex;
1111use std:: {
1212 fs:: File ,
1313 io,
14+ ops:: Deref ,
1415 path:: { Path , PathBuf } ,
1516} ;
1617
@@ -194,21 +195,6 @@ impl Database {
194195 Ok ( ( ) )
195196 }
196197
197- pub fn begin_rw ( & self ) -> Result < Transaction < ' _ , RW > , TransactionError > {
198- let context = self . storage_engine . write_context ( ) ;
199- let min_snapshot_id = self . transaction_manager . lock ( ) . begin_rw ( context. snapshot_id ) ?;
200- if min_snapshot_id > 0 {
201- self . storage_engine . unlock ( min_snapshot_id - 1 ) ;
202- }
203- Ok ( Transaction :: new ( context, self ) )
204- }
205-
206- pub fn begin_ro ( & self ) -> Result < Transaction < ' _ , RO > , TransactionError > {
207- let context = self . storage_engine . read_context ( ) ;
208- self . transaction_manager . lock ( ) . begin_ro ( context. snapshot_id ) ;
209- Ok ( Transaction :: new ( context, self ) )
210- }
211-
212198 pub fn state_root ( & self ) -> B256 {
213199 self . storage_engine . read_context ( ) . root_node_hash
214200 }
@@ -244,13 +230,32 @@ impl Database {
244230 }
245231}
246232
233+ pub fn begin_ro < DB : Deref < Target = Database > > (
234+ db : DB ,
235+ ) -> Result < Transaction < DB , RO > , TransactionError > {
236+ let context = db. storage_engine . read_context ( ) ;
237+ db. transaction_manager . lock ( ) . begin_ro ( context. snapshot_id ) ;
238+ Ok ( Transaction :: new ( context, db) )
239+ }
240+
241+ pub fn begin_rw < DB : Deref < Target = Database > > (
242+ db : DB ,
243+ ) -> Result < Transaction < DB , RW > , TransactionError > {
244+ let context = db. storage_engine . write_context ( ) ;
245+ let min_snapshot_id = db. transaction_manager . lock ( ) . begin_rw ( context. snapshot_id ) ?;
246+ if min_snapshot_id > 0 {
247+ db. storage_engine . unlock ( min_snapshot_id - 1 ) ;
248+ }
249+ Ok ( Transaction :: new ( context, db) )
250+ }
251+
247252#[ cfg( test) ]
248253mod tests {
249254 use super :: * ;
250255 use crate :: { account:: Account , path:: AddressPath } ;
251256 use alloy_primitives:: { address, Address , U256 } ;
252257 use alloy_trie:: { EMPTY_ROOT_HASH , KECCAK_EMPTY } ;
253- use std:: fs ;
258+ use std:: { fs , sync :: Arc } ;
254259 use tempdir:: TempDir ;
255260
256261 #[ test]
@@ -315,16 +320,16 @@ mod tests {
315320 let address = address ! ( "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" ) ;
316321
317322 let account1 = Account :: new ( 1 , U256 :: from ( 100 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ;
318- let mut tx = db . begin_rw ( ) . unwrap ( ) ;
323+ let mut tx = begin_rw ( & db ) . unwrap ( ) ;
319324 tx. set_account ( AddressPath :: for_address ( address) , Some ( account1. clone ( ) ) ) . unwrap ( ) ;
320325
321326 tx. commit ( ) . unwrap ( ) ;
322327
323328 let account2 = Account :: new ( 456 , U256 :: from ( 123 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ;
324- let mut tx = db . begin_rw ( ) . unwrap ( ) ;
329+ let mut tx = begin_rw ( & db ) . unwrap ( ) ;
325330 tx. set_account ( AddressPath :: for_address ( address) , Some ( account2. clone ( ) ) ) . unwrap ( ) ;
326331
327- let mut ro_tx = db . begin_ro ( ) . unwrap ( ) ;
332+ let mut ro_tx = begin_ro ( & db ) . unwrap ( ) ;
328333 tx. commit ( ) . unwrap ( ) ;
329334
330335 // The read transaction was created before the write was committed, so it should not see the
@@ -334,7 +339,7 @@ mod tests {
334339 assert_eq ! ( account1, read_account. unwrap( ) ) ;
335340
336341 // The writer transaction is committed, so the read transaction should see the changes.
337- let mut ro_tx = db . begin_ro ( ) . unwrap ( ) ;
342+ let mut ro_tx = begin_ro ( & db ) . unwrap ( ) ;
338343
339344 let read_account = ro_tx. get_account ( AddressPath :: for_address ( address) ) . unwrap ( ) ;
340345
@@ -372,29 +377,29 @@ mod tests {
372377 let address1 = address ! ( "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" ) ;
373378 let account1 = Account :: new ( 1 , U256 :: from ( 100 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ;
374379
375- let mut tx = db . begin_rw ( ) . unwrap ( ) ;
380+ let mut tx = begin_rw ( & db ) . unwrap ( ) ;
376381 tx. set_account ( AddressPath :: for_address ( address1) , Some ( account1. clone ( ) ) ) . unwrap ( ) ;
377382
378383 tx. commit ( ) . unwrap ( ) ;
379384 db. close ( ) . unwrap ( ) ;
380385
381386 let db = Database :: open ( & file_path) . unwrap ( ) ;
382- let mut tx = db . begin_ro ( ) . unwrap ( ) ;
387+ let mut tx = begin_ro ( & db ) . unwrap ( ) ;
383388 let account = tx. get_account ( AddressPath :: for_address ( address1) ) . unwrap ( ) . unwrap ( ) ;
384389 assert_eq ! ( account, account1) ;
385390
386391 tx. commit ( ) . unwrap ( ) ;
387392
388393 let address2 = address ! ( "0x1234567890abcdef1234567890abcdef12345678" ) ;
389394 let account2 = Account :: new ( 2 , U256 :: from ( 200 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ;
390- let mut tx = db . begin_rw ( ) . unwrap ( ) ;
395+ let mut tx = begin_rw ( & db ) . unwrap ( ) ;
391396 tx. set_account ( AddressPath :: for_address ( address2) , Some ( account2. clone ( ) ) ) . unwrap ( ) ;
392397
393398 tx. commit ( ) . unwrap ( ) ;
394399 db. close ( ) . unwrap ( ) ;
395400
396401 let db = Database :: open ( & file_path) . unwrap ( ) ;
397- let mut tx = db . begin_ro ( ) . unwrap ( ) ;
402+ let mut tx = begin_ro ( & db ) . unwrap ( ) ;
398403
399404 let account = tx. get_account ( AddressPath :: for_address ( address1) ) . unwrap ( ) . unwrap ( ) ;
400405 assert_eq ! ( account, account1) ;
@@ -434,7 +439,7 @@ mod tests {
434439 assert_eq ! ( db. storage_engine. page_manager. size( ) , 0 ) ;
435440
436441 // Add 1000 accounts
437- let mut tx = db . begin_rw ( ) . expect ( "rw transaction creation failed" ) ;
442+ let mut tx = begin_rw ( & db ) . expect ( "rw transaction creation failed" ) ;
438443 let initial_accounts = random_accounts ( 1000 ) . collect :: < Vec < _ > > ( ) ;
439444 for ( address, account) in & initial_accounts {
440445 tx. set_account ( address. clone ( ) , account. clone ( ) ) . expect ( "adding account failed" ) ;
@@ -456,7 +461,7 @@ mod tests {
456461 }
457462
458463 // Add 1000 more accounts
459- let mut tx = db . begin_rw ( ) . expect ( "rw transaction creation failed" ) ;
464+ let mut tx = begin_rw ( & db ) . expect ( "rw transaction creation failed" ) ;
460465 let more_accounts = random_accounts ( 1000 ) . collect :: < Vec < _ > > ( ) ;
461466 for ( address, account) in & more_accounts {
462467 tx. set_account ( address. clone ( ) , account. clone ( ) ) . expect ( "adding account failed" ) ;
@@ -487,7 +492,7 @@ mod tests {
487492 }
488493
489494 // Obtain a read transaction, and verify that it can access all the initial accounts
490- let mut read_tx = db . begin_ro ( ) . expect ( "ro transaction creation failed" ) ;
495+ let mut read_tx = begin_ro ( & db ) . expect ( "ro transaction creation failed" ) ;
491496 for ( address, account) in & initial_accounts {
492497 assert_eq ! (
493498 read_tx. get_account( address. clone( ) ) . expect( "error while reading account" ) ,
@@ -496,7 +501,7 @@ mod tests {
496501 }
497502
498503 // Delete the initial accounts
499- let mut tx = db . begin_rw ( ) . expect ( "rw transaction creation failed" ) ;
504+ let mut tx = begin_rw ( & db ) . expect ( "rw transaction creation failed" ) ;
500505 for ( address, _) in & initial_accounts {
501506 tx. set_account ( address. clone ( ) , None ) . expect ( "deleting account failed" ) ;
502507 }
@@ -512,4 +517,26 @@ mod tests {
512517 ) ;
513518 }
514519 }
520+
521+ #[ test]
522+ fn test_db_arc_tx ( ) {
523+ let tmp_dir = TempDir :: new ( "test_db" ) . unwrap ( ) ;
524+ let file_path = tmp_dir. path ( ) . join ( "test.db" ) ;
525+ let db = Database :: create_new ( & file_path) . unwrap ( ) ;
526+
527+ let db_arc = Arc :: new ( db) ;
528+
529+ let address = address ! ( "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" ) ;
530+ let mut tx = begin_rw ( db_arc. clone ( ) ) . unwrap ( ) ;
531+ tx. set_account (
532+ AddressPath :: for_address ( address) ,
533+ Some ( Account :: new ( 1 , U256 :: from ( 100 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ) ,
534+ )
535+ . unwrap ( ) ;
536+ tx. commit ( ) . unwrap ( ) ;
537+
538+ let mut tx = begin_ro ( db_arc) . unwrap ( ) ;
539+ let account = tx. get_account ( AddressPath :: for_address ( address) ) . unwrap ( ) . unwrap ( ) ;
540+ assert_eq ! ( account, Account :: new( 1 , U256 :: from( 100 ) , EMPTY_ROOT_HASH , KECCAK_EMPTY ) ) ;
541+ }
515542}
0 commit comments