X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Faccess%2Ftransam%2Fxlogarchive.c;h=7afb73579b009444f9b7df658645ea3f2cf5e5f5;hb=c7b8998ebbf310a156aa38022555a24d98fdbfb4;hp=37745dce8902d41410c6ab9f044f6b4d91669d01;hpb=0a7832005792fa6dad171f9cadb8d587fe0dd800;p=postgresql diff --git a/src/backend/access/transam/xlogarchive.c b/src/backend/access/transam/xlogarchive.c index 37745dce89..7afb73579b 100644 --- a/src/backend/access/transam/xlogarchive.c +++ b/src/backend/access/transam/xlogarchive.c @@ -4,7 +4,7 @@ * Functions for archiving WAL files and restoring from the archive. * * - * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/backend/access/transam/xlogarchive.c @@ -14,7 +14,6 @@ #include "postgres.h" -#include #include #include #include @@ -421,7 +420,7 @@ ExecuteRecoveryCommand(char *command, char *commandName, bool failOnSignal) /* * A file was restored from the archive under a temporary filename (path), * and now we want to keep it. Rename it under the permanent filename in - * in pg_xlog (xlogfname), replacing any existing file with the same name. + * in pg_wal (xlogfname), replacing any existing file with the same name. */ void KeepFileRestoredFromArchive(char *path, char *xlogfname) @@ -459,7 +458,8 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname) xlogfpath, oldpath))); } #else - strncpy(oldpath, xlogfpath, MAXPGPATH); + /* same-size buffers, so this never truncates */ + strlcpy(oldpath, xlogfpath, MAXPGPATH); #endif if (unlink(oldpath) != 0) ereport(FATAL, @@ -469,17 +469,16 @@ KeepFileRestoredFromArchive(char *path, char *xlogfname) reload = true; } - if (rename(path, xlogfpath) < 0) - ereport(ERROR, - (errcode_for_file_access(), - errmsg("could not rename file \"%s\" to \"%s\": %m", - path, xlogfpath))); + durable_rename(path, xlogfpath, ERROR); /* * Create .done file forcibly to prevent the restored segment from being * archived again later. */ - XLogArchiveForceDone(xlogfname); + if (XLogArchiveMode != ARCHIVE_MODE_ALWAYS) + XLogArchiveForceDone(xlogfname); + else + XLogArchiveNotify(xlogfname); /* * If the existing file was replaced, since walsenders might have it open, @@ -576,12 +575,7 @@ XLogArchiveForceDone(const char *xlog) StatusFilePath(archiveReady, xlog, ".ready"); if (stat(archiveReady, &stat_buf) == 0) { - if (rename(archiveReady, archiveDone) < 0) - ereport(WARNING, - (errcode_for_file_access(), - errmsg("could not rename file \"%s\" to \"%s\": %m", - archiveReady, archiveDone))); - + (void) durable_rename(archiveReady, archiveDone, WARNING); return; } @@ -693,6 +687,60 @@ XLogArchiveIsBusy(const char *xlog) return true; } +/* + * XLogArchiveIsReadyOrDone + * + * Check to see if an XLOG segment file has a .ready or .done file. + * This is similar to XLogArchiveIsBusy(), but returns true if the file + * is already archived or is about to be archived. + * + * This is currently only used at recovery. During normal operation this + * would be racy: the file might get removed or marked with .ready as we're + * checking it, or immediately after we return. + */ +bool +XLogArchiveIsReadyOrDone(const char *xlog) +{ + char archiveStatusPath[MAXPGPATH]; + struct stat stat_buf; + + /* First check for .done --- this means archiver is done with it */ + StatusFilePath(archiveStatusPath, xlog, ".done"); + if (stat(archiveStatusPath, &stat_buf) == 0) + return true; + + /* check for .ready --- this means archiver is still busy with it */ + StatusFilePath(archiveStatusPath, xlog, ".ready"); + if (stat(archiveStatusPath, &stat_buf) == 0) + return true; + + /* Race condition --- maybe archiver just finished, so recheck */ + StatusFilePath(archiveStatusPath, xlog, ".done"); + if (stat(archiveStatusPath, &stat_buf) == 0) + return true; + + return false; +} + +/* + * XLogArchiveIsReady + * + * Check to see if an XLOG segment file has an archive notification (.ready) + * file. + */ +bool +XLogArchiveIsReady(const char *xlog) +{ + char archiveStatusPath[MAXPGPATH]; + struct stat stat_buf; + + StatusFilePath(archiveStatusPath, xlog, ".ready"); + if (stat(archiveStatusPath, &stat_buf) == 0) + return true; + + return false; +} + /* * XLogArchiveCleanup *