Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 72af71a

Browse files
committed
Use correct LSN for error reporting in pg_walinspect
Usage of ReadNextXLogRecord()'s first_record parameter for error reporting isn't always correct. For instance, in GetWALRecordsInfo() and GetWalStats(), we're reading multiple records, and first_record is always passed as the LSN of the first record which is then used for error reporting for later WAL record read failures. This isn't correct. The correct parameter to use for error reports in case of WAL reading failures is xlogreader->EndRecPtr. This change fixes it. While on it, removed an unnecessary Assert in pg_walinspect code. Reported-by: Robert Haas Author: Bharath Rupireddy Reviewed-by: Robert Haas Discussion: https://www.postgresql.org/message-id/CA%2BTgmoZAOGzPUifrcZRjFZ2vbtcw3mp-mN6UgEoEcQg6bY3OVg%40mail.gmail.com Backpatch-through: 15
1 parent 2a42c1c commit 72af71a

File tree

1 file changed

+23
-30
lines changed

1 file changed

+23
-30
lines changed

contrib/pg_walinspect/pg_walinspect.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,10 @@ PG_FUNCTION_INFO_V1(pg_get_wal_stats);
3737
PG_FUNCTION_INFO_V1(pg_get_wal_stats_till_end_of_wal);
3838

3939
static bool IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn);
40-
static XLogReaderState *InitXLogReaderState(XLogRecPtr lsn,
41-
XLogRecPtr *first_record);
42-
static XLogRecord *ReadNextXLogRecord(XLogReaderState *xlogreader,
43-
XLogRecPtr first_record);
44-
static void GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
45-
Datum *values, bool *nulls, uint32 ncols);
40+
static XLogReaderState *InitXLogReaderState(XLogRecPtr lsn);
41+
static XLogRecord *ReadNextXLogRecord(XLogReaderState *xlogreader);
42+
static void GetWALRecordInfo(XLogReaderState *record, Datum *values,
43+
bool *nulls, uint32 ncols);
4644
static XLogRecPtr ValidateInputLSNs(bool till_end_of_wal,
4745
XLogRecPtr start_lsn, XLogRecPtr end_lsn);
4846
static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
@@ -86,10 +84,11 @@ IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn)
8684
* Intialize WAL reader and identify first valid LSN.
8785
*/
8886
static XLogReaderState *
89-
InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
87+
InitXLogReaderState(XLogRecPtr lsn)
9088
{
9189
XLogReaderState *xlogreader;
9290
ReadLocalXLogPageNoWaitPrivate *private_data;
91+
XLogRecPtr first_valid_record;
9392

9493
/*
9594
* Reading WAL below the first page of the first segments isn't allowed.
@@ -117,9 +116,9 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
117116
errdetail("Failed while allocating a WAL reading processor.")));
118117

119118
/* first find a valid recptr to start from */
120-
*first_record = XLogFindNextRecord(xlogreader, lsn);
119+
first_valid_record = XLogFindNextRecord(xlogreader, lsn);
121120

122-
if (XLogRecPtrIsInvalid(*first_record))
121+
if (XLogRecPtrIsInvalid(first_valid_record))
123122
ereport(ERROR,
124123
(errmsg("could not find a valid record after %X/%X",
125124
LSN_FORMAT_ARGS(lsn))));
@@ -140,7 +139,7 @@ InitXLogReaderState(XLogRecPtr lsn, XLogRecPtr *first_record)
140139
* that case we'll return NULL.
141140
*/
142141
static XLogRecord *
143-
ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
142+
ReadNextXLogRecord(XLogReaderState *xlogreader)
144143
{
145144
XLogRecord *record;
146145
char *errormsg;
@@ -162,12 +161,12 @@ ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
162161
ereport(ERROR,
163162
(errcode_for_file_access(),
164163
errmsg("could not read WAL at %X/%X: %s",
165-
LSN_FORMAT_ARGS(first_record), errormsg)));
164+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
166165
else
167166
ereport(ERROR,
168167
(errcode_for_file_access(),
169168
errmsg("could not read WAL at %X/%X",
170-
LSN_FORMAT_ARGS(first_record))));
169+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
171170
}
172171

173172
return record;
@@ -177,8 +176,8 @@ ReadNextXLogRecord(XLogReaderState *xlogreader, XLogRecPtr first_record)
177176
* Get a single WAL record info.
178177
*/
179178
static void
180-
GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
181-
Datum *values, bool *nulls, uint32 ncols)
179+
GetWALRecordInfo(XLogReaderState *record, Datum *values,
180+
bool *nulls, uint32 ncols)
182181
{
183182
const char *id;
184183
RmgrData desc;
@@ -203,7 +202,7 @@ GetWALRecordInfo(XLogReaderState *record, XLogRecPtr lsn,
203202

204203
main_data_len = XLogRecGetDataLen(record);
205204

206-
values[i++] = LSNGetDatum(lsn);
205+
values[i++] = LSNGetDatum(record->ReadRecPtr);
207206
values[i++] = LSNGetDatum(record->EndRecPtr);
208207
values[i++] = LSNGetDatum(XLogRecGetPrev(record));
209208
values[i++] = TransactionIdGetDatum(XLogRecGetXid(record));
@@ -233,7 +232,6 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
233232
bool nulls[PG_GET_WAL_RECORD_INFO_COLS];
234233
XLogRecPtr lsn;
235234
XLogRecPtr curr_lsn;
236-
XLogRecPtr first_record;
237235
XLogReaderState *xlogreader;
238236
TupleDesc tupdesc;
239237
HeapTuple tuple;
@@ -258,19 +256,18 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
258256
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
259257
elog(ERROR, "return type must be a row type");
260258

261-
xlogreader = InitXLogReaderState(lsn, &first_record);
259+
xlogreader = InitXLogReaderState(lsn);
262260

263-
if (!ReadNextXLogRecord(xlogreader, first_record))
261+
if (!ReadNextXLogRecord(xlogreader))
264262
ereport(ERROR,
265263
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
266264
errmsg("could not read WAL at %X/%X",
267-
LSN_FORMAT_ARGS(first_record))));
265+
LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
268266

269267
MemSet(values, 0, sizeof(values));
270268
MemSet(nulls, 0, sizeof(nulls));
271269

272-
GetWALRecordInfo(xlogreader, first_record, values, nulls,
273-
PG_GET_WAL_RECORD_INFO_COLS);
270+
GetWALRecordInfo(xlogreader, values, nulls, PG_GET_WAL_RECORD_INFO_COLS);
274271

275272
pfree(xlogreader->private_data);
276273
XLogReaderFree(xlogreader);
@@ -331,25 +328,22 @@ GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
331328
XLogRecPtr end_lsn)
332329
{
333330
#define PG_GET_WAL_RECORDS_INFO_COLS 11
334-
XLogRecPtr first_record;
335331
XLogReaderState *xlogreader;
336332
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
337333
Datum values[PG_GET_WAL_RECORDS_INFO_COLS];
338334
bool nulls[PG_GET_WAL_RECORDS_INFO_COLS];
339335

340336
SetSingleFuncCall(fcinfo, 0);
341337

342-
xlogreader = InitXLogReaderState(start_lsn, &first_record);
343-
344-
Assert(xlogreader);
338+
xlogreader = InitXLogReaderState(start_lsn);
345339

346340
MemSet(values, 0, sizeof(values));
347341
MemSet(nulls, 0, sizeof(nulls));
348342

349-
while (ReadNextXLogRecord(xlogreader, first_record) &&
343+
while (ReadNextXLogRecord(xlogreader) &&
350344
xlogreader->EndRecPtr <= end_lsn)
351345
{
352-
GetWALRecordInfo(xlogreader, xlogreader->currRecPtr, values, nulls,
346+
GetWALRecordInfo(xlogreader, values, nulls,
353347
PG_GET_WAL_RECORDS_INFO_COLS);
354348

355349
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
@@ -554,7 +548,6 @@ GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
554548
XLogRecPtr end_lsn, bool stats_per_record)
555549
{
556550
#define PG_GET_WAL_STATS_COLS 9
557-
XLogRecPtr first_record;
558551
XLogReaderState *xlogreader;
559552
XLogStats stats;
560553
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
@@ -563,11 +556,11 @@ GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
563556

564557
SetSingleFuncCall(fcinfo, 0);
565558

566-
xlogreader = InitXLogReaderState(start_lsn, &first_record);
559+
xlogreader = InitXLogReaderState(start_lsn);
567560

568561
MemSet(&stats, 0, sizeof(stats));
569562

570-
while (ReadNextXLogRecord(xlogreader, first_record) &&
563+
while (ReadNextXLogRecord(xlogreader) &&
571564
xlogreader->EndRecPtr <= end_lsn)
572565
{
573566
XLogRecStoreStats(&stats, xlogreader);

0 commit comments

Comments
 (0)