@@ -346,8 +346,8 @@ static void CommitTransaction(void);
346
346
static TransactionId RecordTransactionAbort (bool isSubXact );
347
347
static void StartTransaction (void );
348
348
349
- static void CommitTransactionCommandInternal (void );
350
- static void AbortCurrentTransactionInternal (void );
349
+ static bool CommitTransactionCommandInternal (void );
350
+ static bool AbortCurrentTransactionInternal (void );
351
351
352
352
static void StartSubTransaction (void );
353
353
static void CommitSubTransaction (void );
@@ -3092,50 +3092,27 @@ RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
3092
3092
void
3093
3093
CommitTransactionCommand (void )
3094
3094
{
3095
- while (true)
3095
+ /*
3096
+ * Repeatedly call CommitTransactionCommandInternal() until all the work
3097
+ * is done.
3098
+ */
3099
+ while (!CommitTransactionCommandInternal ())
3096
3100
{
3097
- switch (CurrentTransactionState -> blockState )
3098
- {
3099
- /*
3100
- * The current already-failed subtransaction is ending due to
3101
- * a ROLLBACK or ROLLBACK TO command, so pop it and
3102
- * recursively examine the parent (which could be in any of
3103
- * several states).
3104
- */
3105
- case TBLOCK_SUBABORT_END :
3106
- CleanupSubTransaction ();
3107
- continue ;
3108
-
3109
- /*
3110
- * As above, but it's not dead yet, so abort first.
3111
- */
3112
- case TBLOCK_SUBABORT_PENDING :
3113
- AbortSubTransaction ();
3114
- CleanupSubTransaction ();
3115
- continue ;
3116
- default :
3117
- break ;
3118
- }
3119
- CommitTransactionCommandInternal ();
3120
- break ;
3121
3101
}
3122
3102
}
3123
3103
3124
3104
/*
3125
- * CommitTransactionCommandInternal - a function doing all the material work
3126
- * regarding handling the commit transaction command except for loop over
3127
- * subtransactions.
3105
+ * CommitTransactionCommandInternal - a function doing an iteration of work
3106
+ * regarding handling the commit transaction command. In the case of
3107
+ * subtransactions more than one iterations could be required. Returns
3108
+ * true when no more iterations required, false otherwise.
3128
3109
*/
3129
- static void
3110
+ static bool
3130
3111
CommitTransactionCommandInternal (void )
3131
3112
{
3132
3113
TransactionState s = CurrentTransactionState ;
3133
3114
SavedTransactionCharacteristics savetc ;
3134
3115
3135
- /* This states are handled in CommitTransactionCommand() */
3136
- Assert (s -> blockState != TBLOCK_SUBABORT_END &&
3137
- s -> blockState != TBLOCK_SUBABORT_PENDING );
3138
-
3139
3116
/* Must save in case we need to restore below */
3140
3117
SaveTransactionCharacteristics (& savetc );
3141
3118
@@ -3319,6 +3296,25 @@ CommitTransactionCommandInternal(void)
3319
3296
BlockStateAsString (s -> blockState ));
3320
3297
break ;
3321
3298
3299
+ /*
3300
+ * The current already-failed subtransaction is ending due to a
3301
+ * ROLLBACK or ROLLBACK TO command, so pop it and recursively
3302
+ * examine the parent (which could be in any of several states).
3303
+ * As we need to examine the parent, return false to request the
3304
+ * caller to do the next iteration.
3305
+ */
3306
+ case TBLOCK_SUBABORT_END :
3307
+ CleanupSubTransaction ();
3308
+ return false;
3309
+
3310
+ /*
3311
+ * As above, but it's not dead yet, so abort first.
3312
+ */
3313
+ case TBLOCK_SUBABORT_PENDING :
3314
+ AbortSubTransaction ();
3315
+ CleanupSubTransaction ();
3316
+ return false;
3317
+
3322
3318
/*
3323
3319
* The current subtransaction is the target of a ROLLBACK TO
3324
3320
* command. Abort and pop it, then start a new subtransaction
@@ -3376,10 +3372,10 @@ CommitTransactionCommandInternal(void)
3376
3372
s -> blockState = TBLOCK_SUBINPROGRESS ;
3377
3373
}
3378
3374
break ;
3379
- default :
3380
- /* Keep compiler quiet */
3381
- break ;
3382
3375
}
3376
+
3377
+ /* Done, no more iterations required */
3378
+ return true;
3383
3379
}
3384
3380
3385
3381
/*
@@ -3390,59 +3386,26 @@ CommitTransactionCommandInternal(void)
3390
3386
void
3391
3387
AbortCurrentTransaction (void )
3392
3388
{
3393
- while (true)
3389
+ /*
3390
+ * Repeatedly call AbortCurrentTransactionInternal() until all the work is
3391
+ * done.
3392
+ */
3393
+ while (!AbortCurrentTransactionInternal ())
3394
3394
{
3395
- switch (CurrentTransactionState -> blockState )
3396
- {
3397
- /*
3398
- * If we failed while trying to create a subtransaction, clean
3399
- * up the broken subtransaction and abort the parent. The
3400
- * same applies if we get a failure while ending a
3401
- * subtransaction.
3402
- */
3403
- case TBLOCK_SUBBEGIN :
3404
- case TBLOCK_SUBRELEASE :
3405
- case TBLOCK_SUBCOMMIT :
3406
- case TBLOCK_SUBABORT_PENDING :
3407
- case TBLOCK_SUBRESTART :
3408
- AbortSubTransaction ();
3409
- CleanupSubTransaction ();
3410
- continue ;
3411
-
3412
- /*
3413
- * Same as above, except the Abort() was already done.
3414
- */
3415
- case TBLOCK_SUBABORT_END :
3416
- case TBLOCK_SUBABORT_RESTART :
3417
- CleanupSubTransaction ();
3418
- continue ;
3419
- default :
3420
- break ;
3421
- }
3422
- AbortCurrentTransactionInternal ();
3423
- break ;
3424
3395
}
3425
3396
}
3426
3397
3427
3398
/*
3428
- * AbortCurrentTransactionInternal - a function doing all the material work
3429
- * regarding handling the abort transaction command except for loop over
3430
- * subtransactions.
3399
+ * AbortCurrentTransactionInternal - a function doing an iteration of work
3400
+ * regarding handling the current transaction abort. In the case of
3401
+ * subtransactions more than one iterations could be required. Returns
3402
+ * true when no more iterations required, false otherwise.
3431
3403
*/
3432
- static void
3404
+ static bool
3433
3405
AbortCurrentTransactionInternal (void )
3434
3406
{
3435
3407
TransactionState s = CurrentTransactionState ;
3436
3408
3437
- /* This states are handled in AbortCurrentTransaction() */
3438
- Assert (s -> blockState != TBLOCK_SUBBEGIN &&
3439
- s -> blockState != TBLOCK_SUBRELEASE &&
3440
- s -> blockState != TBLOCK_SUBCOMMIT &&
3441
- s -> blockState != TBLOCK_SUBABORT_PENDING &&
3442
- s -> blockState != TBLOCK_SUBRESTART &&
3443
- s -> blockState != TBLOCK_SUBABORT_END &&
3444
- s -> blockState != TBLOCK_SUBABORT_RESTART );
3445
-
3446
3409
switch (s -> blockState )
3447
3410
{
3448
3411
case TBLOCK_DEFAULT :
@@ -3563,10 +3526,34 @@ AbortCurrentTransactionInternal(void)
3563
3526
AbortSubTransaction ();
3564
3527
s -> blockState = TBLOCK_SUBABORT ;
3565
3528
break ;
3566
- default :
3567
- /* Keep compiler quiet */
3568
- break ;
3529
+
3530
+ /*
3531
+ * If we failed while trying to create a subtransaction, clean up
3532
+ * the broken subtransaction and abort the parent. The same
3533
+ * applies if we get a failure while ending a subtransaction. As
3534
+ * we need to abort the parent, return false to request the caller
3535
+ * to do the next iteration.
3536
+ */
3537
+ case TBLOCK_SUBBEGIN :
3538
+ case TBLOCK_SUBRELEASE :
3539
+ case TBLOCK_SUBCOMMIT :
3540
+ case TBLOCK_SUBABORT_PENDING :
3541
+ case TBLOCK_SUBRESTART :
3542
+ AbortSubTransaction ();
3543
+ CleanupSubTransaction ();
3544
+ return false;
3545
+
3546
+ /*
3547
+ * Same as above, except the Abort() was already done.
3548
+ */
3549
+ case TBLOCK_SUBABORT_END :
3550
+ case TBLOCK_SUBABORT_RESTART :
3551
+ CleanupSubTransaction ();
3552
+ return false;
3569
3553
}
3554
+
3555
+ /* Done, no more iterations required */
3556
+ return true;
3570
3557
}
3571
3558
3572
3559
/*
0 commit comments