Skip to content

Commit 1a2654b

Browse files
committed
Rework redundant code in subtrans.c
When this code was written the duplicity didn't matter, but with all the SLRU-bank stuff we just added, it has become excessive. Turn it into a simpler loop with no code duplication. Also add a test so that this code becomes covered. Discussion: https://postgr.es/m/202403041517.3a35jw53os65@alvherre.pgsql
1 parent 030e10f commit 1a2654b

File tree

2 files changed

+49
-22
lines changed

2 files changed

+49
-22
lines changed

src/backend/access/transam/subtrans.c

+7-22
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
311311
FullTransactionId nextXid;
312312
int64 startPage;
313313
int64 endPage;
314-
LWLock *prevlock;
314+
LWLock *prevlock = NULL;
315315
LWLock *lock;
316316

317317
/*
@@ -324,42 +324,27 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
324324
nextXid = TransamVariables->nextXid;
325325
endPage = TransactionIdToPage(XidFromFullTransactionId(nextXid));
326326

327-
prevlock = SimpleLruGetBankLock(SubTransCtl, startPage);
328-
LWLockAcquire(prevlock, LW_EXCLUSIVE);
329-
while (startPage != endPage)
327+
for (;;)
330328
{
331329
lock = SimpleLruGetBankLock(SubTransCtl, startPage);
332-
333-
/*
334-
* Check if we need to acquire the lock on the new bank then release
335-
* the lock on the old bank and acquire on the new bank.
336-
*/
337330
if (prevlock != lock)
338331
{
339-
LWLockRelease(prevlock);
332+
if (prevlock)
333+
LWLockRelease(prevlock);
340334
LWLockAcquire(lock, LW_EXCLUSIVE);
341335
prevlock = lock;
342336
}
343337

344338
(void) ZeroSUBTRANSPage(startPage);
339+
if (startPage == endPage)
340+
break;
341+
345342
startPage++;
346343
/* must account for wraparound */
347344
if (startPage > TransactionIdToPage(MaxTransactionId))
348345
startPage = 0;
349346
}
350347

351-
lock = SimpleLruGetBankLock(SubTransCtl, startPage);
352-
353-
/*
354-
* Check if we need to acquire the lock on the new bank then release the
355-
* lock on the old bank and acquire on the new bank.
356-
*/
357-
if (prevlock != lock)
358-
{
359-
LWLockRelease(prevlock);
360-
LWLockAcquire(lock, LW_EXCLUSIVE);
361-
}
362-
(void) ZeroSUBTRANSPage(startPage);
363348
LWLockRelease(lock);
364349
}
365350

src/test/recovery/t/009_twophase.pl

+42
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ sub configure_and_reload
4545
my $node_paris = PostgreSQL::Test::Cluster->new('paris');
4646
$node_paris->init_from_backup($node_london, 'london_backup',
4747
has_streaming => 1);
48+
$node_paris->append_conf(
49+
'postgresql.conf', qq(
50+
subtransaction_buffers = 32
51+
));
4852
$node_paris->start;
4953

5054
# Switch to synchronous replication in both directions
@@ -481,4 +485,42 @@ sub configure_and_reload
481485
qq{27|issued to paris},
482486
"Check expected t_009_tbl2 data on standby");
483487

488+
489+
# Exercise the 2PC recovery code in StartupSUBTRANS, which is concerned with
490+
# ensuring that enough pg_subtrans pages exist on disk to cover the range of
491+
# prepared transactions at server start time. There's not much we can verify
492+
# directly, but let's at least get the code to run.
493+
$cur_standby->stop();
494+
configure_and_reload($cur_primary, "synchronous_standby_names = ''");
495+
496+
$cur_primary->safe_psql('postgres', "CHECKPOINT");
497+
498+
my $start_lsn =
499+
$cur_primary->safe_psql('postgres', 'select pg_current_wal_insert_lsn()');
500+
$cur_primary->safe_psql('postgres',
501+
"CREATE TABLE test(); BEGIN; CREATE TABLE test1(); PREPARE TRANSACTION 'foo';"
502+
);
503+
my $osubtrans = $cur_primary->safe_psql('postgres',
504+
"select 'pg_subtrans/'||f, s.size from pg_ls_dir('pg_subtrans') f, pg_stat_file('pg_subtrans/'||f) s"
505+
);
506+
$cur_primary->pgbench(
507+
'--no-vacuum --client=5 --transactions=1000',
508+
0,
509+
[],
510+
[],
511+
'pgbench run to cause pg_subtrans traffic',
512+
{
513+
'009_twophase.pgb' => 'insert into test default values'
514+
});
515+
# StartupSUBTRANS is exercised with a wide range of visible XIDs in this
516+
# stop/start sequence, because we left a prepared transaction open above.
517+
# Also, setting subtransaction_buffers to 32 above causes to switch SLRU
518+
# bank, for additional code coverage.
519+
$cur_primary->stop;
520+
$cur_primary->start;
521+
my $nsubtrans = $cur_primary->safe_psql('postgres',
522+
"select 'pg_subtrans/'||f, s.size from pg_ls_dir('pg_subtrans') f, pg_stat_file('pg_subtrans/'||f) s"
523+
);
524+
isnt($osubtrans, $nsubtrans, "contents of pg_subtrans/ have changed");
525+
484526
done_testing();

0 commit comments

Comments
 (0)