1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/*--------------------------------------------------------------------------
*
* regress_injection.c
* Functions supporting test-specific subject matter.
*
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/test/modules/injection_points/regress_injection.c
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/table.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "postmaster/autovacuum.h"
#include "storage/procarray.h"
#include "utils/rel.h"
#include "utils/xid8.h"
/*
* removable_cutoff - for syscache-update-pruned.spec
*
* Wrapper around GetOldestNonRemovableTransactionId(). In general, this can
* move backward. runningcheck=false isolation tests can reasonably prevent
* that. For the causes of backward movement, see
* postgr.es/m/CAEze2Wj%2BV0kTx86xB_YbyaqTr5hnE_igdWAwuhSyjXBYscf5-Q%40mail.gmail.com
* and the header comment for ComputeXidHorizons(). One can assume this
* doesn't move backward if one (a) passes a shared catalog as the argument
* and (b) arranges for concurrent activity not to reach AbortTransaction().
* Non-runningcheck tests can control most concurrent activity, except
* autovacuum and the isolationtester control connection. AbortTransaction()
* in those would justify test failure. Seeing autoanalyze can allocate an
* XID in any database, (a) ensures we'll consistently not ignore those XIDs.
*/
PG_FUNCTION_INFO_V1(removable_cutoff);
Datum
removable_cutoff(PG_FUNCTION_ARGS)
{
Relation rel = NULL;
TransactionId xid;
FullTransactionId next_fxid_before,
next_fxid;
/* could take other relkinds callee takes, but we've not yet needed it */
if (!PG_ARGISNULL(0))
rel = table_open(PG_GETARG_OID(0), AccessShareLock);
if (!rel->rd_rel->relisshared && autovacuum_start_daemon)
elog(WARNING,
"removable_cutoff(non-shared-rel) can move backward under autovacuum=on");
/*
* No lock or snapshot necessarily prevents oldestXid from advancing past
* "xid" while this function runs. That concerns us only in that we must
* not ascribe "xid" to the wrong epoch. (That may never arise in
* isolation testing, but let's set a good example.) As a crude solution,
* retry until nextXid doesn't change.
*/
next_fxid = ReadNextFullTransactionId();
do
{
CHECK_FOR_INTERRUPTS();
next_fxid_before = next_fxid;
xid = GetOldestNonRemovableTransactionId(rel);
next_fxid = ReadNextFullTransactionId();
} while (!FullTransactionIdEquals(next_fxid, next_fxid_before));
if (rel)
table_close(rel, AccessShareLock);
PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromAllowableAt(next_fxid,
xid));
}
|