diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c index 2fd16421aa..6d085c2412 100644 --- a/src/bin/pg_basebackup/receivelog.c +++ b/src/bin/pg_basebackup/receivelog.c @@ -92,26 +92,29 @@ static bool open_walfile(StreamCtl *stream, XLogRecPtr startpoint) { Walfile *f; - char fn[MAXPGPATH]; + char *fn; ssize_t size; XLogSegNo segno; XLByteToSeg(startpoint, segno, WalSegSz); XLogFileName(current_walfile_name, stream->timeline, segno, WalSegSz); - snprintf(fn, sizeof(fn), "%s%s", current_walfile_name, - stream->partial_suffix ? stream->partial_suffix : ""); + /* Note that this considers the compression used if necessary */ + fn = stream->walmethod->get_file_name(current_walfile_name, + stream->partial_suffix); /* * When streaming to files, if an existing file exists we verify that it's * either empty (just created), or a complete WalSegSz segment (in which * case it has been created and padded). Anything else indicates a corrupt - * file. + * file. Compressed files have no need for padding, so just ignore this + * case. * * When streaming to tar, no file with this name will exist before, so we * never have to verify a size. */ - if (stream->walmethod->existsfile(fn)) + if (stream->walmethod->compression() == 0 && + stream->walmethod->existsfile(fn)) { size = stream->walmethod->get_file_size(fn); if (size < 0) diff --git a/src/bin/pg_basebackup/walmethods.c b/src/bin/pg_basebackup/walmethods.c index 83b520898b..7779625af8 100644 --- a/src/bin/pg_basebackup/walmethods.c +++ b/src/bin/pg_basebackup/walmethods.c @@ -69,20 +69,32 @@ dir_getlasterror(void) return strerror(errno); } +static char * +dir_get_file_name(const char *pathname, const char *temp_suffix) +{ + char *filename = pg_malloc0(MAXPGPATH * sizeof(char)); + + snprintf(filename, MAXPGPATH, "%s%s%s", + pathname, dir_data->compression > 0 ? ".gz" : "", + temp_suffix ? temp_suffix : ""); + + return filename; +} + static Walfile dir_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size) { static char tmppath[MAXPGPATH]; + char *filename; int fd; DirectoryMethodFile *f; #ifdef HAVE_LIBZ gzFile gzfp = NULL; #endif - snprintf(tmppath, sizeof(tmppath), "%s/%s%s%s", - dir_data->basedir, pathname, - dir_data->compression > 0 ? ".gz" : "", - temp_suffix ? temp_suffix : ""); + filename = dir_get_file_name(pathname, temp_suffix); + snprintf(tmppath, sizeof(tmppath), "%s/%s", + dir_data->basedir, filename); /* * Open a file for non-compressed as well as compressed files. Tracking @@ -233,26 +245,31 @@ dir_close(Walfile f, WalCloseMethod method) /* Build path to the current version of the file */ if (method == CLOSE_NORMAL && df->temp_suffix) { + char *filename; + char *filename2; + /* * If we have a temp prefix, normal operation is to rename the * file. */ - snprintf(tmppath, sizeof(tmppath), "%s/%s%s%s", - dir_data->basedir, df->pathname, - dir_data->compression > 0 ? ".gz" : "", - df->temp_suffix); - snprintf(tmppath2, sizeof(tmppath2), "%s/%s%s", - dir_data->basedir, df->pathname, - dir_data->compression > 0 ? ".gz" : ""); + filename = dir_get_file_name(df->pathname, df->temp_suffix); + snprintf(tmppath, sizeof(tmppath), "%s/%s", + dir_data->basedir, filename); + + /* permanent name, so no need for the prefix */ + filename2 = dir_get_file_name(df->pathname, NULL); + snprintf(tmppath2, sizeof(tmppath2), "%s/%s", + dir_data->basedir, filename2); r = durable_rename(tmppath, tmppath2); } else if (method == CLOSE_UNLINK) { + char *filename; + /* Unlink the file once it's closed */ - snprintf(tmppath, sizeof(tmppath), "%s/%s%s%s", - dir_data->basedir, df->pathname, - dir_data->compression > 0 ? ".gz" : "", - df->temp_suffix ? df->temp_suffix : ""); + filename = dir_get_file_name(df->pathname, df->temp_suffix); + snprintf(tmppath, sizeof(tmppath), "%s/%s", + dir_data->basedir, filename); r = unlink(tmppath); } else @@ -314,6 +331,12 @@ dir_get_file_size(const char *pathname) return statbuf.st_size; } +static int +dir_compression(void) +{ + return dir_data->compression; +} + static bool dir_existsfile(const char *pathname) { @@ -356,6 +379,8 @@ CreateWalDirectoryMethod(const char *basedir, int compression, bool sync) method->write = dir_write; method->get_current_pos = dir_get_current_pos; method->get_file_size = dir_get_file_size; + method->get_file_name = dir_get_file_name; + method->compression = dir_compression; method->close = dir_close; method->sync = dir_sync; method->existsfile = dir_existsfile; @@ -528,11 +553,22 @@ tar_write_padding_data(TarMethodFile *f, size_t bytes) return true; } +static char * +tar_get_file_name(const char *pathname, const char *temp_suffix) +{ + char *filename = pg_malloc0(MAXPGPATH * sizeof(char)); + + snprintf(filename, MAXPGPATH, "%s%s", + pathname, temp_suffix ? temp_suffix : ""); + + return filename; +} + static Walfile tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_size) { int save_errno; - static char tmppath[MAXPGPATH]; + char *tmppath; tar_clear_error(); @@ -584,8 +620,7 @@ tar_open_for_write(const char *pathname, const char *temp_suffix, size_t pad_to_ tar_data->currentfile = pg_malloc0(sizeof(TarMethodFile)); - snprintf(tmppath, sizeof(tmppath), "%s%s", - pathname, temp_suffix ? temp_suffix : ""); + tmppath = tar_get_file_name(pathname, temp_suffix); /* Create a header with size set to 0 - we will fill out the size on close */ if (tarCreateHeader(tar_data->currentfile->header, tmppath, NULL, 0, S_IRUSR | S_IWUSR, 0, 0, time(NULL)) != TAR_OK) @@ -686,6 +721,12 @@ tar_get_file_size(const char *pathname) return -1; } +static int +tar_compression(void) +{ + return tar_data->compression; +} + static off_t tar_get_current_pos(Walfile f) { @@ -990,6 +1031,8 @@ CreateWalTarMethod(const char *tarbase, int compression, bool sync) method->write = tar_write; method->get_current_pos = tar_get_current_pos; method->get_file_size = tar_get_file_size; + method->get_file_name = tar_get_file_name; + method->compression = tar_compression; method->close = tar_close; method->sync = tar_sync; method->existsfile = tar_existsfile; diff --git a/src/bin/pg_basebackup/walmethods.h b/src/bin/pg_basebackup/walmethods.h index 94d0f6bc91..d1e2c834a6 100644 --- a/src/bin/pg_basebackup/walmethods.h +++ b/src/bin/pg_basebackup/walmethods.h @@ -52,6 +52,15 @@ struct WalWriteMethod /* Return the size of a file, or -1 on failure. */ ssize_t (*get_file_size) (const char *pathname); + /* + * Return the name of the current file to work on, without the base + * directory. This is useful for logging. + */ + char *(*get_file_name) (const char *pathname, const char *temp_suffix); + + /* Return the level of compression */ + int (*compression) (void); + /* * Write count number of bytes to the file, and return the number of bytes * actually written or -1 for error.