From 9b5f9b8c99496fa9def940331a4445c0c2e38490 Mon Sep 17 00:00:00 2001 From: Grigory Smolkin Date: Thu, 4 Jul 2019 22:51:07 +0300 Subject: [PATCH] [Issue #90] Refactoring --- src/archive.c | 84 ++++++++++++++++++++++++---------------------- src/pg_probackup.h | 1 + 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/archive.c b/src/archive.c index 0360416f..45badcf0 100644 --- a/src/archive.c +++ b/src/archive.c @@ -143,10 +143,10 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress, char to_path_temp[MAXPGPATH]; int errno_temp; /* partial handling */ - int partial_timeout = 0; - int partial_size = 0; struct stat st; - bool partial_exists = false; + int partial_file_timeout = 0; + int partial_file_size = 0; + bool partial_file_exists = false; #ifdef HAVE_LIBZ char gz_to_path[MAXPGPATH]; @@ -186,7 +186,7 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress, gz_out = fio_gzopen(to_path_temp, PG_BINARY_W, instance_config.compress_level, FIO_BACKUP_HOST); if (gz_out == NULL) { - partial_exists = true; + partial_file_exists = true; elog(WARNING, "Cannot open destination temporary WAL file \"%s\": %s", to_path_temp, strerror(errno)); } @@ -199,47 +199,28 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress, out = fio_open(to_path_temp, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, FIO_BACKUP_HOST); if (out < 0) { - partial_exists = true; + partial_file_exists = true; elog(WARNING, "Cannot open destination temporary WAL file \"%s\": %s", to_path_temp, strerror(errno)); } } - /* sleep a second, check if .partial file size is changing, if not, then goto p1 - * Algorihtm is not pretty however we do not expect conflict for '.partial' file - * to be frequent occurrence. - * The main goal is to protect against failed archive-push which left behind - * orphan '.partial' file. + /* Partial file is already exists, it could have happened due to failed archive-push, + * in this case partial file can be discarded, or due to concurrent archiving. + * + * Our main goal here is to try to handle partial file to prevent stalling of + * continious archiving. + * To ensure that ecncountered partial file is actually a stale "orphaned" file, + * check its size every second. + * If the size has not changed in PARTIAL_WAL_TIMER seconds, we can consider + * the file stale and reuse it. + * If file size is changing, it means that another archiver works at the same + * directory with the same files. Such partial files cannot be reused. */ - if (partial_exists) + if (partial_file_exists) { - while (1) + while (partial_file_timeout < PARTIAL_WAL_TIMER) { - /* exit from loop */ - if (partial_timeout > 10) - { - /* For 10 second the file didn`t changed its size, so consider it stale and reuse it */ - elog(WARNING, "Reusing stale destination temporary WAL file \"%s\"", to_path_temp); - fio_unlink(to_path_temp, FIO_BACKUP_HOST); - -#ifdef HAVE_LIBZ - if (is_compress) - { - gz_out = fio_gzopen(to_path_temp, PG_BINARY_W, instance_config.compress_level, FIO_BACKUP_HOST); - if (gz_out == NULL) - elog(ERROR, "Cannot open destination temporary WAL file \"%s\": %s", - to_path_temp, strerror(errno)); - } - else -#endif - { - out = fio_open(to_path_temp, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, FIO_BACKUP_HOST); - if (out < 0) - elog(ERROR, "Cannot open destination temporary WAL file \"%s\": %s", - to_path_temp, strerror(errno)); - } - break; - } if (fio_stat(to_path_temp, &st, false, FIO_BACKUP_HOST) < 0) /* It is ok if partial is gone, we can safely error out */ @@ -247,15 +228,36 @@ push_wal_file(const char *from_path, const char *to_path, bool is_compress, strerror(errno)); /* first round */ - if (!partial_timeout) - partial_size = st.st_size; + if (!partial_file_timeout) + partial_file_size = st.st_size; /* file size is changing */ - if (st.st_size > partial_size) + if (st.st_size > partial_file_size) elog(ERROR, "Destination temporary WAL file \"%s\" is not stale", to_path_temp); sleep(1); - partial_timeout++; + partial_file_timeout++; + } + + /* Partial segment is considered stale, so reuse it */ + elog(WARNING, "Reusing stale destination temporary WAL file \"%s\"", to_path_temp); + fio_unlink(to_path_temp, FIO_BACKUP_HOST); + +#ifdef HAVE_LIBZ + if (is_compress) + { + gz_out = fio_gzopen(to_path_temp, PG_BINARY_W, instance_config.compress_level, FIO_BACKUP_HOST); + if (gz_out == NULL) + elog(ERROR, "Cannot open destination temporary WAL file \"%s\": %s", + to_path_temp, strerror(errno)); + } + else +#endif + { + out = fio_open(to_path_temp, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, FIO_BACKUP_HOST); + if (out < 0) + elog(ERROR, "Cannot open destination temporary WAL file \"%s\": %s", + to_path_temp, strerror(errno)); } } diff --git a/src/pg_probackup.h b/src/pg_probackup.h index 000b9acb..66b814b7 100644 --- a/src/pg_probackup.h +++ b/src/pg_probackup.h @@ -63,6 +63,7 @@ extern const char *PROGRAM_EMAIL; #define EXTERNAL_DIR "external_directories/externaldir" /* Timeout defaults */ +#define PARTIAL_WAL_TIMER 60 #define ARCHIVE_TIMEOUT_DEFAULT 300 #define REPLICA_TIMEOUT_DEFAULT 300