| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * transam.h |
| 4 | * postgres transaction access method support code |
| 5 | * |
| 6 | * |
| 7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 8 | * Portions Copyright (c) 1994, Regents of the University of California |
| 9 | * |
| 10 | * src/include/access/transam.h |
| 11 | * |
| 12 | *------------------------------------------------------------------------- |
| 13 | */ |
| 14 | #ifndef TRANSAM_H |
| 15 | #define TRANSAM_H |
| 16 | |
| 17 | #include "access/xlogdefs.h" |
| 18 | |
| 19 | |
| 20 | /* ---------------- |
| 21 | * Special transaction ID values |
| 22 | * |
| 23 | * BootstrapTransactionId is the XID for "bootstrap" operations, and |
| 24 | * FrozenTransactionId is used for very old tuples. Both should |
| 25 | * always be considered valid. |
| 26 | * |
| 27 | * FirstNormalTransactionId is the first "normal" transaction id. |
| 28 | * Note: if you need to change it, you must change pg_class.h as well. |
| 29 | * ---------------- |
| 30 | */ |
| 31 | #define InvalidTransactionId ((TransactionId) 0) |
| 32 | #define BootstrapTransactionId ((TransactionId) 1) |
| 33 | #define FrozenTransactionId ((TransactionId) 2) |
| 34 | #define FirstNormalTransactionId ((TransactionId) 3) |
| 35 | #define MaxTransactionId ((TransactionId) 0xFFFFFFFF) |
| 36 | |
| 37 | /* ---------------- |
| 38 | * transaction ID manipulation macros |
| 39 | * ---------------- |
| 40 | */ |
| 41 | #define TransactionIdIsValid(xid) ((xid) != InvalidTransactionId) |
| 42 | #define TransactionIdIsNormal(xid) ((xid) >= FirstNormalTransactionId) |
| 43 | #define TransactionIdEquals(id1, id2) ((id1) == (id2)) |
| 44 | #define TransactionIdStore(xid, dest) (*(dest) = (xid)) |
| 45 | #define StoreInvalidTransactionId(dest) (*(dest) = InvalidTransactionId) |
| 46 | |
| 47 | #define EpochFromFullTransactionId(x) ((uint32) ((x).value >> 32)) |
| 48 | #define XidFromFullTransactionId(x) ((uint32) (x).value) |
| 49 | #define U64FromFullTransactionId(x) ((x).value) |
| 50 | #define FullTransactionIdPrecedes(a, b) ((a).value < (b).value) |
| 51 | #define FullTransactionIdIsValid(x) TransactionIdIsValid(XidFromFullTransactionId(x)) |
| 52 | #define InvalidFullTransactionId FullTransactionIdFromEpochAndXid(0, InvalidTransactionId) |
| 53 | |
| 54 | /* |
| 55 | * A 64 bit value that contains an epoch and a TransactionId. This is |
| 56 | * wrapped in a struct to prevent implicit conversion to/from TransactionId. |
| 57 | * Not all values represent valid normal XIDs. |
| 58 | */ |
| 59 | typedef struct FullTransactionId |
| 60 | { |
| 61 | uint64 value; |
| 62 | } FullTransactionId; |
| 63 | |
| 64 | static inline FullTransactionId |
| 65 | FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid) |
| 66 | { |
| 67 | FullTransactionId result; |
| 68 | |
| 69 | result.value = ((uint64) epoch) << 32 | xid; |
| 70 | |
| 71 | return result; |
| 72 | } |
| 73 | |
| 74 | /* advance a transaction ID variable, handling wraparound correctly */ |
| 75 | #define TransactionIdAdvance(dest) \ |
| 76 | do { \ |
| 77 | (dest)++; \ |
| 78 | if ((dest) < FirstNormalTransactionId) \ |
| 79 | (dest) = FirstNormalTransactionId; \ |
| 80 | } while(0) |
| 81 | |
| 82 | /* advance a FullTransactionId variable, stepping over special XIDs */ |
| 83 | static inline void |
| 84 | FullTransactionIdAdvance(FullTransactionId *dest) |
| 85 | { |
| 86 | dest->value++; |
| 87 | while (XidFromFullTransactionId(*dest) < FirstNormalTransactionId) |
| 88 | dest->value++; |
| 89 | } |
| 90 | |
| 91 | /* back up a transaction ID variable, handling wraparound correctly */ |
| 92 | #define TransactionIdRetreat(dest) \ |
| 93 | do { \ |
| 94 | (dest)--; \ |
| 95 | } while ((dest) < FirstNormalTransactionId) |
| 96 | |
| 97 | /* compare two XIDs already known to be normal; this is a macro for speed */ |
| 98 | #define NormalTransactionIdPrecedes(id1, id2) \ |
| 99 | (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \ |
| 100 | (int32) ((id1) - (id2)) < 0) |
| 101 | |
| 102 | /* compare two XIDs already known to be normal; this is a macro for speed */ |
| 103 | #define NormalTransactionIdFollows(id1, id2) \ |
| 104 | (AssertMacro(TransactionIdIsNormal(id1) && TransactionIdIsNormal(id2)), \ |
| 105 | (int32) ((id1) - (id2)) > 0) |
| 106 | |
| 107 | /* ---------- |
| 108 | * Object ID (OID) zero is InvalidOid. |
| 109 | * |
| 110 | * OIDs 1-9999 are reserved for manual assignment (see .dat files in |
| 111 | * src/include/catalog/). Of these, 8000-9999 are reserved for |
| 112 | * development purposes (such as in-progress patches and forks); |
| 113 | * they should not appear in released versions. |
| 114 | * |
| 115 | * OIDs 10000-11999 are reserved for assignment by genbki.pl, for use |
| 116 | * when the .dat files in src/include/catalog/ do not specify an OID |
| 117 | * for a catalog entry that requires one. |
| 118 | * |
| 119 | * OIDS 12000-16383 are reserved for assignment during initdb |
| 120 | * using the OID generator. (We start the generator at 12000.) |
| 121 | * |
| 122 | * OIDs beginning at 16384 are assigned from the OID generator |
| 123 | * during normal multiuser operation. (We force the generator up to |
| 124 | * 16384 as soon as we are in normal operation.) |
| 125 | * |
| 126 | * The choices of 8000, 10000 and 12000 are completely arbitrary, and can be |
| 127 | * moved if we run low on OIDs in any category. Changing the macros below, |
| 128 | * and updating relevant documentation (see bki.sgml and RELEASE_CHANGES), |
| 129 | * should be sufficient to do this. Moving the 16384 boundary between |
| 130 | * initdb-assigned OIDs and user-defined objects would be substantially |
| 131 | * more painful, however, since some user-defined OIDs will appear in |
| 132 | * on-disk data; such a change would probably break pg_upgrade. |
| 133 | * |
| 134 | * NOTE: if the OID generator wraps around, we skip over OIDs 0-16383 |
| 135 | * and resume with 16384. This minimizes the odds of OID conflict, by not |
| 136 | * reassigning OIDs that might have been assigned during initdb. |
| 137 | * ---------- |
| 138 | */ |
| 139 | #define FirstGenbkiObjectId 10000 |
| 140 | #define FirstBootstrapObjectId 12000 |
| 141 | #define FirstNormalObjectId 16384 |
| 142 | |
| 143 | /* |
| 144 | * VariableCache is a data structure in shared memory that is used to track |
| 145 | * OID and XID assignment state. For largely historical reasons, there is |
| 146 | * just one struct with different fields that are protected by different |
| 147 | * LWLocks. |
| 148 | * |
| 149 | * Note: xidWrapLimit and oldestXidDB are not "active" values, but are |
| 150 | * used just to generate useful messages when xidWarnLimit or xidStopLimit |
| 151 | * are exceeded. |
| 152 | */ |
| 153 | typedef struct VariableCacheData |
| 154 | { |
| 155 | /* |
| 156 | * These fields are protected by OidGenLock. |
| 157 | */ |
| 158 | Oid nextOid; /* next OID to assign */ |
| 159 | uint32 oidCount; /* OIDs available before must do XLOG work */ |
| 160 | |
| 161 | /* |
| 162 | * These fields are protected by XidGenLock. |
| 163 | */ |
| 164 | FullTransactionId nextFullXid; /* next full XID to assign */ |
| 165 | |
| 166 | TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */ |
| 167 | TransactionId xidVacLimit; /* start forcing autovacuums here */ |
| 168 | TransactionId xidWarnLimit; /* start complaining here */ |
| 169 | TransactionId xidStopLimit; /* refuse to advance nextFullXid beyond here */ |
| 170 | TransactionId xidWrapLimit; /* where the world ends */ |
| 171 | Oid oldestXidDB; /* database with minimum datfrozenxid */ |
| 172 | |
| 173 | /* |
| 174 | * These fields are protected by CommitTsLock |
| 175 | */ |
| 176 | TransactionId oldestCommitTsXid; |
| 177 | TransactionId newestCommitTsXid; |
| 178 | |
| 179 | /* |
| 180 | * These fields are protected by ProcArrayLock. |
| 181 | */ |
| 182 | TransactionId latestCompletedXid; /* newest XID that has committed or |
| 183 | * aborted */ |
| 184 | |
| 185 | /* |
| 186 | * These fields are protected by CLogTruncationLock |
| 187 | */ |
| 188 | TransactionId oldestClogXid; /* oldest it's safe to look up in clog */ |
| 189 | |
| 190 | } VariableCacheData; |
| 191 | |
| 192 | typedef VariableCacheData *VariableCache; |
| 193 | |
| 194 | |
| 195 | /* ---------------- |
| 196 | * extern declarations |
| 197 | * ---------------- |
| 198 | */ |
| 199 | |
| 200 | /* in transam/xact.c */ |
| 201 | extern bool TransactionStartedDuringRecovery(void); |
| 202 | |
| 203 | /* in transam/varsup.c */ |
| 204 | extern PGDLLIMPORT VariableCache ShmemVariableCache; |
| 205 | |
| 206 | /* |
| 207 | * prototypes for functions in transam/transam.c |
| 208 | */ |
| 209 | extern bool TransactionIdDidCommit(TransactionId transactionId); |
| 210 | extern bool TransactionIdDidAbort(TransactionId transactionId); |
| 211 | extern bool TransactionIdIsKnownCompleted(TransactionId transactionId); |
| 212 | extern void TransactionIdAbort(TransactionId transactionId); |
| 213 | extern void TransactionIdCommitTree(TransactionId xid, int nxids, TransactionId *xids); |
| 214 | extern void TransactionIdAsyncCommitTree(TransactionId xid, int nxids, TransactionId *xids, XLogRecPtr lsn); |
| 215 | extern void TransactionIdAbortTree(TransactionId xid, int nxids, TransactionId *xids); |
| 216 | extern bool TransactionIdPrecedes(TransactionId id1, TransactionId id2); |
| 217 | extern bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2); |
| 218 | extern bool TransactionIdFollows(TransactionId id1, TransactionId id2); |
| 219 | extern bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2); |
| 220 | extern TransactionId TransactionIdLatest(TransactionId mainxid, |
| 221 | int nxids, const TransactionId *xids); |
| 222 | extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid); |
| 223 | |
| 224 | /* in transam/varsup.c */ |
| 225 | extern FullTransactionId GetNewTransactionId(bool isSubXact); |
| 226 | extern void AdvanceNextFullTransactionIdPastXid(TransactionId xid); |
| 227 | extern FullTransactionId ReadNextFullTransactionId(void); |
| 228 | extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, |
| 229 | Oid oldest_datoid); |
| 230 | extern void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid); |
| 231 | extern bool ForceTransactionIdLimitUpdate(void); |
| 232 | extern Oid GetNewObjectId(void); |
| 233 | |
| 234 | /* |
| 235 | * Some frontend programs include this header. For compilers that emit static |
| 236 | * inline functions even when they're unused, that leads to unsatisfied |
| 237 | * external references; hence hide them with #ifndef FRONTEND. |
| 238 | */ |
| 239 | #ifndef FRONTEND |
| 240 | |
| 241 | /* |
| 242 | * For callers that just need the XID part of the next transaction ID. |
| 243 | */ |
| 244 | static inline TransactionId |
| 245 | ReadNewTransactionId(void) |
| 246 | { |
| 247 | return XidFromFullTransactionId(ReadNextFullTransactionId()); |
| 248 | } |
| 249 | |
| 250 | #endif /* FRONTEND */ |
| 251 | |
| 252 | #endif /* TRANSAM_H */ |
| 253 | |