Line data Source code
1 : /*-------------------------------------------------------------------------- 2 : * 3 : * regress_injection.c 4 : * Functions supporting test-specific subject matter. 5 : * 6 : * Portions Copyright (c) 1996-2025, 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 68 : PG_FUNCTION_INFO_V1(removable_cutoff); 41 : Datum 42 18 : removable_cutoff(PG_FUNCTION_ARGS) 43 : { 44 18 : 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 18 : if (!PG_ARGISNULL(0)) 51 18 : rel = table_open(PG_GETARG_OID(0), AccessShareLock); 52 : 53 18 : if (!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 18 : next_fxid = ReadNextFullTransactionId(); 65 : do 66 : { 67 18 : CHECK_FOR_INTERRUPTS(); 68 18 : next_fxid_before = next_fxid; 69 18 : xid = GetOldestNonRemovableTransactionId(rel); 70 18 : next_fxid = ReadNextFullTransactionId(); 71 18 : } while (!FullTransactionIdEquals(next_fxid, next_fxid_before)); 72 : 73 18 : if (rel) 74 18 : table_close(rel, AccessShareLock); 75 : 76 18 : PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromAllowableAt(next_fxid, 77 : xid)); 78 : }