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