137 pg_fatal(
"could not create directory \"%s\": %m", path);
146 pg_fatal(
"directory \"%s\" exists but is not empty", path);
150 pg_fatal(
"could not access directory \"%s\": %m", path);
199 pg_fatal(
"could not open file \"%s\": %m", fname);
257 "invalid WAL segment size in WAL file \"%s\" (%d bytes)",
265 pg_fatal(
"could not read file \"%s\": %m",
268 pg_fatal(
"could not read file \"%s\": read %d of %d",
329 pg_fatal(
"could not locate WAL file \"%s\"", fname);
331 pg_fatal(
"could not find any WAL file");
353 for (tries = 0; tries < 10; tries++)
356 if (
state->seg.ws_file >= 0)
372 pg_fatal(
"could not find file \"%s\": %m", fname);
384 state->seg.ws_file = -1;
404 private->endptr_reached =
true;
416 state->segcxt.ws_segsize);
421 pg_fatal(
"could not read from file \"%s\", offset %d: %m",
425 pg_fatal(
"could not read from file \"%s\", offset %d: read %d of %d",
452 &rlocator, &forknum, &
blk,
NULL))
558 printf(
"rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
616 "%20" PRIu64 " (%6.02f)\n",
659 printf(
"WAL statistics between %X/%08X and %X/%08X:\n",
667 printf(
"%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n"
668 "%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n",
669 "Type",
"N",
"(%)",
"Record size",
"(%)",
"FPI size",
"(%)",
"Combined size",
"(%)",
670 "----",
"-",
"---",
"-----------",
"---",
"--------",
"---",
"-------------",
"---");
726 printf(
"%-27s %20s %8s %20s %8s %20s %8s %20s\n",
727 "",
"--------",
"",
"--------",
"",
"--------",
"",
"--------");
749 "Total", stats->
count,
"",
752 total_len,
"[100%]");
758 printf(
_(
"%s decodes and displays PostgreSQL write-ahead logs for debugging.\n\n"),
763 printf(
_(
" -b, --bkp-details output detailed information about backup blocks\n"));
764 printf(
_(
" -B, --block=N with --relation, only show records that modify block N\n"));
765 printf(
_(
" -e, --end=RECPTR stop reading at WAL location RECPTR\n"));
766 printf(
_(
" -f, --follow keep retrying after reaching end of WAL\n"));
767 printf(
_(
" -F, --fork=FORK only show records that modify blocks in fork FORK;\n"
768 " valid names are main, fsm, vm, init\n"));
769 printf(
_(
" -n, --limit=N number of records to display\n"));
770 printf(
_(
" -p, --path=PATH directory in which to find WAL segment files or a\n"
771 " directory with a ./pg_wal that contains such files\n"
772 " (default: current directory, ./pg_wal, $PGDATA/pg_wal)\n"));
773 printf(
_(
" -q, --quiet do not print any output, except for errors\n"));
774 printf(
_(
" -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n"
775 " use --rmgr=list to list valid resource manager names\n"));
776 printf(
_(
" -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n"));
777 printf(
_(
" -s, --start=RECPTR start reading at WAL location RECPTR\n"));
778 printf(
_(
" -t, --timeline=TLI timeline from which to read WAL records\n"
779 " (default: 1 or the value used in STARTSEG)\n"));
780 printf(
_(
" -V, --version output version information, then exit\n"));
781 printf(
_(
" -w, --fullpage only show records with a full page write\n"));
782 printf(
_(
" -x, --xid=XID only show records with transaction ID XID\n"));
783 printf(
_(
" -z, --stats[=record] show statistics instead of records\n"
784 " (optionally, show per-record statistics)\n"));
785 printf(
_(
" --save-fullpage=DIR save full page images to DIR\n"));
786 printf(
_(
" -?, --help show this help, then exit\n"));
840 if (
strcmp(argv[1],
"--help") == 0 ||
strcmp(argv[1],
"-?") == 0)
845 if (
strcmp(argv[1],
"--version") == 0 ||
strcmp(argv[1],
"-V") == 0)
856 private.timeline = 1;
859 private.endptr_reached =
false;
861 config.
quiet =
false;
876 config.
stats =
false;
913 private.endptr = (
uint64) xlogid << 32 | xrecoff;
961 pg_log_error(
"custom resource manager \"%s\" does not exist",
1012 private.startptr = (
uint64) xlogid << 32 | xrecoff;
1028 while (*endptr !=
'\0' &&
isspace((
unsigned char) *endptr))
1031 if (*endptr !=
'\0')
1034 optarg,
"-t/--timeline");
1045 private.timeline =
val;
1055 pg_log_error(
"invalid transaction ID specification: \"%s\"",
1062 config.
stats =
true;
1087 pg_log_error(
"option %s requires option %s to be specified",
1088 "-B/--block",
"-R/--relation");
1094 pg_log_error(
"too many command-line arguments (first is \"%s\")",
1133 pg_fatal(
"could not open file \"%s\"", fname);
1143 pg_log_error(
"start WAL location %X/%08X is not inside file \"%s\"",
1163 pg_fatal(
"could not open file \"%s\"", fname);
1170 pg_fatal(
"ENDSEG %s is before STARTSEG %s",
1183 private.endptr != (segno + 1) *
WalSegSz)
1185 pg_log_error(
"end WAL location %X/%08X is not inside file \"%s\"",
1211 pg_fatal(
"out of memory while allocating a WAL reading processor");
1217 pg_fatal(
"could not find a valid record after %X/%08X",
1228 "first record is after %X/%08X, at %X/%08X, skipping over %u bytes",
1249 if (!config.
follow ||
private.endptr_reached)
1285 if (config.
stats ==
true)
1312 pg_fatal(
"error in WAL record at %X/%08X: %s",
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
#define ngettext(s, p, n)
#define Assert(condition)
#define PG_TEXTDOMAIN(domain)
#define OidIsValid(objectId)
void set_pglocale_pgservice(const char *argv0, const char *app)
struct dirent * readdir(DIR *)
DIR * opendir(const char *)
char * pg_strdup(const char *in)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
#define required_argument
#define optional_argument
void pg_logging_init(const char *argv0)
#define pg_log_error(...)
#define pg_log_error_hint(...)
#define pg_log_error_detail(...)
void pfree(void *pointer)
char * pnstrdup(const char *in, Size len)
PGDLLIMPORT char * optarg
static char buf[DEFAULT_XLOG_SEG_SIZE]
static bool search_directory(const char *directory, const char *fname)
static void XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
static void WALDumpCloseSegment(XLogReaderState *state)
static char * identify_target_directory(char *directory, char *fname)
static volatile sig_atomic_t time_to_stop
static void split_path(const char *path, char **dir, char **fname)
static int open_file_in_directory(const char *directory, const char *fname)
static void XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record)
static void XLogDumpStatsRow(const char *name, uint64 n, uint64 total_count, uint64 rec_len, uint64 total_rec_len, uint64 fpi_len, uint64 total_fpi_len, uint64 tot_len, uint64 total_len)
static void create_fullpage_directory(char *path)
static bool verify_directory(const char *directory)
static const RelFileLocator emptyRelFileLocator
static void print_rmgr_list(void)
static void WALDumpOpenSegment(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
static const char * progname
static int WALDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetPtr, char *readBuff)
static void XLogRecordSaveFPWs(XLogReaderState *record, const char *savepath)
static bool XLogRecordHasFPW(XLogReaderState *record)
static void sigint_handler(SIGNAL_ARGS)
static bool XLogRecordMatchesRelationBlock(XLogReaderState *record, RelFileLocator matchRlocator, BlockNumber matchBlock, ForkNumber matchFork)
int pg_mkdir_p(char *path, int omode)
int pg_strcasecmp(const char *s1, const char *s2)
int pg_check_dir(const char *dir)
const char * get_progname(const char *argv0)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
#define RelFileLocatorEquals(locator1, locator2)
ForkNumber forkname_to_number(const char *forkName)
const char *const forkNames[]
#define RelFileNumberIsValid(relnumber)
#define RM_MAX_BUILTIN_ID
static bool RmgrIdIsCustom(int rmid)
#define RmgrIdIsValid(rmid)
const RmgrDescData * GetRmgrDesc(RmgrId rmid)
void pg_usleep(long microsec)
void resetStringInfo(StringInfo str)
void initStringInfo(StringInfo str)
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
const char *(* rm_identify)(uint8 info)
bool filter_by_xid_enabled
RelFileLocator filter_by_relation
char * save_fullpage_path
bool filter_by_rmgr[RM_MAX_ID+1]
int already_displayed_records
bool filter_by_relation_enabled
BlockNumber filter_by_relation_block
bool filter_by_rmgr_enabled
TransactionId filter_by_xid
ForkNumber filter_by_relation_forknum
bool filter_by_relation_block_enabled
XLogRecStats record_stats[RM_MAX_ID+1][MAX_XLINFO_TYPES]
XLogRecStats rmgr_stats[RM_MAX_ID+1]
#define InvalidTransactionId
#define IsValidWalSegSize(size)
XLogLongPageHeaderData * XLogLongPageHeader
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
static bool IsXLogFileName(const char *fname)
static void XLogFromFileName(const char *fname, TimeLineID *tli, XLogSegNo *logSegNo, int wal_segsz_bytes)
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogRecPtrIsValid(r)
#define LSN_FORMAT_ARGS(lsn)
#define InvalidXLogRecPtr
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
void XLogReaderFree(XLogReaderState *state)
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#define XLogRecGetInfo(decoder)
#define XLogRecGetRmid(decoder)
#define XLogRecGetTotalLen(decoder)
#define XLogRecGetXid(decoder)
#define XLogRecMaxBlockId(decoder)
#define XLogRecHasBlockImage(decoder, block_id)
#define XLogRecHasBlockRef(decoder, block_id)
#define XLogRecGetPrev(decoder)
void XLogRecStoreStats(XLogStats *stats, XLogReaderState *record)
void XLogRecGetLen(XLogReaderState *record, uint32 *rec_len, uint32 *fpi_len)
static const char * directory