diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/pg_basebackup/pg_receivexlog.c | 74 | ||||
-rw-r--r-- | src/bin/pg_basebackup/receivelog.c | 7 |
2 files changed, 52 insertions, 29 deletions
diff --git a/src/bin/pg_basebackup/pg_receivexlog.c b/src/bin/pg_basebackup/pg_receivexlog.c index 787a3951bda..031ec1aa97c 100644 --- a/src/bin/pg_basebackup/pg_receivexlog.c +++ b/src/bin/pg_basebackup/pg_receivexlog.c @@ -121,6 +121,7 @@ FindStreamingStart(uint32 *tli) struct dirent *dirent; XLogSegNo high_segno = 0; uint32 high_tli = 0; + bool high_ispartial = false; dir = opendir(basedir); if (dir == NULL) @@ -132,20 +133,32 @@ FindStreamingStart(uint32 *tli) while ((dirent = readdir(dir)) != NULL) { - char fullpath[MAXPGPATH]; - struct stat statbuf; uint32 tli; unsigned int log, seg; XLogSegNo segno; + bool ispartial; /* * Check if the filename looks like an xlog file, or a .partial file. * Xlog files are always 24 characters, and .partial files are 32 * characters. */ - if (strlen(dirent->d_name) != 24 || - strspn(dirent->d_name, "0123456789ABCDEF") != 24) + if (strlen(dirent->d_name) == 24) + { + if (strspn(dirent->d_name, "0123456789ABCDEF") != 24) + continue; + ispartial = false; + } + else if (strlen(dirent->d_name) == 32) + { + if (strspn(dirent->d_name, "0123456789ABCDEF") != 24) + continue; + if (strcmp(&dirent->d_name[24], ".partial") != 0) + continue; + ispartial = true; + } + else continue; /* @@ -160,31 +173,40 @@ FindStreamingStart(uint32 *tli) } segno = ((uint64) log) << 32 | seg; - /* Check if this is a completed segment or not */ - snprintf(fullpath, sizeof(fullpath), "%s/%s", basedir, dirent->d_name); - if (stat(fullpath, &statbuf) != 0) + /* + * Check that the segment has the right size, if it's supposed to be + * completed. + */ + if (!ispartial) { - fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"), - progname, fullpath, strerror(errno)); - disconnect_and_exit(1); - } + struct stat statbuf; + char fullpath[MAXPGPATH]; - if (statbuf.st_size == XLOG_SEG_SIZE) - { - /* Completed segment */ - if (segno > high_segno || (segno == high_segno && tli > high_tli)) + snprintf(fullpath, sizeof(fullpath), "%s/%s", basedir, dirent->d_name); + if (stat(fullpath, &statbuf) != 0) + { + fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"), + progname, fullpath, strerror(errno)); + disconnect_and_exit(1); + } + + if (statbuf.st_size != XLOG_SEG_SIZE) { - high_segno = segno; - high_tli = tli; + fprintf(stderr, + _("%s: segment file \"%s\" has incorrect size %d, skipping\n"), + progname, dirent->d_name, (int) statbuf.st_size); continue; } } - else + + /* Looks like a valid segment. Remember that we saw it. */ + if ((segno > high_segno) || + (segno == high_segno && tli > high_tli) || + (segno == high_segno && tli == high_tli && high_ispartial && !ispartial)) { - fprintf(stderr, - _("%s: segment file \"%s\" has incorrect size %d, skipping\n"), - progname, dirent->d_name, (int) statbuf.st_size); - continue; + high_segno = segno; + high_tli = tli; + high_ispartial = ispartial; } } @@ -195,10 +217,12 @@ FindStreamingStart(uint32 *tli) XLogRecPtr high_ptr; /* - * Move the starting pointer to the start of the next segment, since - * the highest one we've seen was completed. + * Move the starting pointer to the start of the next segment, if + * the highest one we saw was completed. Otherwise start streaming + * from the beginning of the .partial segment. */ - high_segno++; + if (!high_ispartial) + high_segno++; XLogSegNoOffsetToRecPtr(high_segno, 0, high_ptr); diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c index d56a4d71ea2..02643eaea94 100644 --- a/src/bin/pg_basebackup/receivelog.c +++ b/src/bin/pg_basebackup/receivelog.c @@ -166,8 +166,7 @@ close_walfile(char *basedir, char *partial_suffix) walfile = -1; /* - * Rename the .partial file only if we've completed writing the whole - * segment or segment_complete is true. + * If we finished writing a .partial file, rename it into place. */ if (currpos == XLOG_SEG_SIZE && partial_suffix) { @@ -306,6 +305,8 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co return false; } + snprintf(path, sizeof(path), "%s/%s", basedir, histfname); + /* * Write into a temp file name. */ @@ -356,8 +357,6 @@ writeTimeLineHistoryFile(char *basedir, TimeLineID tli, char *filename, char *co /* * Now move the completed history file into place with its final name. */ - - snprintf(path, sizeof(path), "%s/%s", basedir, histfname); if (rename(tmppath, path) < 0) { fprintf(stderr, _("%s: could not rename file \"%s\" to \"%s\": %s\n"), |