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 0xD11C /* 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
164 8078 : XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
165 : {
166 8078 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
167 8078 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
168 8078 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
169 8078 : }
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 54057 : IsXLogFileName(const char *fname)
179 : {
180 98639 : return (strlen(fname) == XLOG_FNAME_LEN && \
181 44582 : 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 8474 : IsPartialXLogFileName(const char *fname)
191 : {
192 8481 : return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
193 8481 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
194 7 : strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
195 : }
196 :
197 : static inline void
198 2962 : XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
199 : {
200 : uint32 log;
201 : uint32 seg;
202 :
203 2962 : sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
204 2962 : *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
205 2962 : }
206 :
207 : static inline void
208 27128 : XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
209 : {
210 27128 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
211 27128 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
212 27128 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
213 27128 : }
214 :
215 : static inline void
216 511 : TLHistoryFileName(char *fname, TimeLineID tli)
217 : {
218 511 : snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
219 511 : }
220 :
221 : static inline bool
222 10445 : IsTLHistoryFileName(const char *fname)
223 : {
224 10459 : return (strlen(fname) == 8 + strlen(".history") &&
225 10459 : strspn(fname, "0123456789ABCDEF") == 8 &&
226 14 : strcmp(fname + 8, ".history") == 0);
227 : }
228 :
229 : static inline void
230 201 : TLHistoryFilePath(char *path, TimeLineID tli)
231 : {
232 201 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
233 201 : }
234 :
235 : static inline void
236 79065 : StatusFilePath(char *path, const char *xlog, const char *suffix)
237 : {
238 79065 : snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
239 79065 : }
240 :
241 : static inline void
242 5 : BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
243 : {
244 5 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
245 5 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
246 5 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
247 5 : (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
248 5 : }
249 :
250 : static inline bool
251 1331 : IsBackupHistoryFileName(const char *fname)
252 : {
253 1503 : return (strlen(fname) > XLOG_FNAME_LEN &&
254 1503 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
255 172 : strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
256 : }
257 :
258 : static inline void
259 159 : BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
260 : {
261 159 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
262 159 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
263 159 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
264 159 : (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
265 159 : }
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
358 7481021 : RmgrIdExists(RmgrId rmid)
359 : {
360 7481021 : return RmgrTable[rmid].rm_name != NULL;
361 : }
362 :
363 : static inline RmgrData
364 7259607 : GetRmgr(RmgrId rmid)
365 : {
366 7259607 : if (unlikely(!RmgrIdExists(rmid)))
367 0 : RmgrNotFound(rmid);
368 7259607 : 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 */
|