3 * PostgreSQL logical replay/reorder buffer management.
5 * Copyright (c) 2012-2014, PostgreSQL Global Development Group
7 * src/include/replication/reorderbuffer.h
9 #ifndef REORDERBUFFER_H
10 #define REORDERBUFFER_H
12 #include "access/htup_details.h"
14 #include "lib/ilist.h"
16 #include "storage/sinval.h"
18 #include "utils/hsearch.h"
19 #include "utils/rel.h"
20 #include "utils/snapshot.h"
21 #include "utils/timestamp.h"
23 /* an individual tuple, stored in one chunk of memory */
24 typedef struct ReorderBufferTupleBuf
26 /* position in preallocated list */
29 /* tuple, stored sequentially */
31 HeapTupleHeaderData header;
32 char data[MaxHeapTupleSize];
33 } ReorderBufferTupleBuf;
36 * Types of the change passed to a 'change' callback.
38 * For efficiency and simplicity reasons we want to keep Snapshots, CommandIds
39 * and ComboCids in the same list with the user visible INSERT/UPDATE/DELETE
40 * changes. Users of the decoding facilities will never see changes with
41 * *_INTERNAL_* actions.
43 enum ReorderBufferChangeType
45 REORDER_BUFFER_CHANGE_INSERT,
46 REORDER_BUFFER_CHANGE_UPDATE,
47 REORDER_BUFFER_CHANGE_DELETE,
48 REORDER_BUFFER_CHANGE_INTERNAL_SNAPSHOT,
49 REORDER_BUFFER_CHANGE_INTERNAL_COMMAND_ID,
50 REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID
54 * a single 'change', can be an insert (with one tuple), an update (old, new),
57 * The same struct is also used internally for other purposes but that should
58 * never be visible outside reorderbuffer.c.
60 typedef struct ReorderBufferChange
64 /* The type of change. */
65 enum ReorderBufferChangeType action;
68 * Context data for the change, which part of the union is valid depends
69 * on action/action_internal.
73 /* Old, new tuples when action == *_INSERT|UPDATE|DELETE */
76 /* relation that has been changed */
79 /* no previously reassembled toast chunks are necessary anymore */
80 bool clear_toast_afterwards;
82 /* valid for DELETE || UPDATE */
83 ReorderBufferTupleBuf *oldtuple;
84 /* valid for INSERT || UPDATE */
85 ReorderBufferTupleBuf *newtuple;
88 /* New snapshot, set when action == *_INTERNAL_SNAPSHOT */
92 * New command id for existing snapshot in a catalog changing tx. Set
93 * when action == *_INTERNAL_COMMAND_ID.
98 * New cid mapping for catalog changing transaction, set when action
99 * == *_INTERNAL_TUPLECID.
112 * While in use this is how a change is linked into a transactions,
113 * otherwise it's the preallocated list.
116 } ReorderBufferChange;
118 typedef struct ReorderBufferTXN
121 * The transactions transaction id, can be a toplevel or sub xid.
125 /* did the TX have catalog changes */
126 bool has_catalog_changes;
129 * Do we know this is a subxact?
131 bool is_known_as_subxact;
134 * LSN of the first data carrying, WAL record with knowledge about this
135 * xid. This is allowed to *not* be first record adorned with this xid, if
136 * the previous records aren't relevant for logical decoding.
138 XLogRecPtr first_lsn;
141 * LSN of the record that lead to this xact to be committed or
142 * aborted. This can be a
143 * * plain commit record
144 * * plain commit record, of a parent transaction
145 * * prepared transaction commit
146 * * plain abort record
147 * * prepared transaction abort
148 * * error during decoding
151 XLogRecPtr final_lsn;
154 * LSN pointing to the end of the commit record + 1.
159 * LSN of the last lsn at which snapshot information reside, so we can
160 * restart decoding from there and fully recover this transaction from
163 XLogRecPtr restart_decoding_lsn;
166 * Commit time, only known when we read the actual commit record.
168 TimestampTz commit_time;
171 * Base snapshot or NULL.
173 Snapshot base_snapshot;
174 XLogRecPtr base_snapshot_lsn;
177 * How many ReorderBufferChange's do we have in this txn.
179 * Changes in subtransactions are *not* included but tracked separately.
184 * How many of the above entries are stored in memory in contrast to being
190 * List of ReorderBufferChange structs, including new Snapshots and new
196 * List of (relation, ctid) => (cmin, cmax) mappings for catalog tuples.
197 * Those are always assigned to the toplevel transaction. (Keep track of
198 * #entries to create a hash of the right size)
200 dlist_head tuplecids;
204 * On-demand built hash for looking up the above values.
209 * Hash containing (potentially partial) toast entries. NULL if no toast
210 * tuples have been found for the current change.
215 * non-hierarchical list of subtransactions that are *not* aborted. Only
216 * used in toplevel transactions.
222 * Stored cache invalidations. This is not a linked list because we get
223 * all the invalidations at once.
225 uint32 ninvalidations;
226 SharedInvalidationMessage *invalidations;
229 * Position in one of three lists:
230 * * list of subtransactions if we are *known* to be subxact
231 * * list of toplevel xacts (can be a as-yet unknown subxact)
232 * * list of preallocated ReorderBufferTXNs
239 /* so we can define the callbacks used inside struct ReorderBuffer itself */
240 typedef struct ReorderBuffer ReorderBuffer;
242 /* change callback signature */
243 typedef void (*ReorderBufferApplyChangeCB) (
245 ReorderBufferTXN *txn,
247 ReorderBufferChange *change);
249 /* begin callback signature */
250 typedef void (*ReorderBufferBeginCB) (
252 ReorderBufferTXN *txn);
254 /* commit callback signature */
255 typedef void (*ReorderBufferCommitCB) (
257 ReorderBufferTXN *txn,
258 XLogRecPtr commit_lsn);
263 * xid => ReorderBufferTXN lookup table
268 * Transactions that could be a toplevel xact, ordered by LSN of the first
269 * record bearing that xid..
271 dlist_head toplevel_by_lsn;
274 * one-entry sized cache for by_txn. Very frequently the same txn gets
275 * looked up over and over again.
277 TransactionId by_txn_last_xid;
278 ReorderBufferTXN *by_txn_last_txn;
281 * Callacks to be called when a transactions commits.
283 ReorderBufferBeginCB begin;
284 ReorderBufferApplyChangeCB apply_change;
285 ReorderBufferCommitCB commit;
288 * Pointer that will be passed untouched to the callbacks.
293 * Private memory context.
295 MemoryContext context;
298 * Data structure slab cache.
300 * We allocate/deallocate some structures very frequently, to avoid bigger
301 * overhead we cache some unused ones here.
303 * The maximum number of cached entries is controlled by const variables
304 * ontop of reorderbuffer.c
307 /* cached ReorderBufferTXNs */
308 dlist_head cached_transactions;
309 Size nr_cached_transactions;
311 /* cached ReorderBufferChanges */
312 dlist_head cached_changes;
313 Size nr_cached_changes;
315 /* cached ReorderBufferTupleBufs */
316 slist_head cached_tuplebufs;
317 Size nr_cached_tuplebufs;
319 XLogRecPtr current_restart_decoding_lsn;
321 /* buffer for disk<->memory conversions */
327 ReorderBuffer *ReorderBufferAllocate(void);
328 void ReorderBufferFree(ReorderBuffer *);
330 ReorderBufferTupleBuf *ReorderBufferGetTupleBuf(ReorderBuffer *);
331 void ReorderBufferReturnTupleBuf(ReorderBuffer *, ReorderBufferTupleBuf *tuple);
332 ReorderBufferChange *ReorderBufferGetChange(ReorderBuffer *);
333 void ReorderBufferReturnChange(ReorderBuffer *, ReorderBufferChange *);
335 void ReorderBufferQueueChange(ReorderBuffer *, TransactionId, XLogRecPtr lsn, ReorderBufferChange *);
336 void ReorderBufferCommit(ReorderBuffer *, TransactionId,
337 XLogRecPtr commit_lsn, XLogRecPtr end_lsn,
338 TimestampTz commit_time);
339 void ReorderBufferAssignChild(ReorderBuffer *, TransactionId, TransactionId, XLogRecPtr commit_lsn);
340 void ReorderBufferCommitChild(ReorderBuffer *, TransactionId, TransactionId,
341 XLogRecPtr commit_lsn, XLogRecPtr end_lsn);
342 void ReorderBufferAbort(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
343 void ReorderBufferAbortOld(ReorderBuffer *, TransactionId xid);
344 void ReorderBufferForget(ReorderBuffer *, TransactionId, XLogRecPtr lsn);
346 void ReorderBufferSetBaseSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
347 void ReorderBufferAddSnapshot(ReorderBuffer *, TransactionId, XLogRecPtr lsn, struct SnapshotData *snap);
348 void ReorderBufferAddNewCommandId(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
350 void ReorderBufferAddNewTupleCids(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
351 RelFileNode node, ItemPointerData pt,
352 CommandId cmin, CommandId cmax, CommandId combocid);
353 void ReorderBufferAddInvalidations(ReorderBuffer *, TransactionId, XLogRecPtr lsn,
354 Size nmsgs, SharedInvalidationMessage *msgs);
355 bool ReorderBufferIsXidKnown(ReorderBuffer *, TransactionId xid);
356 void ReorderBufferXidSetCatalogChanges(ReorderBuffer *, TransactionId xid, XLogRecPtr lsn);
357 bool ReorderBufferXidHasCatalogChanges(ReorderBuffer *, TransactionId xid);
358 bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *, TransactionId xid);
360 ReorderBufferTXN *ReorderBufferGetOldestTXN(ReorderBuffer *);
362 void ReorderBufferSetRestartPoint(ReorderBuffer *, XLogRecPtr ptr);
364 void StartupReorderBuffer(void);