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 "storage/procarray.h" 21 : #include "utils/xid8.h" 22 : 23 : /* 24 : * removable_cutoff - for syscache-update-pruned.spec 25 : * 26 : * Wrapper around GetOldestNonRemovableTransactionId(). In general, this can 27 : * move backward. runningcheck=false isolation tests can reasonably prevent 28 : * that. For the causes of backward movement, see 29 : * postgr.es/m/CAEze2Wj%2BV0kTx86xB_YbyaqTr5hnE_igdWAwuhSyjXBYscf5-Q%40mail.gmail.com 30 : * and the header comment for ComputeXidHorizons(). One can assume this 31 : * doesn't move backward if one arranges for concurrent activity not to reach 32 : * AbortTransaction() and not to allocate an XID while connected to another 33 : * database. Non-runningcheck tests can control most concurrent activity, 34 : * except autovacuum and the isolationtester control connection. Neither 35 : * allocates XIDs, and AbortTransaction() in those would justify test failure. 36 : */ 37 64 : PG_FUNCTION_INFO_V1(removable_cutoff); 38 : Datum 39 12 : removable_cutoff(PG_FUNCTION_ARGS) 40 : { 41 12 : Relation rel = NULL; 42 : TransactionId xid; 43 : FullTransactionId next_fxid_before, 44 : next_fxid; 45 : 46 : /* could take other relkinds callee takes, but we've not yet needed it */ 47 12 : if (!PG_ARGISNULL(0)) 48 12 : rel = table_open(PG_GETARG_OID(0), AccessShareLock); 49 : 50 : /* 51 : * No lock or snapshot necessarily prevents oldestXid from advancing past 52 : * "xid" while this function runs. That concerns us only in that we must 53 : * not ascribe "xid" to the wrong epoch. (That may never arise in 54 : * isolation testing, but let's set a good example.) As a crude solution, 55 : * retry until nextXid doesn't change. 56 : */ 57 12 : next_fxid = ReadNextFullTransactionId(); 58 : do 59 : { 60 12 : CHECK_FOR_INTERRUPTS(); 61 12 : next_fxid_before = next_fxid; 62 12 : xid = GetOldestNonRemovableTransactionId(rel); 63 12 : next_fxid = ReadNextFullTransactionId(); 64 12 : } while (!FullTransactionIdEquals(next_fxid, next_fxid_before)); 65 : 66 12 : if (rel) 67 12 : table_close(rel, AccessShareLock); 68 : 69 12 : PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromAllowableAt(next_fxid, 70 : xid)); 71 : }