Change Windows rename and unlink substitutes so that they time out after

30 seconds instead of retrying forever.  Also modify xlog.c so that if
it fails to rename an old xlog segment up to a future slot, it will
unlink the segment instead.  Per discussion of bug #2712, in which it
became apparent that Windows can handle unlinking a file that's being
held open, but not renaming it.
This commit is contained in:
Tom Lane 2006-11-08 20:12:05 +00:00
parent 808b3190d1
commit dcbdf9b1d4
2 changed files with 39 additions and 50 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.253 2006/11/05 22:42:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.254 2006/11/08 20:12:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2140,7 +2140,9 @@ XLogFileCopy(uint32 log, uint32 seg,
* caller must *not* hold the lock at call.
*
* Returns TRUE if file installed, FALSE if not installed because of
* exceeding max_advance limit. (Any other kind of failure causes ereport().)
* 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().)
*/
static bool
InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
@ -2195,10 +2197,25 @@ InstallXLogFileSegment(uint32 *log, uint32 *seg, char *tmppath,
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,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\" (initialization of log file %u, segment %u): %m",
tmppath, path, *log, *seg)));
}
#endif
if (use_lock)

View File

@ -10,7 +10,7 @@
* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.43 2006/07/18 22:36:46 tgl Exp $
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.44 2006/11/08 20:12:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -117,43 +117,28 @@ pgrename(const char *from, const char *to)
int loops = 0;
/*
* We need these loops because even though PostgreSQL uses flags that
* We need to loop because even though PostgreSQL uses flags that
* allow rename while the file is open, other applications might have
* these files open without those flags.
* the file open without those flags. However, we won't wait
* indefinitely for someone else to close the file.
*/
#if defined(WIN32) && !defined(__CYGWIN__)
while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
#else
while (rename(from, to) < 0)
#endif
#ifdef __CYGWIN__
while (rename(from, to) < 0)
#endif
{
{
#if defined(WIN32) && !defined(__CYGWIN__)
if (GetLastError() != ERROR_ACCESS_DENIED)
#endif
#ifdef __CYGWIN__
if (errno != EACCES)
#endif
/* set errno? */
return -1;
pg_usleep(100000); /* us */
if (loops == 30)
#ifndef FRONTEND
elog(LOG, "could not rename file \"%s\" to \"%s\", continuing to try",
from, to);
if (GetLastError() != ERROR_ACCESS_DENIED)
#else
fprintf(stderr, _("could not rename file \"%s\" to \"%s\", continuing to try\n"),
from, to);
#endif
loops++;
}
if (loops > 30)
#ifndef FRONTEND
elog(LOG, "completed rename of file \"%s\" to \"%s\"", from, to);
#else
fprintf(stderr, _("completed rename of file \"%s\" to \"%s\"\n"), from, to);
if (errno != EACCES)
#endif
/* set errno? */
return -1;
if (++loops > 300) /* time out after 30 sec */
return -1;
pg_usleep(100000); /* us */
}
return 0;
}
@ -167,33 +152,20 @@ pgunlink(const char *path)
int loops = 0;
/*
* We need these loops because even though PostgreSQL uses flags that
* We need to loop because even though PostgreSQL uses flags that
* allow unlink while the file is open, other applications might have
* these files open without those flags.
* the file open without those flags. However, we won't wait
* indefinitely for someone else to close the file.
*/
while (unlink(path))
{
if (errno != EACCES)
/* set errno? */
return -1;
if (++loops > 300) /* time out after 30 sec */
return -1;
pg_usleep(100000); /* us */
if (loops == 30)
#ifndef FRONTEND
elog(LOG, "could not remove file \"%s\", continuing to try",
path);
#else
fprintf(stderr, _("could not remove file \"%s\", continuing to try\n"),
path);
#endif
loops++;
}
if (loops > 30)
#ifndef FRONTEND
elog(LOG, "completed removal of file \"%s\"", path);
#else
fprintf(stderr, _("completed removal of file \"%s\"\n"), path);
#endif
return 0;
}