1 /*-------------------------------------------------------------------------
2  *
3  * xact.h
4  *	  postgres transaction system definitions
5  *
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * src/include/access/xact.h
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef XACT_H
15 #define XACT_H
16 
17 #include "access/xlogreader.h"
18 #include "lib/stringinfo.h"
19 #include "nodes/pg_list.h"
20 #include "storage/relfilenode.h"
21 #include "storage/sinval.h"
22 #include "utils/datetime.h"
23 
24 
25 /*
26  * Xact isolation levels
27  */
28 #define XACT_READ_UNCOMMITTED	0
29 #define XACT_READ_COMMITTED		1
30 #define XACT_REPEATABLE_READ	2
31 #define XACT_SERIALIZABLE		3
32 
33 extern int	DefaultXactIsoLevel;
34 extern PGDLLIMPORT int XactIsoLevel;
35 
36 /*
37  * We implement three isolation levels internally.
38  * The two stronger ones use one snapshot per database transaction;
39  * the others use one snapshot per statement.
40  * Serializable uses predicate locks in addition to snapshots.
41  * These macros should be used to check which isolation level is selected.
42  */
43 #define IsolationUsesXactSnapshot() (XactIsoLevel >= XACT_REPEATABLE_READ)
44 #define IsolationIsSerializable() (XactIsoLevel == XACT_SERIALIZABLE)
45 
46 /* Xact read-only state */
47 extern bool DefaultXactReadOnly;
48 extern bool XactReadOnly;
49 
50 /*
51  * Xact is deferrable -- only meaningful (currently) for read only
52  * SERIALIZABLE transactions
53  */
54 extern bool DefaultXactDeferrable;
55 extern bool XactDeferrable;
56 
57 typedef enum
58 {
59 	SYNCHRONOUS_COMMIT_OFF,		/* asynchronous commit */
60 	SYNCHRONOUS_COMMIT_LOCAL_FLUSH, /* wait for local flush only */
61 	SYNCHRONOUS_COMMIT_REMOTE_WRITE,	/* wait for local flush and remote
62 										 * write */
63 	SYNCHRONOUS_COMMIT_REMOTE_FLUSH,	/* wait for local and remote flush */
64 	SYNCHRONOUS_COMMIT_REMOTE_APPLY /* wait for local and remote flush
65 									   and remote apply */
66 }			SyncCommitLevel;
67 
68 /* Define the default setting for synchronous_commit */
69 #define SYNCHRONOUS_COMMIT_ON	SYNCHRONOUS_COMMIT_REMOTE_FLUSH
70 
71 /* Synchronous commit level */
72 extern int	synchronous_commit;
73 
74 /*
75  * Miscellaneous flag bits to record events which occur on the top level
76  * transaction. These flags are only persisted in MyXactFlags and are intended
77  * so we remember to do certain things later in the transaction. This is
78  * globally accessible, so can be set from anywhere in the code which requires
79  * recording flags.
80  */
81 extern int	MyXactFlags;
82 
83 /*
84  * XACT_FLAGS_ACCESSEDTEMPREL - set when a temporary relation is accessed. We
85  * don't allow PREPARE TRANSACTION in that case.
86  */
87 #define XACT_FLAGS_ACCESSEDTEMPREL				(1U << 0)
88 
89 /*
90  * XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK - records whether the top level xact
91  * logged any Access Exclusive Locks.
92  */
93 #define XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK	(1U << 1)
94 
95 /*
96  * XACT_FLAGS_ACCESSEDTEMPNAMESPACE - set when a temporary namespace is
97  * accessed.  We don't allow PREPARE TRANSACTION in that case.
98  */
99 #define XACT_FLAGS_ACCESSEDTEMPNAMESPACE		(1U << 2)
100 
101 /*
102  *	start- and end-of-transaction callbacks for dynamically loaded modules
103  */
104 typedef enum
105 {
106 	XACT_EVENT_COMMIT,
107 	XACT_EVENT_PARALLEL_COMMIT,
108 	XACT_EVENT_ABORT,
109 	XACT_EVENT_PARALLEL_ABORT,
110 	XACT_EVENT_PREPARE,
111 	XACT_EVENT_PRE_COMMIT,
112 	XACT_EVENT_PARALLEL_PRE_COMMIT,
113 	XACT_EVENT_PRE_PREPARE
114 } XactEvent;
115 
116 typedef void (*XactCallback) (XactEvent event, void *arg);
117 
118 typedef enum
119 {
120 	SUBXACT_EVENT_START_SUB,
121 	SUBXACT_EVENT_COMMIT_SUB,
122 	SUBXACT_EVENT_ABORT_SUB,
123 	SUBXACT_EVENT_PRE_COMMIT_SUB
124 } SubXactEvent;
125 
126 typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
127 								 SubTransactionId parentSubid, void *arg);
128 
129 
130 /* ----------------
131  *		transaction-related XLOG entries
132  * ----------------
133  */
134 
135 /*
136  * XLOG allows to store some information in high 4 bits of log record xl_info
137  * field. We use 3 for the opcode, and one about an optional flag variable.
138  */
139 #define XLOG_XACT_COMMIT			0x00
140 #define XLOG_XACT_PREPARE			0x10
141 #define XLOG_XACT_ABORT				0x20
142 #define XLOG_XACT_COMMIT_PREPARED	0x30
143 #define XLOG_XACT_ABORT_PREPARED	0x40
144 #define XLOG_XACT_ASSIGNMENT		0x50
145 /* free opcode 0x60 */
146 /* free opcode 0x70 */
147 
148 /* mask for filtering opcodes out of xl_info */
149 #define XLOG_XACT_OPMASK			0x70
150 
151 /* does this record have a 'xinfo' field or not */
152 #define XLOG_XACT_HAS_INFO			0x80
153 
154 /*
155  * The following flags, stored in xinfo, determine which information is
156  * contained in commit/abort records.
157  */
158 #define XACT_XINFO_HAS_DBINFO			(1U << 0)
159 #define XACT_XINFO_HAS_SUBXACTS			(1U << 1)
160 #define XACT_XINFO_HAS_RELFILENODES		(1U << 2)
161 #define XACT_XINFO_HAS_INVALS			(1U << 3)
162 #define XACT_XINFO_HAS_TWOPHASE			(1U << 4)
163 #define XACT_XINFO_HAS_ORIGIN			(1U << 5)
164 #define XACT_XINFO_HAS_AE_LOCKS			(1U << 6)
165 
166 /*
167  * Also stored in xinfo, these indicating a variety of additional actions that
168  * need to occur when emulating transaction effects during recovery.
169  *
170  * They are named XactCompletion... to differentiate them from
171  * EOXact... routines which run at the end of the original transaction
172  * completion.
173  */
174 #define XACT_COMPLETION_APPLY_FEEDBACK			(1U << 29)
175 #define XACT_COMPLETION_UPDATE_RELCACHE_FILE	(1U << 30)
176 #define XACT_COMPLETION_FORCE_SYNC_COMMIT		(1U << 31)
177 
178 /* Access macros for above flags */
179 #define XactCompletionApplyFeedback(xinfo) \
180 	((xinfo & XACT_COMPLETION_APPLY_FEEDBACK) != 0)
181 #define XactCompletionRelcacheInitFileInval(xinfo) \
182 	((xinfo & XACT_COMPLETION_UPDATE_RELCACHE_FILE) != 0)
183 #define XactCompletionForceSyncCommit(xinfo) \
184 	((xinfo & XACT_COMPLETION_FORCE_SYNC_COMMIT) != 0)
185 
186 typedef struct xl_xact_assignment
187 {
188 	TransactionId xtop;			/* assigned XID's top-level XID */
189 	int			nsubxacts;		/* number of subtransaction XIDs */
190 	TransactionId xsub[FLEXIBLE_ARRAY_MEMBER];	/* assigned subxids */
191 } xl_xact_assignment;
192 
193 #define MinSizeOfXactAssignment offsetof(xl_xact_assignment, xsub)
194 
195 /*
196  * Commit and abort records can contain a lot of information. But a large
197  * portion of the records won't need all possible pieces of information. So we
198  * only include what's needed.
199  *
200  * A minimal commit/abort record only consists of a xl_xact_commit/abort
201  * struct. The presence of additional information is indicated by bits set in
202  * 'xl_xact_xinfo->xinfo'. The presence of the xinfo field itself is signalled
203  * by a set XLOG_XACT_HAS_INFO bit in the xl_info field.
204  *
205  * NB: All the individual data chunks should be sized to multiples of
206  * sizeof(int) and only require int32 alignment. If they require bigger
207  * alignment, they need to be copied upon reading.
208  */
209 
210 /* sub-records for commit/abort */
211 
212 typedef struct xl_xact_xinfo
213 {
214 	/*
215 	 * Even though we right now only require 1 byte of space in xinfo we use
216 	 * four so following records don't have to care about alignment. Commit
217 	 * records can be large, so copying large portions isn't attractive.
218 	 */
219 	uint32		xinfo;
220 } xl_xact_xinfo;
221 
222 typedef struct xl_xact_dbinfo
223 {
224 	Oid			dbId;			/* MyDatabaseId */
225 	Oid			tsId;			/* MyDatabaseTableSpace */
226 } xl_xact_dbinfo;
227 
228 typedef struct xl_xact_subxacts
229 {
230 	int			nsubxacts;		/* number of subtransaction XIDs */
231 	TransactionId subxacts[FLEXIBLE_ARRAY_MEMBER];
232 } xl_xact_subxacts;
233 #define MinSizeOfXactSubxacts offsetof(xl_xact_subxacts, subxacts)
234 
235 typedef struct xl_xact_relfilenodes
236 {
237 	int			nrels;			/* number of subtransaction XIDs */
238 	RelFileNode xnodes[FLEXIBLE_ARRAY_MEMBER];
239 } xl_xact_relfilenodes;
240 #define MinSizeOfXactRelfilenodes offsetof(xl_xact_relfilenodes, xnodes)
241 
242 typedef struct xl_xact_invals
243 {
244 	int			nmsgs;			/* number of shared inval msgs */
245 	SharedInvalidationMessage msgs[FLEXIBLE_ARRAY_MEMBER];
246 } xl_xact_invals;
247 #define MinSizeOfXactInvals offsetof(xl_xact_invals, msgs)
248 
249 typedef struct xl_xact_twophase
250 {
251 	TransactionId xid;
252 } xl_xact_twophase;
253 
254 typedef struct xl_xact_origin
255 {
256 	XLogRecPtr	origin_lsn;
257 	TimestampTz origin_timestamp;
258 } xl_xact_origin;
259 
260 typedef struct xl_xact_commit
261 {
262 	TimestampTz xact_time;		/* time of commit */
263 
264 	/* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */
265 	/* xl_xact_dbinfo follows if XINFO_HAS_DBINFO */
266 	/* xl_xact_subxacts follows if XINFO_HAS_SUBXACT */
267 	/* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */
268 	/* xl_xact_invals follows if XINFO_HAS_INVALS */
269 	/* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */
270 	/* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */
271 } xl_xact_commit;
272 #define MinSizeOfXactCommit (offsetof(xl_xact_commit, xact_time) + sizeof(TimestampTz))
273 
274 typedef struct xl_xact_abort
275 {
276 	TimestampTz xact_time;		/* time of abort */
277 
278 	/* xl_xact_xinfo follows if XLOG_XACT_HAS_INFO */
279 	/* No db_info required */
280 	/* xl_xact_subxacts follows if HAS_SUBXACT */
281 	/* xl_xact_relfilenodes follows if HAS_RELFILENODES */
282 	/* No invalidation messages needed. */
283 	/* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */
284 } xl_xact_abort;
285 #define MinSizeOfXactAbort sizeof(xl_xact_abort)
286 
287 /*
288  * Commit/Abort records in the above form are a bit verbose to parse, so
289  * there's a deconstructed versions generated by ParseCommit/AbortRecord() for
290  * easier consumption.
291  */
292 typedef struct xl_xact_parsed_commit
293 {
294 	TimestampTz xact_time;
295 
296 	uint32		xinfo;
297 
298 	Oid			dbId;			/* MyDatabaseId */
299 	Oid			tsId;			/* MyDatabaseTableSpace */
300 
301 	int			nsubxacts;
302 	TransactionId *subxacts;
303 
304 	int			nrels;
305 	RelFileNode *xnodes;
306 
307 	int			nmsgs;
308 	SharedInvalidationMessage *msgs;
309 
310 	TransactionId twophase_xid; /* only for 2PC */
311 
312 	XLogRecPtr	origin_lsn;
313 	TimestampTz origin_timestamp;
314 } xl_xact_parsed_commit;
315 
316 typedef struct xl_xact_parsed_abort
317 {
318 	TimestampTz xact_time;
319 	uint32		xinfo;
320 
321 	int			nsubxacts;
322 	TransactionId *subxacts;
323 
324 	int			nrels;
325 	RelFileNode *xnodes;
326 
327 	TransactionId twophase_xid; /* only for 2PC */
328 } xl_xact_parsed_abort;
329 
330 
331 /* ----------------
332  *		extern definitions
333  * ----------------
334  */
335 extern bool IsTransactionState(void);
336 extern bool IsAbortedTransactionBlockState(void);
337 extern TransactionId GetTopTransactionId(void);
338 extern TransactionId GetTopTransactionIdIfAny(void);
339 extern TransactionId GetCurrentTransactionId(void);
340 extern TransactionId GetCurrentTransactionIdIfAny(void);
341 extern TransactionId GetStableLatestTransactionId(void);
342 extern SubTransactionId GetCurrentSubTransactionId(void);
343 extern void MarkCurrentTransactionIdLoggedIfAny(void);
344 extern bool SubTransactionIsActive(SubTransactionId subxid);
345 extern CommandId GetCurrentCommandId(bool used);
346 extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
347 extern TimestampTz GetCurrentTransactionStartTimestamp(void);
348 extern TimestampTz GetCurrentStatementStartTimestamp(void);
349 extern TimestampTz GetCurrentTransactionStopTimestamp(void);
350 extern void SetCurrentStatementStartTimestamp(void);
351 extern int	GetCurrentTransactionNestLevel(void);
352 extern bool TransactionIdIsCurrentTransactionId(TransactionId xid);
353 extern void CommandCounterIncrement(void);
354 extern void ForceSyncCommit(void);
355 extern void StartTransactionCommand(void);
356 extern void CommitTransactionCommand(void);
357 extern void AbortCurrentTransaction(void);
358 extern void BeginTransactionBlock(void);
359 extern bool EndTransactionBlock(void);
360 extern bool PrepareTransactionBlock(char *gid);
361 extern void UserAbortTransactionBlock(void);
362 extern void ReleaseSavepoint(List *options);
363 extern void DefineSavepoint(char *name);
364 extern void RollbackToSavepoint(List *options);
365 extern void BeginInternalSubTransaction(char *name);
366 extern void ReleaseCurrentSubTransaction(void);
367 extern void RollbackAndReleaseCurrentSubTransaction(void);
368 extern bool IsSubTransaction(void);
369 extern Size EstimateTransactionStateSpace(void);
370 extern void SerializeTransactionState(Size maxsize, char *start_address);
371 extern void StartParallelWorkerTransaction(char *tstatespace);
372 extern void EndParallelWorkerTransaction(void);
373 extern bool IsTransactionBlock(void);
374 extern bool IsTransactionOrTransactionBlock(void);
375 extern char TransactionBlockStatusCode(void);
376 extern void AbortOutOfAnyTransaction(void);
377 extern void PreventTransactionChain(bool isTopLevel, const char *stmtType);
378 extern void RequireTransactionChain(bool isTopLevel, const char *stmtType);
379 extern void WarnNoTransactionChain(bool isTopLevel, const char *stmtType);
380 extern bool IsInTransactionChain(bool isTopLevel);
381 extern void RegisterXactCallback(XactCallback callback, void *arg);
382 extern void UnregisterXactCallback(XactCallback callback, void *arg);
383 extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
384 extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
385 
386 extern int	xactGetCommittedChildren(TransactionId **ptr);
387 
388 extern XLogRecPtr XactLogCommitRecord(TimestampTz commit_time,
389 					int nsubxacts, TransactionId *subxacts,
390 					int nrels, RelFileNode *rels,
391 					int nmsgs, SharedInvalidationMessage *msgs,
392 					bool relcacheInval, bool forceSync,
393 					int xactflags,
394 					TransactionId twophase_xid);
395 
396 extern XLogRecPtr XactLogAbortRecord(TimestampTz abort_time,
397 				   int nsubxacts, TransactionId *subxacts,
398 				   int nrels, RelFileNode *rels,
399 				   int xactflags, TransactionId twophase_xid);
400 extern void xact_redo(XLogReaderState *record);
401 
402 /* xactdesc.c */
403 extern void xact_desc(StringInfo buf, XLogReaderState *record);
404 extern const char *xact_identify(uint8 info);
405 
406 /* also in xactdesc.c, so they can be shared between front/backend code */
407 extern void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed);
408 extern void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed);
409 
410 extern void EnterParallelMode(void);
411 extern void ExitParallelMode(void);
412 extern bool IsInParallelMode(void);
413 
414 #endif							/* XACT_H */
415