Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * xlog_internal.h
3 : : *
4 : : * PostgreSQL write-ahead log internal declarations
5 : : *
6 : : * NOTE: this file is intended to contain declarations useful for
7 : : * manipulating the XLOG files directly, but it is not supposed to be
8 : : * needed by rmgr routines (redo support for individual record types).
9 : : * So the XLogRecord typedef and associated stuff appear in xlogrecord.h.
10 : : *
11 : : * Note: This file must be includable in both frontend and backend contexts,
12 : : * to allow stand-alone tools like pg_receivewal to deal with WAL files.
13 : : *
14 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
15 : : * Portions Copyright (c) 1994, Regents of the University of California
16 : : *
17 : : * src/include/access/xlog_internal.h
18 : : */
19 : : #ifndef XLOG_INTERNAL_H
20 : : #define XLOG_INTERNAL_H
21 : :
22 : : #include "access/xlogdefs.h"
23 : : #include "access/xlogreader.h"
24 : : #include "datatype/timestamp.h"
25 : : #include "lib/stringinfo.h"
26 : : #include "pgtime.h"
27 : : #include "storage/block.h"
28 : : #include "storage/relfilelocator.h"
29 : :
30 : :
31 : : /*
32 : : * Each page of XLOG file has a header like this:
33 : : */
34 : : #define XLOG_PAGE_MAGIC 0xD11D /* can be used as WAL version indicator */
35 : :
36 : : typedef struct XLogPageHeaderData
37 : : {
38 : : uint16 xlp_magic; /* magic value for correctness checks */
39 : : uint16 xlp_info; /* flag bits, see below */
40 : : TimeLineID xlp_tli; /* TimeLineID of first record on page */
41 : : XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
42 : :
43 : : /*
44 : : * When there is not enough space on current page for whole record, we
45 : : * continue on the next page. xlp_rem_len is the number of bytes
46 : : * remaining from a previous page; it tracks xl_tot_len in the initial
47 : : * header. Note that the continuation data isn't necessarily aligned.
48 : : */
49 : : uint32 xlp_rem_len; /* total len of remaining data for record */
50 : : } XLogPageHeaderData;
51 : :
52 : : #define SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData))
53 : :
54 : : typedef XLogPageHeaderData *XLogPageHeader;
55 : :
56 : : /*
57 : : * When the XLP_LONG_HEADER flag is set, we store additional fields in the
58 : : * page header. (This is ordinarily done just in the first page of an
59 : : * XLOG file.) The additional fields serve to identify the file accurately.
60 : : */
61 : : typedef struct XLogLongPageHeaderData
62 : : {
63 : : XLogPageHeaderData std; /* standard header fields */
64 : : uint64 xlp_sysid; /* system identifier from pg_control */
65 : : uint32 xlp_seg_size; /* just as a cross-check */
66 : : uint32 xlp_xlog_blcksz; /* just as a cross-check */
67 : : } XLogLongPageHeaderData;
68 : :
69 : : #define SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData))
70 : :
71 : : typedef XLogLongPageHeaderData *XLogLongPageHeader;
72 : :
73 : : /* When record crosses page boundary, set this flag in new page's header */
74 : : #define XLP_FIRST_IS_CONTRECORD 0x0001
75 : : /* This flag indicates a "long" page header */
76 : : #define XLP_LONG_HEADER 0x0002
77 : : /* Replaces a missing contrecord; see CreateOverwriteContrecordRecord */
78 : : #define XLP_FIRST_IS_OVERWRITE_CONTRECORD 0x0004
79 : : /* All defined flag bits in xlp_info (used for validity checking of header) */
80 : : #define XLP_ALL_FLAGS 0x0007
81 : :
82 : : #define XLogPageHeaderSize(hdr) \
83 : : (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
84 : :
85 : : /* wal_segment_size can range from 1MB to 1GB */
86 : : #define WalSegMinSize 1024 * 1024
87 : : #define WalSegMaxSize 1024 * 1024 * 1024
88 : : /* default number of min and max wal segments */
89 : : #define DEFAULT_MIN_WAL_SEGS 5
90 : : #define DEFAULT_MAX_WAL_SEGS 64
91 : :
92 : : /* check that the given size is a valid wal_segment_size */
93 : : #define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
94 : : #define IsValidWalSegSize(size) \
95 : : (IsPowerOf2(size) && \
96 : : ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
97 : :
98 : : #define XLogSegmentsPerXLogId(wal_segsz_bytes) \
99 : : (UINT64CONST(0x100000000) / (wal_segsz_bytes))
100 : :
101 : : #define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
102 : : (dest) = (segno) * (wal_segsz_bytes) + (offset)
103 : :
104 : : #define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
105 : : ((xlogptr) & ((wal_segsz_bytes) - 1))
106 : :
107 : : /*
108 : : * Compute a segment number from an XLogRecPtr.
109 : : *
110 : : * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
111 : : * a boundary byte is taken to be in the previous segment. This is suitable
112 : : * for deciding which segment to write given a pointer to a record end,
113 : : * for example.
114 : : */
115 : : #define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
116 : : logSegNo = (xlrp) / (wal_segsz_bytes)
117 : :
118 : : #define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
119 : : logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
120 : :
121 : : /*
122 : : * Convert values of GUCs measured in megabytes to equiv. segment count.
123 : : * Rounds down.
124 : : */
125 : : #define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
126 : : ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
127 : :
128 : : /*
129 : : * Is an XLogRecPtr within a particular XLOG segment?
130 : : *
131 : : * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
132 : : * a boundary byte is taken to be in the previous segment.
133 : : */
134 : : #define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
135 : : (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
136 : :
137 : : #define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
138 : : ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
139 : :
140 : : /* Check if an XLogRecPtr value is in a plausible range */
141 : : #define XRecOffIsValid(xlrp) \
142 : : ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD)
143 : :
144 : : /*
145 : : * The XLog directory and control file (relative to $PGDATA)
146 : : */
147 : : #define XLOGDIR "pg_wal"
148 : : #define XLOG_CONTROL_FILE "global/pg_control"
149 : :
150 : : /*
151 : : * These macros encapsulate knowledge about the exact layout of XLog file
152 : : * names, timeline history file names, and archive-status file names.
153 : : */
154 : : #define MAXFNAMELEN 64
155 : :
156 : : /* Length of XLog file name */
157 : : #define XLOG_FNAME_LEN 24
158 : :
159 : : /*
160 : : * Generate a WAL segment file name. Do not use this function in a helper
161 : : * function allocating the result generated.
162 : : */
163 : : static inline void
1339 peter@eisentraut.org 164 :CBC 8013 : XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
165 : : {
166 : 8013 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
167 : 8013 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
168 : 8013 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
169 : 8013 : }
170 : :
171 : : static inline void
172 : 2 : XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
173 : : {
174 : 2 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
175 : 2 : }
176 : :
177 : : static inline bool
178 : 45148 : IsXLogFileName(const char *fname)
179 : : {
180 [ + + ]: 80930 : return (strlen(fname) == XLOG_FNAME_LEN && \
181 [ + - ]: 35782 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN);
182 : : }
183 : :
184 : : /*
185 : : * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
186 : : * archive recovery, when we want to archive a WAL segment but it might not
187 : : * be complete yet.
188 : : */
189 : : static inline bool
190 : 8432 : IsPartialXLogFileName(const char *fname)
191 : : {
192 : 8439 : return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
193 [ + + + - ]: 8439 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
194 [ + - ]: 7 : strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
195 : : }
196 : :
197 : : static inline void
198 : 3021 : XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
199 : : {
200 : : uint32 log;
201 : : uint32 seg;
202 : :
203 : 3021 : sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
204 : 3021 : *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
205 : 3021 : }
206 : :
207 : : static inline void
208 : 31148 : XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
209 : : {
210 : 31148 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
211 : 31148 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
212 : 31148 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
213 : 31148 : }
214 : :
215 : : static inline void
216 : 508 : TLHistoryFileName(char *fname, TimeLineID tli)
217 : : {
218 : 508 : snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
219 : 508 : }
220 : :
221 : : static inline bool
222 : 8301 : IsTLHistoryFileName(const char *fname)
223 : : {
224 : 8316 : return (strlen(fname) == 8 + strlen(".history") &&
225 [ + + + - ]: 8316 : strspn(fname, "0123456789ABCDEF") == 8 &&
226 [ + - ]: 15 : strcmp(fname + 8, ".history") == 0);
227 : : }
228 : :
229 : : static inline void
230 : 196 : TLHistoryFilePath(char *path, TimeLineID tli)
231 : : {
232 : 196 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
233 : 196 : }
234 : :
235 : : static inline void
236 : 61958 : StatusFilePath(char *path, const char *xlog, const char *suffix)
237 : : {
238 : 61958 : snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
239 : 61958 : }
240 : :
241 : : static inline void
242 : 4 : BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
243 : : {
244 : 4 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
245 : 4 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
246 : 4 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
247 : 4 : (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
248 : 4 : }
249 : :
250 : : static inline bool
251 : 1348 : IsBackupHistoryFileName(const char *fname)
252 : : {
253 : 1522 : return (strlen(fname) > XLOG_FNAME_LEN &&
254 [ + + + - ]: 1522 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
255 [ + + ]: 174 : strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
256 : : }
257 : :
258 : : static inline void
259 : 163 : BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
260 : : {
261 : 163 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
262 : 163 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
263 : 163 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
264 : 163 : (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
265 : 163 : }
266 : :
267 : : /*
268 : : * Information logged when we detect a change in one of the parameters
269 : : * important for Hot Standby.
270 : : */
271 : : typedef struct xl_parameter_change
272 : : {
273 : : int MaxConnections;
274 : : int max_worker_processes;
275 : : int max_wal_senders;
276 : : int max_prepared_xacts;
277 : : int max_locks_per_xact;
278 : : int wal_level;
279 : : bool wal_log_hints;
280 : : bool track_commit_timestamp;
281 : : } xl_parameter_change;
282 : :
283 : : /* logs restore point */
284 : : typedef struct xl_restore_point
285 : : {
286 : : TimestampTz rp_time;
287 : : char rp_name[MAXFNAMELEN];
288 : : } xl_restore_point;
289 : :
290 : : /* Overwrite of prior contrecord */
291 : : typedef struct xl_overwrite_contrecord
292 : : {
293 : : XLogRecPtr overwritten_lsn;
294 : : TimestampTz overwrite_time;
295 : : } xl_overwrite_contrecord;
296 : :
297 : : /* End of recovery mark, when we don't do an END_OF_RECOVERY checkpoint */
298 : : typedef struct xl_end_of_recovery
299 : : {
300 : : TimestampTz end_time;
301 : : TimeLineID ThisTimeLineID; /* new TLI */
302 : : TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
303 : : int wal_level;
304 : : } xl_end_of_recovery;
305 : :
306 : : /*
307 : : * The functions in xloginsert.c construct a chain of XLogRecData structs
308 : : * to represent the final WAL record.
309 : : */
310 : : typedef struct XLogRecData
311 : : {
312 : : struct XLogRecData *next; /* next struct in chain, or NULL */
313 : : const void *data; /* start of rmgr data to include */
314 : : uint32 len; /* length of rmgr data to include */
315 : : } XLogRecData;
316 : :
317 : : struct LogicalDecodingContext;
318 : : struct XLogRecordBuffer;
319 : :
320 : : /*
321 : : * Method table for resource managers.
322 : : *
323 : : * This struct must be kept in sync with the PG_RMGR definition in
324 : : * rmgr.c.
325 : : *
326 : : * rm_identify must return a name for the record based on xl_info (without
327 : : * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
328 : : * "VACUUM". rm_desc can then be called to obtain additional detail for the
329 : : * record, if available (e.g. the last block).
330 : : *
331 : : * rm_mask takes as input a page modified by the resource manager and masks
332 : : * out bits that shouldn't be flagged by wal_consistency_checking.
333 : : *
334 : : * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is
335 : : * NULL, the corresponding RmgrTable entry is considered invalid.
336 : : */
337 : : typedef struct RmgrData
338 : : {
339 : : const char *rm_name;
340 : : void (*rm_redo) (XLogReaderState *record);
341 : : void (*rm_desc) (StringInfo buf, XLogReaderState *record);
342 : : const char *(*rm_identify) (uint8 info);
343 : : void (*rm_startup) (void);
344 : : void (*rm_cleanup) (void);
345 : : void (*rm_mask) (char *pagedata, BlockNumber blkno);
346 : : void (*rm_decode) (struct LogicalDecodingContext *ctx,
347 : : struct XLogRecordBuffer *buf);
348 : : } RmgrData;
349 : :
350 : : extern PGDLLIMPORT RmgrData RmgrTable[];
351 : : extern void RmgrStartup(void);
352 : : extern void RmgrCleanup(void);
353 : : extern void RmgrNotFound(RmgrId rmid);
354 : : extern void RegisterCustomRmgr(RmgrId rmid, const RmgrData *rmgr);
355 : :
356 : : #ifndef FRONTEND
357 : : static inline bool
1439 jdavis@postgresql.or 358 : 7621778 : RmgrIdExists(RmgrId rmid)
359 : : {
360 : 7621778 : return RmgrTable[rmid].rm_name != NULL;
361 : : }
362 : :
363 : : static inline RmgrData
364 : 7400364 : GetRmgr(RmgrId rmid)
365 : : {
366 [ - + ]: 7400364 : if (unlikely(!RmgrIdExists(rmid)))
1439 jdavis@postgresql.or 367 :UBC 0 : RmgrNotFound(rmid);
1439 jdavis@postgresql.or 368 :CBC 7400364 : return RmgrTable[rmid];
369 : : }
370 : : #endif
371 : :
372 : : /*
373 : : * Exported to support xlog switching from checkpointer
374 : : */
375 : : extern pg_time_t GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN);
376 : : extern XLogRecPtr RequestXLogSwitch(bool mark_unimportant);
377 : :
378 : : extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
379 : :
380 : : extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
381 : : bool detailed_format, StringInfo buf,
382 : : uint32 *fpi_len);
383 : :
384 : : /*
385 : : * Exported for the functions in timeline.c and xlogarchive.c. Only valid
386 : : * in the startup process.
387 : : */
388 : : extern PGDLLIMPORT bool ArchiveRecoveryRequested;
389 : : extern PGDLLIMPORT bool InArchiveRecovery;
390 : : extern PGDLLIMPORT bool StandbyMode;
391 : : extern PGDLLIMPORT char *recoveryRestoreCommand;
392 : :
393 : : #endif /* XLOG_INTERNAL_H */
|