aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/transam/xlog.c56
-rw-r--r--src/port/dirmod.c34
2 files changed, 55 insertions, 35 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 53ded25ed01..331809a3b91 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.352 2009/09/10 09:42:10 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.353 2009/09/13 18:32:07 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2262,12 +2262,14 @@ XLogFileInit(uint32 log, uint32 seg,
*use_existent, &max_advance,
use_lock))
{
- /* No need for any more future segments... */
+ /*
+ * No need for any more future segments, or InstallXLogFileSegment()
+ * failed to rename the file into place. If the rename failed, opening
+ * the file below will fail.
+ */
unlink(tmppath);
}
- elog(DEBUG2, "done creating and filling new WAL file");
-
/* Set flag to tell caller there was no existent file */
*use_existent = false;
@@ -2280,6 +2282,8 @@ XLogFileInit(uint32 log, uint32 seg,
errmsg("could not open file \"%s\" (log file %u, segment %u): %m",
path, log, seg)));
+ elog(DEBUG2, "done creating and filling new WAL file");
+
return fd;
}
@@ -2409,10 +2413,9 @@ XLogFileCopy(uint32 log, uint32 seg,
* place. This should be TRUE except during bootstrap log creation. The
* caller must *not* hold the lock at call.
*
- * Returns TRUE if file installed, FALSE if not installed because of
- * exceeding max_advance limit. On Windows, we also return FALSE if we
- * can't rename the file into place because someone's got it open.
- * (Any other kind of failure causes ereport().)
+ * Returns TRUE if the file was installed successfully. FALSE indicates that
+ * max_advance limit was exceeded, or an error occurred while renaming the
+ * file into place.
*/
static bool
InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
@@ -2460,31 +2463,26 @@ InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
*/
#if HAVE_WORKING_LINK
if (link(tmppath, path) < 0)
- ereport(ERROR,
+ {
+ if (use_lock)
+ LWLockRelease(ControlFileLock);
+ ereport(LOG,
(errcode_for_file_access(),
errmsg("could not link file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
tmppath, path, *log, *seg)));
+ return false;
+ }
unlink(tmppath);
#else
if (rename(tmppath, path) < 0)
{
-#ifdef WIN32
-#if !defined(__CYGWIN__)
- if (GetLastError() == ERROR_ACCESS_DENIED)
-#else
- if (errno == EACCES)
-#endif
- {
- if (use_lock)
- LWLockRelease(ControlFileLock);
- return false;
- }
-#endif /* WIN32 */
-
- ereport(ERROR,
+ if (use_lock)
+ LWLockRelease(ControlFileLock);
+ ereport(LOG,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
tmppath, path, *log, *seg)));
+ return false;
}
#endif
@@ -3128,19 +3126,25 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
*/
snprintf(newpath, MAXPGPATH, "%s.deleted", path);
if (rename(path, newpath) != 0)
- ereport(ERROR,
+ {
+ ereport(LOG,
(errcode_for_file_access(),
- errmsg("could not rename old transaction log file \"%s\"",
+ errmsg("could not rename old transaction log file \"%s\": %m",
path)));
+ continue;
+ }
rc = unlink(newpath);
#else
rc = unlink(path);
#endif
if (rc != 0)
- ereport(ERROR,
+ {
+ ereport(LOG,
(errcode_for_file_access(),
errmsg("could not remove old transaction log file \"%s\": %m",
path)));
+ continue;
+ }
CheckpointStats.ckpt_segs_removed++;
}
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index a31e74cbd31..27b70644c47 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -10,7 +10,7 @@
* Win32 (NT4 and newer).
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.58 2009/06/11 14:49:15 momjian Exp $
+ * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.59 2009/09/13 18:32:08 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -120,7 +120,8 @@ pgrename(const char *from, const char *to)
* We need to loop because even though PostgreSQL uses flags that allow
* rename while the file is open, other applications might have the file
* open without those flags. However, we won't wait indefinitely for
- * someone else to close the file.
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
*/
#if defined(WIN32) && !defined(__CYGWIN__)
while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
@@ -129,13 +130,28 @@ pgrename(const char *from, const char *to)
#endif
{
#if defined(WIN32) && !defined(__CYGWIN__)
- if (GetLastError() != ERROR_ACCESS_DENIED)
+ DWORD err = GetLastError();
+
+ _dosmaperr(err);
+
+ /*
+ * Modern NT-based Windows versions return ERROR_SHARING_VIOLATION
+ * if another process has the file open without FILE_SHARE_DELETE.
+ * ERROR_LOCK_VIOLATION has also been seen with some anti-virus
+ * software. This used to check for just ERROR_ACCESS_DENIED, so
+ * presumably you can get that too with some OS versions. We don't
+ * expect real permission errors where we currently use rename().
+ */
+ if (err != ERROR_ACCESS_DENIED &&
+ err != ERROR_SHARING_VIOLATION &&
+ err != ERROR_LOCK_VIOLATION)
+ return -1;
#else
if (errno != EACCES)
-#endif
- /* set errno? */
return -1;
- if (++loops > 300) /* time out after 30 sec */
+#endif
+
+ if (++loops > 100) /* time out after 10 sec */
return -1;
pg_usleep(100000); /* us */
}
@@ -155,14 +171,14 @@ pgunlink(const char *path)
* We need to loop because even though PostgreSQL uses flags that allow
* unlink while the file is open, other applications might have the file
* open without those flags. However, we won't wait indefinitely for
- * someone else to close the file.
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
*/
while (unlink(path))
{
if (errno != EACCES)
- /* set errno? */
return -1;
- if (++loops > 300) /* time out after 30 sec */
+ if (++loops > 100) /* time out after 10 sec */
return -1;
pg_usleep(100000); /* us */
}