mirror of
https://github.com/postgres/postgres.git
synced 2026-04-15 22:10:45 -04:00
pg_waldump: Preparatory refactoring for tar archive WAL decoding.
Several refactoring steps in preparation for adding tar archive WAL decoding support to pg_waldump: - Move XLogDumpPrivate and related declarations into a new pg_waldump.h header, allowing a second source file to share them. - Factor out required_read_len() so the read-size calculation can be reused for both regular WAL files and tar-archived WAL. - Move the WAL segment size variable into XLogDumpPrivate and rename it to segsize, making it accessible to the archive streamer code. Author: Amul Sul <sulamul@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Jakub Wartak <jakub.wartak@enterprisedb.com> Reviewed-by: Chao Li <li.evan.chao@gmail.com> Reviewed-by: Euler Taveira <euler@eulerto.com> Reviewed-by: Andrew Dunstan <andrew@dunslane.net> discussion: https://postgr.es/m/CAAJ_b94bqdWN3h2J-PzzzQ2Npbwct5ZQHggn_QoYGhC2rn-=WQ@mail.gmail.com
This commit is contained in:
parent
c8a350a439
commit
f8a0cd2671
2 changed files with 70 additions and 34 deletions
|
|
@ -29,6 +29,7 @@
|
|||
#include "common/logging.h"
|
||||
#include "common/relpath.h"
|
||||
#include "getopt_long.h"
|
||||
#include "pg_waldump.h"
|
||||
#include "rmgrdesc.h"
|
||||
#include "storage/bufpage.h"
|
||||
|
||||
|
|
@ -43,14 +44,6 @@ static volatile sig_atomic_t time_to_stop = false;
|
|||
|
||||
static const RelFileLocator emptyRelFileLocator = {0, 0, 0};
|
||||
|
||||
typedef struct XLogDumpPrivate
|
||||
{
|
||||
TimeLineID timeline;
|
||||
XLogRecPtr startptr;
|
||||
XLogRecPtr endptr;
|
||||
bool endptr_reached;
|
||||
} XLogDumpPrivate;
|
||||
|
||||
typedef struct XLogDumpConfig
|
||||
{
|
||||
/* display options */
|
||||
|
|
@ -333,6 +326,32 @@ identify_target_directory(char *directory, char *fname, int *WalSegSz)
|
|||
return NULL; /* not reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the size in bytes of the data to be read. Returns -1 if the end
|
||||
* point has already been reached.
|
||||
*/
|
||||
static inline int
|
||||
required_read_len(XLogDumpPrivate *private, XLogRecPtr targetPagePtr,
|
||||
int reqLen)
|
||||
{
|
||||
int count = XLOG_BLCKSZ;
|
||||
|
||||
if (XLogRecPtrIsValid(private->endptr))
|
||||
{
|
||||
if (targetPagePtr + XLOG_BLCKSZ <= private->endptr)
|
||||
count = XLOG_BLCKSZ;
|
||||
else if (targetPagePtr + reqLen <= private->endptr)
|
||||
count = private->endptr - targetPagePtr;
|
||||
else
|
||||
{
|
||||
private->endptr_reached = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* pg_waldump's XLogReaderRoutine->segment_open callback */
|
||||
static void
|
||||
WALDumpOpenSegment(XLogReaderState *state, XLogSegNo nextSegNo,
|
||||
|
|
@ -390,21 +409,12 @@ WALDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
|
|||
XLogRecPtr targetPtr, char *readBuff)
|
||||
{
|
||||
XLogDumpPrivate *private = state->private_data;
|
||||
int count = XLOG_BLCKSZ;
|
||||
int count = required_read_len(private, targetPagePtr, reqLen);
|
||||
WALReadError errinfo;
|
||||
|
||||
if (XLogRecPtrIsValid(private->endptr))
|
||||
{
|
||||
if (targetPagePtr + XLOG_BLCKSZ <= private->endptr)
|
||||
count = XLOG_BLCKSZ;
|
||||
else if (targetPagePtr + reqLen <= private->endptr)
|
||||
count = private->endptr - targetPagePtr;
|
||||
else
|
||||
{
|
||||
private->endptr_reached = true;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Bail out if the count to be read is not valid */
|
||||
if (count < 0)
|
||||
return -1;
|
||||
|
||||
if (!WALRead(state, readBuff, targetPagePtr, count, private->timeline,
|
||||
&errinfo))
|
||||
|
|
@ -801,7 +811,6 @@ main(int argc, char **argv)
|
|||
XLogRecPtr first_record;
|
||||
char *waldir = NULL;
|
||||
char *errormsg;
|
||||
int WalSegSz;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"bkp-details", no_argument, NULL, 'b'},
|
||||
|
|
@ -855,6 +864,7 @@ main(int argc, char **argv)
|
|||
memset(&stats, 0, sizeof(XLogStats));
|
||||
|
||||
private.timeline = 1;
|
||||
private.segsize = 0;
|
||||
private.startptr = InvalidXLogRecPtr;
|
||||
private.endptr = InvalidXLogRecPtr;
|
||||
private.endptr_reached = false;
|
||||
|
|
@ -1128,18 +1138,18 @@ main(int argc, char **argv)
|
|||
pg_fatal("could not open directory \"%s\": %m", waldir);
|
||||
}
|
||||
|
||||
waldir = identify_target_directory(waldir, fname, &WalSegSz);
|
||||
waldir = identify_target_directory(waldir, fname, &private.segsize);
|
||||
fd = open_file_in_directory(waldir, fname);
|
||||
if (fd < 0)
|
||||
pg_fatal("could not open file \"%s\"", fname);
|
||||
close(fd);
|
||||
|
||||
/* parse position from file */
|
||||
XLogFromFileName(fname, &private.timeline, &segno, WalSegSz);
|
||||
XLogFromFileName(fname, &private.timeline, &segno, private.segsize);
|
||||
|
||||
if (!XLogRecPtrIsValid(private.startptr))
|
||||
XLogSegNoOffsetToRecPtr(segno, 0, WalSegSz, private.startptr);
|
||||
else if (!XLByteInSeg(private.startptr, segno, WalSegSz))
|
||||
XLogSegNoOffsetToRecPtr(segno, 0, private.segsize, private.startptr);
|
||||
else if (!XLByteInSeg(private.startptr, segno, private.segsize))
|
||||
{
|
||||
pg_log_error("start WAL location %X/%08X is not inside file \"%s\"",
|
||||
LSN_FORMAT_ARGS(private.startptr),
|
||||
|
|
@ -1149,7 +1159,7 @@ main(int argc, char **argv)
|
|||
|
||||
/* no second file specified, set end position */
|
||||
if (!(optind + 1 < argc) && !XLogRecPtrIsValid(private.endptr))
|
||||
XLogSegNoOffsetToRecPtr(segno + 1, 0, WalSegSz, private.endptr);
|
||||
XLogSegNoOffsetToRecPtr(segno + 1, 0, private.segsize, private.endptr);
|
||||
|
||||
/* parse ENDSEG if passed */
|
||||
if (optind + 1 < argc)
|
||||
|
|
@ -1165,14 +1175,14 @@ main(int argc, char **argv)
|
|||
close(fd);
|
||||
|
||||
/* parse position from file */
|
||||
XLogFromFileName(fname, &private.timeline, &endsegno, WalSegSz);
|
||||
XLogFromFileName(fname, &private.timeline, &endsegno, private.segsize);
|
||||
|
||||
if (endsegno < segno)
|
||||
pg_fatal("ENDSEG %s is before STARTSEG %s",
|
||||
argv[optind + 1], argv[optind]);
|
||||
|
||||
if (!XLogRecPtrIsValid(private.endptr))
|
||||
XLogSegNoOffsetToRecPtr(endsegno + 1, 0, WalSegSz,
|
||||
XLogSegNoOffsetToRecPtr(endsegno + 1, 0, private.segsize,
|
||||
private.endptr);
|
||||
|
||||
/* set segno to endsegno for check of --end */
|
||||
|
|
@ -1180,8 +1190,8 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
|
||||
if (!XLByteInSeg(private.endptr, segno, WalSegSz) &&
|
||||
private.endptr != (segno + 1) * WalSegSz)
|
||||
if (!XLByteInSeg(private.endptr, segno, private.segsize) &&
|
||||
private.endptr != (segno + 1) * private.segsize)
|
||||
{
|
||||
pg_log_error("end WAL location %X/%08X is not inside file \"%s\"",
|
||||
LSN_FORMAT_ARGS(private.endptr),
|
||||
|
|
@ -1190,7 +1200,7 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
else
|
||||
waldir = identify_target_directory(waldir, NULL, &WalSegSz);
|
||||
waldir = identify_target_directory(waldir, NULL, &private.segsize);
|
||||
|
||||
/* we don't know what to print */
|
||||
if (!XLogRecPtrIsValid(private.startptr))
|
||||
|
|
@ -1203,7 +1213,7 @@ main(int argc, char **argv)
|
|||
|
||||
/* we have everything we need, start reading */
|
||||
xlogreader_state =
|
||||
XLogReaderAllocate(WalSegSz, waldir,
|
||||
XLogReaderAllocate(private.segsize, waldir,
|
||||
XL_ROUTINE(.page_read = WALDumpReadPage,
|
||||
.segment_open = WALDumpOpenSegment,
|
||||
.segment_close = WALDumpCloseSegment),
|
||||
|
|
@ -1224,7 +1234,7 @@ main(int argc, char **argv)
|
|||
* a segment (e.g. we were used in file mode).
|
||||
*/
|
||||
if (first_record != private.startptr &&
|
||||
XLogSegmentOffset(private.startptr, WalSegSz) != 0)
|
||||
XLogSegmentOffset(private.startptr, private.segsize) != 0)
|
||||
pg_log_info(ngettext("first record is after %X/%08X, at %X/%08X, skipping over %u byte",
|
||||
"first record is after %X/%08X, at %X/%08X, skipping over %u bytes",
|
||||
(first_record - private.startptr)),
|
||||
|
|
|
|||
26
src/bin/pg_waldump/pg_waldump.h
Normal file
26
src/bin/pg_waldump/pg_waldump.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_waldump.h - decode and display WAL
|
||||
*
|
||||
* Copyright (c) 2026, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/bin/pg_waldump/pg_waldump.h
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PG_WALDUMP_H
|
||||
#define PG_WALDUMP_H
|
||||
|
||||
#include "access/xlogdefs.h"
|
||||
|
||||
/* Contains the necessary information to drive WAL decoding */
|
||||
typedef struct XLogDumpPrivate
|
||||
{
|
||||
TimeLineID timeline;
|
||||
int segsize;
|
||||
XLogRecPtr startptr;
|
||||
XLogRecPtr endptr;
|
||||
bool endptr_reached;
|
||||
} XLogDumpPrivate;
|
||||
|
||||
#endif /* PG_WALDUMP_H */
|
||||
Loading…
Reference in a new issue