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-2024, 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 0xD118 /* 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 : /* This flag indicates backup blocks starting in this page are optional */
78 : #define XLP_BKP_REMOVABLE 0x0004
79 : /* Replaces a missing contrecord; see CreateOverwriteContrecordRecord */
80 : #define XLP_FIRST_IS_OVERWRITE_CONTRECORD 0x0008
81 : /* All defined flag bits in xlp_info (used for validity checking of header) */
82 : #define XLP_ALL_FLAGS 0x000F
83 :
84 : #define XLogPageHeaderSize(hdr) \
85 : (((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
86 :
87 : /* wal_segment_size can range from 1MB to 1GB */
88 : #define WalSegMinSize 1024 * 1024
89 : #define WalSegMaxSize 1024 * 1024 * 1024
90 : /* default number of min and max wal segments */
91 : #define DEFAULT_MIN_WAL_SEGS 5
92 : #define DEFAULT_MAX_WAL_SEGS 64
93 :
94 : /* check that the given size is a valid wal_segment_size */
95 : #define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
96 : #define IsValidWalSegSize(size) \
97 : (IsPowerOf2(size) && \
98 : ((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
99 :
100 : #define XLogSegmentsPerXLogId(wal_segsz_bytes) \
101 : (UINT64CONST(0x100000000) / (wal_segsz_bytes))
102 :
103 : #define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest) \
104 : (dest) = (segno) * (wal_segsz_bytes) + (offset)
105 :
106 : #define XLogSegmentOffset(xlogptr, wal_segsz_bytes) \
107 : ((xlogptr) & ((wal_segsz_bytes) - 1))
108 :
109 : /*
110 : * Compute a segment number from an XLogRecPtr.
111 : *
112 : * For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
113 : * a boundary byte is taken to be in the previous segment. This is suitable
114 : * for deciding which segment to write given a pointer to a record end,
115 : * for example.
116 : */
117 : #define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes) \
118 : logSegNo = (xlrp) / (wal_segsz_bytes)
119 :
120 : #define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
121 : logSegNo = ((xlrp) - 1) / (wal_segsz_bytes)
122 :
123 : /*
124 : * Convert values of GUCs measured in megabytes to equiv. segment count.
125 : * Rounds down.
126 : */
127 : #define XLogMBVarToSegs(mbvar, wal_segsz_bytes) \
128 : ((mbvar) / ((wal_segsz_bytes) / (1024 * 1024)))
129 :
130 : /*
131 : * Is an XLogRecPtr within a particular XLOG segment?
132 : *
133 : * For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
134 : * a boundary byte is taken to be in the previous segment.
135 : */
136 : #define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes) \
137 : (((xlrp) / (wal_segsz_bytes)) == (logSegNo))
138 :
139 : #define XLByteInPrevSeg(xlrp, logSegNo, wal_segsz_bytes) \
140 : ((((xlrp) - 1) / (wal_segsz_bytes)) == (logSegNo))
141 :
142 : /* Check if an XLogRecPtr value is in a plausible range */
143 : #define XRecOffIsValid(xlrp) \
144 : ((xlrp) % XLOG_BLCKSZ >= SizeOfXLogShortPHD)
145 :
146 : /*
147 : * The XLog directory and control file (relative to $PGDATA)
148 : */
149 : #define XLOGDIR "pg_wal"
150 : #define XLOG_CONTROL_FILE "global/pg_control"
151 :
152 : /*
153 : * These macros encapsulate knowledge about the exact layout of XLog file
154 : * names, timeline history file names, and archive-status file names.
155 : */
156 : #define MAXFNAMELEN 64
157 :
158 : /* Length of XLog file name */
159 : #define XLOG_FNAME_LEN 24
160 :
161 : /*
162 : * Generate a WAL segment file name. Do not use this function in a helper
163 : * function allocating the result generated.
164 : */
165 : static inline void
166 12098 : XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
167 : {
168 12098 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
169 12098 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
170 12098 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
171 12098 : }
172 :
173 : static inline void
174 4 : XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
175 : {
176 4 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
177 4 : }
178 :
179 : static inline bool
180 47760 : IsXLogFileName(const char *fname)
181 : {
182 82754 : return (strlen(fname) == XLOG_FNAME_LEN && \
183 34994 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN);
184 : }
185 :
186 : /*
187 : * XLOG segment with .partial suffix. Used by pg_receivewal and at end of
188 : * archive recovery, when we want to archive a WAL segment but it might not
189 : * be complete yet.
190 : */
191 : static inline bool
192 11036 : IsPartialXLogFileName(const char *fname)
193 : {
194 11050 : return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
195 11050 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
196 14 : strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
197 : }
198 :
199 : static inline void
200 4390 : XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
201 : {
202 : uint32 log;
203 : uint32 seg;
204 :
205 4390 : sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
206 4390 : *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
207 4390 : }
208 :
209 : static inline void
210 42160 : XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
211 : {
212 42160 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
213 42160 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
214 42160 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
215 42160 : }
216 :
217 : static inline void
218 850 : TLHistoryFileName(char *fname, TimeLineID tli)
219 : {
220 850 : snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
221 850 : }
222 :
223 : static inline bool
224 396 : IsTLHistoryFileName(const char *fname)
225 : {
226 422 : return (strlen(fname) == 8 + strlen(".history") &&
227 422 : strspn(fname, "0123456789ABCDEF") == 8 &&
228 26 : strcmp(fname + 8, ".history") == 0);
229 : }
230 :
231 : static inline void
232 384 : TLHistoryFilePath(char *path, TimeLineID tli)
233 : {
234 384 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
235 384 : }
236 :
237 : static inline void
238 12048 : StatusFilePath(char *path, const char *xlog, const char *suffix)
239 : {
240 12048 : snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
241 12048 : }
242 :
243 : static inline void
244 6 : BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
245 : {
246 6 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
247 6 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
248 6 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
249 6 : (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
250 6 : }
251 :
252 : static inline bool
253 2342 : IsBackupHistoryFileName(const char *fname)
254 : {
255 2656 : return (strlen(fname) > XLOG_FNAME_LEN &&
256 2656 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
257 314 : strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
258 : }
259 :
260 : static inline void
261 290 : BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
262 : {
263 290 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
264 290 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
265 290 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
266 290 : (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
267 290 : }
268 :
269 : /*
270 : * Information logged when we detect a change in one of the parameters
271 : * important for Hot Standby.
272 : */
273 : typedef struct xl_parameter_change
274 : {
275 : int MaxConnections;
276 : int max_worker_processes;
277 : int max_wal_senders;
278 : int max_prepared_xacts;
279 : int max_locks_per_xact;
280 : int wal_level;
281 : bool wal_log_hints;
282 : bool track_commit_timestamp;
283 : } xl_parameter_change;
284 :
285 : /* logs restore point */
286 : typedef struct xl_restore_point
287 : {
288 : TimestampTz rp_time;
289 : char rp_name[MAXFNAMELEN];
290 : } xl_restore_point;
291 :
292 : /* Overwrite of prior contrecord */
293 : typedef struct xl_overwrite_contrecord
294 : {
295 : XLogRecPtr overwritten_lsn;
296 : TimestampTz overwrite_time;
297 : } xl_overwrite_contrecord;
298 :
299 : /* End of recovery mark, when we don't do an END_OF_RECOVERY checkpoint */
300 : typedef struct xl_end_of_recovery
301 : {
302 : TimestampTz end_time;
303 : TimeLineID ThisTimeLineID; /* new TLI */
304 : TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
305 : int wal_level;
306 : } xl_end_of_recovery;
307 :
308 : /*
309 : * The functions in xloginsert.c construct a chain of XLogRecData structs
310 : * to represent the final WAL record.
311 : */
312 : typedef struct XLogRecData
313 : {
314 : struct XLogRecData *next; /* next struct in chain, or NULL */
315 : const char *data; /* start of rmgr data to include */
316 : uint32 len; /* length of rmgr data to include */
317 : } XLogRecData;
318 :
319 : /*
320 : * Recovery target action.
321 : */
322 : typedef enum
323 : {
324 : RECOVERY_TARGET_ACTION_PAUSE,
325 : RECOVERY_TARGET_ACTION_PROMOTE,
326 : RECOVERY_TARGET_ACTION_SHUTDOWN,
327 : } RecoveryTargetAction;
328 :
329 : struct LogicalDecodingContext;
330 : struct XLogRecordBuffer;
331 :
332 : /*
333 : * Method table for resource managers.
334 : *
335 : * This struct must be kept in sync with the PG_RMGR definition in
336 : * rmgr.c.
337 : *
338 : * rm_identify must return a name for the record based on xl_info (without
339 : * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
340 : * "VACUUM". rm_desc can then be called to obtain additional detail for the
341 : * record, if available (e.g. the last block).
342 : *
343 : * rm_mask takes as input a page modified by the resource manager and masks
344 : * out bits that shouldn't be flagged by wal_consistency_checking.
345 : *
346 : * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is
347 : * NULL, the corresponding RmgrTable entry is considered invalid.
348 : */
349 : typedef struct RmgrData
350 : {
351 : const char *rm_name;
352 : void (*rm_redo) (XLogReaderState *record);
353 : void (*rm_desc) (StringInfo buf, XLogReaderState *record);
354 : const char *(*rm_identify) (uint8 info);
355 : void (*rm_startup) (void);
356 : void (*rm_cleanup) (void);
357 : void (*rm_mask) (char *pagedata, BlockNumber blkno);
358 : void (*rm_decode) (struct LogicalDecodingContext *ctx,
359 : struct XLogRecordBuffer *buf);
360 : } RmgrData;
361 :
362 : extern PGDLLIMPORT RmgrData RmgrTable[];
363 : extern void RmgrStartup(void);
364 : extern void RmgrCleanup(void);
365 : extern void RmgrNotFound(RmgrId rmid);
366 : extern void RegisterCustomRmgr(RmgrId rmid, const RmgrData *rmgr);
367 :
368 : #ifndef FRONTEND
369 : static inline bool
370 14753202 : RmgrIdExists(RmgrId rmid)
371 : {
372 14753202 : return RmgrTable[rmid].rm_name != NULL;
373 : }
374 :
375 : static inline RmgrData
376 14349286 : GetRmgr(RmgrId rmid)
377 : {
378 14349286 : if (unlikely(!RmgrIdExists(rmid)))
379 0 : RmgrNotFound(rmid);
380 14349286 : return RmgrTable[rmid];
381 : }
382 : #endif
383 :
384 : /*
385 : * Exported to support xlog switching from checkpointer
386 : */
387 : extern pg_time_t GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN);
388 : extern XLogRecPtr RequestXLogSwitch(bool mark_unimportant);
389 :
390 : extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
391 :
392 : extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
393 : bool detailed_format, StringInfo buf,
394 : uint32 *fpi_len);
395 :
396 : /*
397 : * Exported for the functions in timeline.c and xlogarchive.c. Only valid
398 : * in the startup process.
399 : */
400 : extern PGDLLIMPORT bool ArchiveRecoveryRequested;
401 : extern PGDLLIMPORT bool InArchiveRecovery;
402 : extern PGDLLIMPORT bool StandbyMode;
403 : extern PGDLLIMPORT char *recoveryRestoreCommand;
404 :
405 : #endif /* XLOG_INTERNAL_H */
|