diff --git a/src/bin/pg_waldump/archive_waldump.c b/src/bin/pg_waldump/archive_waldump.c index 547a5154cb6..c93e02ece8b 100644 --- a/src/bin/pg_waldump/archive_waldump.c +++ b/src/bin/pg_waldump/archive_waldump.c @@ -53,7 +53,7 @@ char *TmpWalSegDir = NULL; * * To minimize the memory footprint, entries and their associated buffers are * freed immediately once consumed. Since pg_waldump does not request the same - * bytes twice, a segment is discarded as soon as it moves past it. + * bytes twice, a segment is discarded as soon as pg_waldump moves past it. */ typedef struct ArchivedWALFile { @@ -142,10 +142,10 @@ init_archive_reader(XLogDumpPrivate *privateInfo, const char *waldir, streamer = astreamer_waldump_new(privateInfo); - /* Before that we must parse the tar archive. */ + /* We must first parse the tar archive. */ streamer = astreamer_tar_parser_new(streamer); - /* Before that we must decompress, if archive is compressed. */ + /* If the archive is compressed, decompress before parsing. */ if (compression == PG_COMPRESSION_GZIP) streamer = astreamer_gzip_decompressor_new(streamer); else if (compression == PG_COMPRESSION_LZ4) @@ -243,6 +243,23 @@ free_archive_reader(XLogDumpPrivate *privateInfo) */ astreamer_free(privateInfo->archive_streamer); + /* Free any remaining hash table entries and their buffers. */ + if (privateInfo->archive_wal_htab != NULL) + { + ArchivedWAL_iterator iter; + ArchivedWALFile *entry; + + ArchivedWAL_start_iterate(privateInfo->archive_wal_htab, &iter); + while ((entry = ArchivedWAL_iterate(privateInfo->archive_wal_htab, + &iter)) != NULL) + { + if (entry->buf != NULL) + destroyStringInfo(entry->buf); + } + ArchivedWAL_destroy(privateInfo->archive_wal_htab); + privateInfo->archive_wal_htab = NULL; + } + /* Free the reusable read buffer. */ if (privateInfo->archive_read_buf != NULL) { @@ -350,16 +367,21 @@ read_archive_wal_page(XLogDumpPrivate *privateInfo, XLogRecPtr targetPagePtr, } /* - * Now, fetch more data; raise an error if it's not the current - * segment being read by the archive streamer or if reading of the - * archived file has finished. + * Now, fetch more data. Raise an error if the archive + * streamer has moved past our segment (meaning the WAL file + * in the archive is shorter than expected) or if reading the + * archive reached EOF. */ - if (privateInfo->cur_file != entry || - read_archive_file(privateInfo, READ_CHUNK_SIZE) == 0) - pg_fatal("could not read file \"%s\" from archive \"%s\": read %lld of %lld", + if (privateInfo->cur_file != entry) + pg_fatal("WAL segment \"%s\" in archive \"%s\" is too short: read %lld of %lld bytes", fname, privateInfo->archive_name, (long long int) (count - nbytes), (long long int) count); + if (read_archive_file(privateInfo, READ_CHUNK_SIZE) == 0) + pg_fatal("unexpected end of archive \"%s\" while reading \"%s\": read %lld of %lld bytes", + privateInfo->archive_name, fname, + (long long int) (count - nbytes), + (long long int) count); } } @@ -736,7 +758,7 @@ astreamer_waldump_finalize(astreamer *streamer) } /* - * Free memory associated with a astreamer_waldump stream. + * Free memory associated with an astreamer_waldump stream. */ static void astreamer_waldump_free(astreamer *streamer) diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c index e970b007883..b13cedaa3e7 100644 --- a/src/bin/pg_waldump/pg_waldump.c +++ b/src/bin/pg_waldump/pg_waldump.c @@ -874,7 +874,7 @@ usage(void) printf(_(" -F, --fork=FORK only show records that modify blocks in fork FORK;\n" " valid names are main, fsm, vm, init\n")); printf(_(" -n, --limit=N number of records to display\n")); - printf(_(" -p, --path=PATH tar archive or a directory in which to find WAL segment files or\n" + printf(_(" -p, --path=PATH a tar archive or a directory in which to find WAL segment files or\n" " a directory with a ./pg_wal that contains such files\n" " (default: current directory, ./pg_wal, $PGDATA/pg_wal)\n")); printf(_(" -q, --quiet do not print any output, except for errors\n")); @@ -1338,6 +1338,13 @@ main(int argc, char **argv) goto bad_argument; } + /* --follow is not supported with tar archives */ + if (config.follow && private.archive_name) + { + pg_log_error("--follow is not supported when reading from a tar archive"); + goto bad_argument; + } + /* done with argument parsing, do the actual work */ /* we have everything we need, start reading */ diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index d849293e6fa..b7b78e2c958 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -147,6 +147,7 @@ ArchiveStartupCB ArchiveStreamState ArchivedWALFile ArchivedWAL_hash +ArchivedWAL_iterator ArchiverOutput ArchiverStage ArrayAnalyzeExtraData