129 pg_fatal(
"could not create directory \"%s\": %m", path);
138 pg_fatal(
"directory \"%s\" exists but is not empty", path);
142 pg_fatal(
"could not access directory \"%s\": %m", path);
191 pg_fatal(
"could not open file \"%s\": %m", fname);
247 "invalid WAL segment size in WAL file \"%s\" (%d bytes)",
257 pg_fatal(
"could not read file \"%s\": %m",
260 pg_fatal(
"could not read file \"%s\": read %d of %d",
322 pg_fatal(
"could not locate WAL file \"%s\"", fname);
324 pg_fatal(
"could not find any WAL file");
347 private->endptr_reached =
true;
372 for (tries = 0; tries < 10; tries++)
375 if (
state->seg.ws_file >= 0)
391 pg_fatal(
"could not find file \"%s\": %m", fname);
403 state->seg.ws_file = -1;
426 state->segcxt.ws_segsize);
431 pg_fatal(
"could not read from file \"%s\", offset %d: %m",
435 pg_fatal(
"could not read from file \"%s\", offset %d: read %d of %d",
476 int segsize =
state->segcxt.ws_segsize;
504 state->seg.ws_tli =
private->timeline;
508 if (
state->seg.ws_file >= 0)
511 state->seg.ws_file = -1;
538 if (
state->seg.ws_file >= 0)
565 &rlocator, &forknum, &
blk,
NULL))
671 printf(
"rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
729 "%20" PRIu64 " (%6.02f)\n",
772 printf(
"WAL statistics between %X/%08X and %X/%08X:\n",
780 printf(
"%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n"
781 "%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n",
782 "Type",
"N",
"(%)",
"Record size",
"(%)",
"FPI size",
"(%)",
"Combined size",
"(%)",
783 "----",
"-",
"---",
"-----------",
"---",
"--------",
"---",
"-------------",
"---");
839 printf(
"%-27s %20s %8s %20s %8s %20s %8s %20s\n",
840 "",
"--------",
"",
"--------",
"",
"--------",
"",
"--------");
862 "Total", stats->
count,
"",
865 total_len,
"[100%]");
871 printf(
_(
"%s decodes and displays PostgreSQL write-ahead logs for debugging.\n\n"),
876 printf(
_(
" -b, --bkp-details output detailed information about backup blocks\n"));
877 printf(
_(
" -B, --block=N with --relation, only show records that modify block N\n"));
878 printf(
_(
" -e, --end=RECPTR stop reading at WAL location RECPTR\n"));
879 printf(
_(
" -f, --follow keep retrying after reaching end of WAL\n"));
880 printf(
_(
" -F, --fork=FORK only show records that modify blocks in fork FORK;\n"
881 " valid names are main, fsm, vm, init\n"));
882 printf(
_(
" -n, --limit=N number of records to display\n"));
883 printf(
_(
" -p, --path=PATH a tar archive or a directory in which to find WAL segment files or\n"
884 " a directory with a pg_wal subdirectory containing such files\n"
885 " (default: current directory, ./pg_wal, $PGDATA/pg_wal)\n"));
886 printf(
_(
" -q, --quiet do not print any output, except for errors\n"));
887 printf(
_(
" -r, --rmgr=RMGR only show records generated by resource manager RMGR;\n"
888 " use --rmgr=list to list valid resource manager names\n"));
889 printf(
_(
" -R, --relation=T/D/R only show records that modify blocks in relation T/D/R\n"));
890 printf(
_(
" -s, --start=RECPTR start reading at WAL location RECPTR\n"));
891 printf(
_(
" -t, --timeline=TLI timeline from which to read WAL records\n"
892 " (default: 1 or the value used in STARTSEG)\n"));
893 printf(
_(
" -V, --version output version information, then exit\n"));
894 printf(
_(
" -w, --fullpage only show records with a full page write\n"));
895 printf(
_(
" -x, --xid=XID only show records with transaction ID XID\n"));
896 printf(
_(
" -z, --stats[=record] show statistics instead of records\n"
897 " (optionally, show per-record statistics)\n"));
898 printf(
_(
" --save-fullpage=DIR save full page images to DIR\n"));
899 printf(
_(
" -?, --help show this help, then exit\n"));
954 if (
strcmp(argv[1],
"--help") == 0 ||
strcmp(argv[1],
"-?") == 0)
959 if (
strcmp(argv[1],
"--version") == 0 ||
strcmp(argv[1],
"-V") == 0)
970 private.timeline = 1;
974 private.endptr_reached =
false;
975 private.decoding_started =
false;
976 private.archive_name =
NULL;
977 private.start_segno = 0;
980 config.
quiet =
false;
995 config.
stats =
false;
1057 config.
quiet =
true;
1080 pg_log_error(
"custom resource manager \"%s\" does not exist",
1147 while (*endptr !=
'\0' &&
isspace((
unsigned char) *endptr))
1150 if (*endptr !=
'\0')
1153 optarg,
"-t/--timeline");
1164 private.timeline =
val;
1174 pg_log_error(
"invalid transaction ID specification: \"%s\"",
1181 config.
stats =
true;
1206 pg_log_error(
"option %s requires option %s to be specified",
1207 "-B/--block",
"-R/--relation");
1213 pg_log_error(
"too many command-line arguments (first is \"%s\")",
1248 if (
private.archive_name)
1250 pg_log_error(
"unnecessary command-line arguments specified with tar archive (first is \"%s\")",
1267 private.archive_dir =
waldir;
1268 private.archive_name = fname;
1275 pg_fatal(
"could not open file \"%s\"", fname);
1283 else if (!
XLByteInSeg(
private.startptr, segno,
private.segsize))
1285 pg_log_error(
"start WAL location %X/%08X is not inside file \"%s\"",
1305 pg_fatal(
"could not open file \"%s\"", fname);
1312 pg_fatal(
"ENDSEG %s is before STARTSEG %s",
1323 if (!
XLByteInSeg(
private.endptr, segno,
private.segsize) &&
1324 private.endptr != (segno + 1) *
private.segsize)
1326 pg_log_error(
"end WAL location %X/%08X is not inside file \"%s\"",
1333 else if (!
private.archive_name)
1344 if (config.
follow &&
private.archive_name)
1346 pg_log_error(
"--follow is not supported when reading from a tar archive");
1353 if (
private.archive_name)
1359 if (
private.archive_dir ==
NULL)
1384 pg_fatal(
"out of memory while allocating a WAL reading processor");
1390 pg_fatal(
"could not find a valid record after %X/%08X",
1401 "first record is after %X/%08X, at %X/%08X, skipping over %u bytes",
1411 private.decoding_started =
true;
1425 if (!config.
follow ||
private.endptr_reached)
1461 if (config.
stats ==
true)
1488 pg_fatal(
"error in WAL record at %X/%08X: %s",
1494 if (
private.archive_name)
int read_archive_wal_page(XLogDumpPrivate *privateInfo, XLogRecPtr targetPagePtr, Size count, char *readBuff)
void free_archive_reader(XLogDumpPrivate *privateInfo)
void free_archive_wal_entry(const char *fname, XLogDumpPrivate *privateInfo)
void init_archive_reader(XLogDumpPrivate *privateInfo, pg_compress_algorithm compression)
#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)
bool parse_tar_compress_algorithm(const char *fname, pg_compress_algorithm *algorithm)
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 void XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
static void TarWALDumpCloseSegment(XLogReaderState *state)
static void WALDumpCloseSegment(XLogReaderState *state)
static volatile sig_atomic_t time_to_stop
static void split_path(const char *path, char **dir, char **fname)
static int required_read_len(XLogDumpPrivate *private, XLogRecPtr targetPagePtr, int reqLen)
int open_file_in_directory(const char *directory, const char *fname)
static bool search_directory(const char *directory, const char *fname, int *WalSegSz)
static char * identify_target_directory(char *directory, char *fname, int *WalSegSz)
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 void TarWALDumpOpenSegment(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
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 int TarWALDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetPtr, char *readBuff)
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)
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
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