nbtree: fix read page recheck typo.
[pgsql.git] / src / backend / backup / walsummaryfuncs.c
blobbb6a3a4a36677189abbbf424083fbda7cbec5f1c
1 /*-------------------------------------------------------------------------
3 * walsummaryfuncs.c
4 * SQL-callable functions for accessing WAL summary data.
6 * Portions Copyright (c) 2010-2024, PostgreSQL Global Development Group
8 * src/backend/backup/walsummaryfuncs.c
10 *-------------------------------------------------------------------------
13 #include "postgres.h"
15 #include "backup/walsummary.h"
16 #include "common/blkreftable.h"
17 #include "funcapi.h"
18 #include "miscadmin.h"
19 #include "postmaster/walsummarizer.h"
20 #include "utils/fmgrprotos.h"
21 #include "utils/pg_lsn.h"
23 #define NUM_WS_ATTS 3
24 #define NUM_SUMMARY_ATTS 6
25 #define NUM_STATE_ATTS 4
26 #define MAX_BLOCKS_PER_CALL 256
29 * List the WAL summary files available in pg_wal/summaries.
31 Datum
32 pg_available_wal_summaries(PG_FUNCTION_ARGS)
34 ReturnSetInfo *rsi;
35 List *wslist;
36 ListCell *lc;
37 Datum values[NUM_WS_ATTS];
38 bool nulls[NUM_WS_ATTS];
40 InitMaterializedSRF(fcinfo, 0);
41 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
43 memset(nulls, 0, sizeof(nulls));
45 wslist = GetWalSummaries(0, InvalidXLogRecPtr, InvalidXLogRecPtr);
46 foreach(lc, wslist)
48 WalSummaryFile *ws = (WalSummaryFile *) lfirst(lc);
49 HeapTuple tuple;
51 CHECK_FOR_INTERRUPTS();
53 values[0] = Int64GetDatum((int64) ws->tli);
54 values[1] = LSNGetDatum(ws->start_lsn);
55 values[2] = LSNGetDatum(ws->end_lsn);
57 tuple = heap_form_tuple(rsi->setDesc, values, nulls);
58 tuplestore_puttuple(rsi->setResult, tuple);
61 return (Datum) 0;
65 * List the contents of a WAL summary file identified by TLI, start LSN,
66 * and end LSN.
68 Datum
69 pg_wal_summary_contents(PG_FUNCTION_ARGS)
71 ReturnSetInfo *rsi;
72 Datum values[NUM_SUMMARY_ATTS];
73 bool nulls[NUM_SUMMARY_ATTS];
74 WalSummaryFile ws;
75 WalSummaryIO io;
76 BlockRefTableReader *reader;
77 int64 raw_tli;
78 RelFileLocator rlocator;
79 ForkNumber forknum;
80 BlockNumber limit_block;
82 InitMaterializedSRF(fcinfo, 0);
83 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
84 memset(nulls, 0, sizeof(nulls));
87 * Since the timeline could at least in theory be more than 2^31, and
88 * since we don't have unsigned types at the SQL level, it is passed as a
89 * 64-bit integer. Test whether it's out of range.
91 raw_tli = PG_GETARG_INT64(0);
92 if (raw_tli < 1 || raw_tli > PG_INT32_MAX)
93 ereport(ERROR,
94 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
95 errmsg("invalid timeline %lld", (long long) raw_tli));
97 /* Prepare to read the specified WAL summary file. */
98 ws.tli = (TimeLineID) raw_tli;
99 ws.start_lsn = PG_GETARG_LSN(1);
100 ws.end_lsn = PG_GETARG_LSN(2);
101 io.filepos = 0;
102 io.file = OpenWalSummaryFile(&ws, false);
103 reader = CreateBlockRefTableReader(ReadWalSummary, &io,
104 FilePathName(io.file),
105 ReportWalSummaryError, NULL);
107 /* Loop over relation forks. */
108 while (BlockRefTableReaderNextRelation(reader, &rlocator, &forknum,
109 &limit_block))
111 BlockNumber blocks[MAX_BLOCKS_PER_CALL];
112 HeapTuple tuple;
114 CHECK_FOR_INTERRUPTS();
116 values[0] = ObjectIdGetDatum(rlocator.relNumber);
117 values[1] = ObjectIdGetDatum(rlocator.spcOid);
118 values[2] = ObjectIdGetDatum(rlocator.dbOid);
119 values[3] = Int16GetDatum((int16) forknum);
122 * If the limit block is not InvalidBlockNumber, emit an extra row
123 * with that block number and limit_block = true.
125 * There is no point in doing this when the limit_block is
126 * InvalidBlockNumber, because no block with that number or any higher
127 * number can ever exist.
129 if (BlockNumberIsValid(limit_block))
131 values[4] = Int64GetDatum((int64) limit_block);
132 values[5] = BoolGetDatum(true);
134 tuple = heap_form_tuple(rsi->setDesc, values, nulls);
135 tuplestore_puttuple(rsi->setResult, tuple);
138 /* Loop over blocks within the current relation fork. */
139 while (1)
141 unsigned nblocks;
142 unsigned i;
144 CHECK_FOR_INTERRUPTS();
146 nblocks = BlockRefTableReaderGetBlocks(reader, blocks,
147 MAX_BLOCKS_PER_CALL);
148 if (nblocks == 0)
149 break;
152 * For each block that we specifically know to have been modified,
153 * emit a row with that block number and limit_block = false.
155 values[5] = BoolGetDatum(false);
156 for (i = 0; i < nblocks; ++i)
158 values[4] = Int64GetDatum((int64) blocks[i]);
160 tuple = heap_form_tuple(rsi->setDesc, values, nulls);
161 tuplestore_puttuple(rsi->setResult, tuple);
166 /* Cleanup */
167 DestroyBlockRefTableReader(reader);
168 FileClose(io.file);
170 return (Datum) 0;
174 * Returns information about the state of the WAL summarizer process.
176 Datum
177 pg_get_wal_summarizer_state(PG_FUNCTION_ARGS)
179 Datum values[NUM_STATE_ATTS];
180 bool nulls[NUM_STATE_ATTS];
181 TimeLineID summarized_tli;
182 XLogRecPtr summarized_lsn;
183 XLogRecPtr pending_lsn;
184 int summarizer_pid;
185 TupleDesc tupdesc;
186 HeapTuple htup;
188 GetWalSummarizerState(&summarized_tli, &summarized_lsn, &pending_lsn,
189 &summarizer_pid);
191 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
192 elog(ERROR, "return type must be a row type");
194 memset(nulls, 0, sizeof(nulls));
196 values[0] = Int64GetDatum((int64) summarized_tli);
197 values[1] = LSNGetDatum(summarized_lsn);
198 values[2] = LSNGetDatum(pending_lsn);
200 if (summarizer_pid < 0)
201 nulls[3] = true;
202 else
203 values[3] = Int32GetDatum(summarizer_pid);
205 htup = heap_form_tuple(tupdesc, values, nulls);
207 PG_RETURN_DATUM(HeapTupleGetDatum(htup));