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-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 0xD115 /* 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
639 peter@eisentraut.org 166 :CBC 4864 : XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
167 : : {
168 : 4864 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli,
169 : 4864 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
170 : 4864 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
171 : 4864 : }
172 : :
173 : : static inline void
174 : 2 : XLogFileNameById(char *fname, TimeLineID tli, uint32 log, uint32 seg)
175 : : {
176 : 2 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg);
177 : 2 : }
178 : :
179 : : static inline bool
180 : 10864 : IsXLogFileName(const char *fname)
181 : : {
182 [ + + ]: 15472 : return (strlen(fname) == XLOG_FNAME_LEN && \
183 [ + - ]: 4608 : 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 : 5071 : IsPartialXLogFileName(const char *fname)
193 : : {
194 : 4758 : return (strlen(fname) == XLOG_FNAME_LEN + strlen(".partial") &&
195 [ + + + - ]: 5080 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
196 [ + - ]: 9 : strcmp(fname + XLOG_FNAME_LEN, ".partial") == 0);
197 : : }
198 : :
199 : : static inline void
200 : 1175 : XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
201 : : {
202 : : uint32 log;
203 : : uint32 seg;
204 : :
205 : 1175 : sscanf(fname, "%08X%08X%08X", tli, &log, &seg);
206 : 1175 : *logSegNo = (uint64) log * XLogSegmentsPerXLogId(wal_segsz_bytes) + seg;
207 : 1175 : }
208 : :
209 : : static inline void
210 : 22728 : XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
211 : : {
212 : 22728 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli,
213 : 22728 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
214 : 22728 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)));
215 : 22728 : }
216 : :
217 : : static inline void
218 : 660 : TLHistoryFileName(char *fname, TimeLineID tli)
219 : : {
220 : 660 : snprintf(fname, MAXFNAMELEN, "%08X.history", tli);
221 : 660 : }
222 : :
223 : : static inline bool
224 : 222 : IsTLHistoryFileName(const char *fname)
225 : : {
226 : 133 : return (strlen(fname) == 8 + strlen(".history") &&
227 [ + + + - ]: 236 : strspn(fname, "0123456789ABCDEF") == 8 &&
228 [ + - ]: 14 : strcmp(fname + 8, ".history") == 0);
229 : : }
230 : :
231 : : static inline void
232 : 193 : TLHistoryFilePath(char *path, TimeLineID tli)
233 : : {
234 : 193 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli);
235 : 193 : }
236 : :
237 : : static inline void
238 : 2665 : StatusFilePath(char *path, const char *xlog, const char *suffix)
239 : : {
240 : 2665 : snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix);
241 : 2665 : }
242 : :
243 : : static inline void
244 : 2 : BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
245 : : {
246 : 2 : snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli,
247 : 2 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
248 : 2 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
249 : 2 : (uint32) (XLogSegmentOffset(startpoint, wal_segsz_bytes)));
250 : 2 : }
251 : :
252 : : static inline bool
253 : 1113 : IsBackupHistoryFileName(const char *fname)
254 : : {
255 : 1259 : return (strlen(fname) > XLOG_FNAME_LEN &&
256 [ + + + - ]: 1259 : strspn(fname, "0123456789ABCDEF") == XLOG_FNAME_LEN &&
257 [ + - ]: 146 : strcmp(fname + strlen(fname) - strlen(".backup"), ".backup") == 0);
258 : : }
259 : :
260 : : static inline void
261 : 138 : BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
262 : : {
263 : 138 : snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli,
264 : 138 : (uint32) (logSegNo / XLogSegmentsPerXLogId(wal_segsz_bytes)),
265 : 138 : (uint32) (logSegNo % XLogSegmentsPerXLogId(wal_segsz_bytes)),
266 : 138 : (uint32) (XLogSegmentOffset((startpoint), wal_segsz_bytes)));
267 : 138 : }
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 : : } xl_end_of_recovery;
306 : :
307 : : /*
308 : : * The functions in xloginsert.c construct a chain of XLogRecData structs
309 : : * to represent the final WAL record.
310 : : */
311 : : typedef struct XLogRecData
312 : : {
313 : : struct XLogRecData *next; /* next struct in chain, or NULL */
314 : : char *data; /* start of rmgr data to include */
315 : : uint32 len; /* length of rmgr data to include */
316 : : } XLogRecData;
317 : :
318 : : /*
319 : : * Recovery target action.
320 : : */
321 : : typedef enum
322 : : {
323 : : RECOVERY_TARGET_ACTION_PAUSE,
324 : : RECOVERY_TARGET_ACTION_PROMOTE,
325 : : RECOVERY_TARGET_ACTION_SHUTDOWN,
326 : : } RecoveryTargetAction;
327 : :
328 : : struct LogicalDecodingContext;
329 : : struct XLogRecordBuffer;
330 : :
331 : : /*
332 : : * Method table for resource managers.
333 : : *
334 : : * This struct must be kept in sync with the PG_RMGR definition in
335 : : * rmgr.c.
336 : : *
337 : : * rm_identify must return a name for the record based on xl_info (without
338 : : * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
339 : : * "VACUUM". rm_desc can then be called to obtain additional detail for the
340 : : * record, if available (e.g. the last block).
341 : : *
342 : : * rm_mask takes as input a page modified by the resource manager and masks
343 : : * out bits that shouldn't be flagged by wal_consistency_checking.
344 : : *
345 : : * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is
346 : : * NULL, the corresponding RmgrTable entry is considered invalid.
347 : : */
348 : : typedef struct RmgrData
349 : : {
350 : : const char *rm_name;
351 : : void (*rm_redo) (XLogReaderState *record);
352 : : void (*rm_desc) (StringInfo buf, XLogReaderState *record);
353 : : const char *(*rm_identify) (uint8 info);
354 : : void (*rm_startup) (void);
355 : : void (*rm_cleanup) (void);
356 : : void (*rm_mask) (char *pagedata, BlockNumber blkno);
357 : : void (*rm_decode) (struct LogicalDecodingContext *ctx,
358 : : struct XLogRecordBuffer *buf);
359 : : } RmgrData;
360 : :
361 : : extern PGDLLIMPORT RmgrData RmgrTable[];
362 : : extern void RmgrStartup(void);
363 : : extern void RmgrCleanup(void);
364 : : extern void RmgrNotFound(RmgrId rmid);
365 : : extern void RegisterCustomRmgr(RmgrId rmid, const RmgrData *rmgr);
366 : :
367 : : #ifndef FRONTEND
368 : : static inline bool
739 jdavis@postgresql.or 369 : 5278446 : RmgrIdExists(RmgrId rmid)
370 : : {
371 : 5278446 : return RmgrTable[rmid].rm_name != NULL;
372 : : }
373 : :
374 : : static inline RmgrData
375 : 5182216 : GetRmgr(RmgrId rmid)
376 : : {
377 [ - + ]: 5182216 : if (unlikely(!RmgrIdExists(rmid)))
739 jdavis@postgresql.or 378 :UBC 0 : RmgrNotFound(rmid);
739 jdavis@postgresql.or 379 :CBC 5182216 : return RmgrTable[rmid];
380 : : }
381 : : #endif
382 : :
383 : : /*
384 : : * Exported to support xlog switching from checkpointer
385 : : */
386 : : extern pg_time_t GetLastSegSwitchData(XLogRecPtr *lastSwitchLSN);
387 : : extern XLogRecPtr RequestXLogSwitch(bool mark_unimportant);
388 : :
389 : : extern void GetOldestRestartPoint(XLogRecPtr *oldrecptr, TimeLineID *oldtli);
390 : :
391 : : extern void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
392 : : bool detailed_format, StringInfo buf,
393 : : uint32 *fpi_len);
394 : :
395 : : /*
396 : : * Exported for the functions in timeline.c and xlogarchive.c. Only valid
397 : : * in the startup process.
398 : : */
399 : : extern PGDLLIMPORT bool ArchiveRecoveryRequested;
400 : : extern PGDLLIMPORT bool InArchiveRecovery;
401 : : extern PGDLLIMPORT bool StandbyMode;
402 : : extern PGDLLIMPORT char *recoveryRestoreCommand;
403 : :
404 : : #endif /* XLOG_INTERNAL_H */
|