aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-09-10 09:42:29 +0000
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2009-09-10 09:42:29 +0000
commit96ca52dbe80a90d191eafbc656f03a33e85107a8 (patch)
tree7abe52808198309ad3873116a5ccb841d69bedbe
parent9ed9ac5a38431cf328088657c4c82b63e6326aab (diff)
downloadpostgresql-96ca52dbe80a90d191eafbc656f03a33e85107a8.tar.gz
postgresql-96ca52dbe80a90d191eafbc656f03a33e85107a8.zip
On Windows, when a file is deleted and another process still has an open
file handle on it, the file goes into "pending deletion" state where it still shows up in directory listing, but isn't accessible otherwise. That confuses RemoveOldXLogFiles(), making it think that the file hasn't been archived yet, while it actually was, and it was deleted along with the .done file. Fix that by renaming the file with ".deleted" extension before deleting it. Also check the return value of rename() and unlink(), so that if the removal fails for any reason (e.g another process is holding the file locked), we don't delete the .done file until the WAL file is really gone. Backpatch to 8.2, which is the oldest version supported on Windows.
-rw-r--r--src/backend/access/transam/xlog.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 022c1b20acd..56e6b8269e4 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.345.2.3 2009/08/27 07:18:04 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.345.2.4 2009/09/10 09:42:29 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3040,6 +3040,9 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
struct dirent *xlde;
char lastoff[MAXFNAMELEN];
char path[MAXPGPATH];
+#ifdef WIN32
+ char newpath[MAXPGPATH];
+#endif
struct stat statbuf;
/*
@@ -3103,10 +3106,41 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
else
{
/* No need for any more future segments... */
+ int rc;
+
ereport(DEBUG2,
(errmsg("removing transaction log file \"%s\"",
xlde->d_name)));
- unlink(path);
+
+#ifdef WIN32
+ /*
+ * On Windows, if another process (e.g another backend)
+ * holds the file open in FILE_SHARE_DELETE mode, unlink
+ * will succeed, but the file will still show up in
+ * directory listing until the last handle is closed.
+ * To avoid confusing the lingering deleted file for a
+ * live WAL file that needs to be archived, rename it
+ * before deleting it.
+ *
+ * If another process holds the file open without
+ * FILE_SHARE_DELETE flag, rename will fail. We'll try
+ * again at the next checkpoint.
+ */
+ snprintf(newpath, MAXPGPATH, "%s.deleted", path);
+ if (rename(path, newpath) != 0)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not rename old transaction log file \"%s\"",
+ path)));
+ rc = unlink(newpath);
+#else
+ rc = unlink(path);
+#endif
+ if (rc != 0)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not remove old transaction log file \"%s\": %m",
+ path)));
CheckpointStats.ckpt_segs_removed++;
}