* 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 $
  *
  *-------------------------------------------------------------------------
  */
                                                                *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;
 
                   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;
 }
 
  * 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,
         */
 #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
 
                                         */
                                        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++;
                                }
 
 
  *     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 $
  *
  *-------------------------------------------------------------------------
  */
         * 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))
 #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 */
        }
         * 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 */
        }