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 | |