@@ -229,7 +229,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
229
229
#crate_:: std_enabled! {
230
230
pub struct RuntimeApiImpl <Block : #crate_:: BlockT , C : #crate_:: CallApiAt <Block > + ' static > {
231
231
call: & ' static C ,
232
- commit_on_success : std:: cell:: RefCell <bool >,
232
+ transaction_depth : std:: cell:: RefCell <u16 >,
233
233
changes: std:: cell:: RefCell <#crate_:: OverlayedChanges >,
234
234
storage_transaction_cache: std:: cell:: RefCell <
235
235
#crate_:: StorageTransactionCache <Block , C :: StateBackend >
@@ -248,11 +248,15 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
248
248
) -> R where Self : Sized {
249
249
self . start_transaction( ) ;
250
250
251
- * std:: cell:: RefCell :: borrow_mut( & self . commit_on_success ) = false ;
251
+ * std:: cell:: RefCell :: borrow_mut( & self . transaction_depth ) += 1 ;
252
252
let res = call( self ) ;
253
- * std:: cell:: RefCell :: borrow_mut( & self . commit_on_success) = true ;
253
+ std:: cell:: RefCell :: borrow_mut( & self . transaction_depth)
254
+ . checked_sub( 1 )
255
+ . expect( "Transactions are opened and closed together; qed" ) ;
254
256
255
- self . commit_or_rollback( std:: matches!( res, #crate_:: TransactionOutcome :: Commit ( _) ) ) ;
257
+ self . commit_or_rollback_transaction(
258
+ std:: matches!( res, #crate_:: TransactionOutcome :: Commit ( _) )
259
+ ) ;
256
260
257
261
res. into_inner( )
258
262
}
@@ -332,7 +336,7 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
332
336
) -> #crate_:: ApiRef <' a, Self :: RuntimeApi > {
333
337
RuntimeApiImpl {
334
338
call: unsafe { std:: mem:: transmute( call) } ,
335
- commit_on_success : true . into( ) ,
339
+ transaction_depth : 0 . into( ) ,
336
340
changes: std:: default :: Default :: default ( ) ,
337
341
recorder: std:: default :: Default :: default ( ) ,
338
342
storage_transaction_cache: std:: default :: Default :: default ( ) ,
@@ -341,52 +345,47 @@ fn generate_runtime_api_base_structures() -> Result<TokenStream> {
341
345
}
342
346
343
347
impl <Block : #crate_:: BlockT , C : #crate_:: CallApiAt <Block >> RuntimeApiImpl <Block , C > {
344
- fn commit_or_rollback ( & self , commit: bool ) {
348
+ fn commit_or_rollback_transaction ( & self , commit: bool ) {
345
349
let proof = "\
346
350
We only close a transaction when we opened one ourself.
347
351
Other parts of the runtime that make use of transactions (state-machine)
348
352
also balance their transactions. The runtime cannot close client initiated
349
353
transactions; qed" ;
350
- if * std:: cell:: RefCell :: borrow( & self . commit_on_success) {
351
- let res = if commit {
352
- let res = if let Some ( recorder) = & self . recorder {
353
- #crate_:: ProofRecorder :: <Block >:: commit_transaction( & recorder)
354
- } else {
355
- Ok ( ( ) )
356
- } ;
357
354
358
- let res2 = #crate_:: OverlayedChanges :: commit_transaction(
359
- & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
360
- ) ;
361
-
362
- // Will panic on an `Err` below, however we should call commit
363
- // on the recorder and the changes together.
364
- std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
355
+ let res = if commit {
356
+ let res = if let Some ( recorder) = & self . recorder {
357
+ #crate_:: ProofRecorder :: <Block >:: commit_transaction( & recorder)
365
358
} else {
366
- let res = if let Some ( recorder) = & self . recorder {
367
- #crate_:: ProofRecorder :: <Block >:: rollback_transaction( & recorder)
368
- } else {
369
- Ok ( ( ) )
370
- } ;
359
+ Ok ( ( ) )
360
+ } ;
371
361
372
- let res2 = #crate_:: OverlayedChanges :: rollback_transaction (
373
- & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
374
- ) ;
362
+ let res2 = #crate_:: OverlayedChanges :: commit_transaction (
363
+ & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
364
+ ) ;
375
365
376
- // Will panic on an `Err` below, however we should call commit
377
- // on the recorder and the changes together.
378
- std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
366
+ // Will panic on an `Err` below, however we should call commit
367
+ // on the recorder and the changes together.
368
+ std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
369
+ } else {
370
+ let res = if let Some ( recorder) = & self . recorder {
371
+ #crate_:: ProofRecorder :: <Block >:: rollback_transaction( & recorder)
372
+ } else {
373
+ Ok ( ( ) )
379
374
} ;
380
375
381
- std:: result:: Result :: expect( res, proof) ;
382
- }
376
+ let res2 = #crate_:: OverlayedChanges :: rollback_transaction(
377
+ & mut std:: cell:: RefCell :: borrow_mut( & self . changes)
378
+ ) ;
379
+
380
+ // Will panic on an `Err` below, however we should call commit
381
+ // on the recorder and the changes together.
382
+ std:: result:: Result :: and( res, std:: result:: Result :: map_err( res2, drop) )
383
+ } ;
384
+
385
+ std:: result:: Result :: expect( res, proof) ;
383
386
}
384
387
385
388
fn start_transaction( & self ) {
386
- if !* std:: cell:: RefCell :: borrow( & self . commit_on_success) {
387
- return
388
- }
389
-
390
389
#crate_:: OverlayedChanges :: start_transaction(
391
390
& mut std:: cell:: RefCell :: borrow_mut( & self . changes)
392
391
) ;
@@ -486,7 +485,13 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
486
485
params: std:: vec:: Vec <u8 >,
487
486
fn_name: & dyn Fn ( #crate_:: RuntimeVersion ) -> & ' static str ,
488
487
) -> std:: result:: Result <std:: vec:: Vec <u8 >, #crate_:: ApiError > {
489
- self . start_transaction( ) ;
488
+ // If we are not already in a transaction, we should create a new transaction
489
+ // and then commit/roll it back at the end!
490
+ let transaction_depth = * std:: cell:: RefCell :: borrow( & self . transaction_depth) ;
491
+
492
+ if transaction_depth == 0 {
493
+ self . start_transaction( ) ;
494
+ }
490
495
491
496
let res = ( || {
492
497
let version = #crate_:: CallApiAt :: <__SrApiBlock__>:: runtime_version_at(
@@ -510,7 +515,9 @@ impl<'a> ApiRuntimeImplToApiRuntimeApiImpl<'a> {
510
515
)
511
516
} ) ( ) ;
512
517
513
- self . commit_or_rollback( std:: result:: Result :: is_ok( & res) ) ;
518
+ if transaction_depth == 0 {
519
+ self . commit_or_rollback_transaction( std:: result:: Result :: is_ok( & res) ) ;
520
+ }
514
521
515
522
res
516
523
}
0 commit comments