1 /*-------------------------------------------------------------------------
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 *-------------------------------------------------------------------------
15 #include "backup/walsummary.h"
16 #include "common/blkreftable.h"
18 #include "miscadmin.h"
19 #include "postmaster/walsummarizer.h"
20 #include "utils/fmgrprotos.h"
21 #include "utils/pg_lsn.h"
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.
32 pg_available_wal_summaries(PG_FUNCTION_ARGS
)
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
);
48 WalSummaryFile
*ws
= (WalSummaryFile
*) lfirst(lc
);
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
);
65 * List the contents of a WAL summary file identified by TLI, start LSN,
69 pg_wal_summary_contents(PG_FUNCTION_ARGS
)
72 Datum values
[NUM_SUMMARY_ATTS
];
73 bool nulls
[NUM_SUMMARY_ATTS
];
76 BlockRefTableReader
*reader
;
78 RelFileLocator rlocator
;
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
)
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);
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
,
111 BlockNumber blocks
[MAX_BLOCKS_PER_CALL
];
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. */
144 CHECK_FOR_INTERRUPTS();
146 nblocks
= BlockRefTableReaderGetBlocks(reader
, blocks
,
147 MAX_BLOCKS_PER_CALL
);
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
);
167 DestroyBlockRefTableReader(reader
);
174 * Returns information about the state of the WAL summarizer process.
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
;
188 GetWalSummarizerState(&summarized_tli
, &summarized_lsn
, &pending_lsn
,
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)
203 values
[3] = Int32GetDatum(summarizer_pid
);
205 htup
= heap_form_tuple(tupdesc
, values
, nulls
);
207 PG_RETURN_DATUM(HeapTupleGetDatum(htup
));