Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search archives
  Advanced Search

Re: [HACKERS] What's left?


  • From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
  • To: PostgreSQL Win32 port list <pgsql-hackers-win32(at)postgresql(dot)org>
  • Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Claudio Natoli <claudio(dot)natoli(at)memetrics(dot)com>, "''Merlin Moncure' '" <merlin(dot)moncure(at)rcsonline(dot)com>, PostgreSQL-patches <pgsql-patches(at)postgresql(dot)org>
  • Subject: Re: [HACKERS] What's left?
  • Date: Mon, 26 Jan 2004 23:01:43 -0500 (EST)
  • Message-id: <200401270401.i0R41h325617@candle.pha.pa.us> <text/plain>

Bruce Momjian wrote:
> Tom Lane wrote:
> > Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us> writes:
> > > In this way, no one ever has the rename file open while we are holding
> > > the locks, and we can loop without holding an exclusive lock on
> > > pg_shadow, and file writes remain in order.
> > 
> > You're doing this where exactly, and are certain that you are holding no
> > locks why exactly?  And if you aren't holding a lock, what prevents
> > concurrency bugs?
> 
> Oh, for concurrency bugs, you make realfile.new while holding the
> exclusive lock, so someone could come in later and replace realfile.new
> while I am in the rename loop, but then I just install theirs instead.
> 
> I could install someone who has just done the rename to realfile.new but
> not tried the rename from realfile.new to realfile, but that seems OK. 
> They will just fine the file missing and fail on the rename, which is
> OK.

OK, here is a patch that I think handles rename.  It does the rename to
a secondary file while holding the lock, then releases the lock and does
a rename to the active file.  I enabled this for Win32 and Cygwin, which
has the same file system behavior.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman(at)candle(dot)pha(dot)pa(dot)us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/commands/user.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/commands/user.c,v
retrieving revision 1.133
diff -c -c -r1.133 user.c
*** src/backend/commands/user.c	26 Jan 2004 22:35:32 -0000	1.133
--- src/backend/commands/user.c	27 Jan 2004 03:46:00 -0000
***************
*** 139,145 ****
  	bufsize = strlen(filename) + 12;
  	tempname = (char *) palloc(bufsize);
  	snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
! 
  	oumask = umask((mode_t) 077);
  	fp = AllocateFile(tempname, "w");
  	umask(oumask);
--- 139,149 ----
  	bufsize = strlen(filename) + 12;
  	tempname = (char *) palloc(bufsize);
  	snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
! #if defined(WIN32) || defined(CYGWIN)
! 	filename = repalloc(filename, strlen(filename) + 1 + strlen(".new");
! 	strcat(filename, ".new");
! #endif
! 	
  	oumask = umask((mode_t) 077);
  	fp = AllocateFile(tempname, "w");
  	umask(oumask);
***************
*** 286,291 ****
--- 290,299 ----
  	bufsize = strlen(filename) + 12;
  	tempname = (char *) palloc(bufsize);
  	snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid);
+ #if defined(WIN32) || defined(CYGWIN)
+ 	filename = repalloc(filename, strlen(filename) + 1 + strlen(".new");
+ 	strcat(filename, ".new");
+ #endif
  
  	oumask = umask((mode_t) 077);
  	fp = AllocateFile(tempname, "w");
***************
*** 457,462 ****
--- 465,482 ----
  		user_file_update_needed = false;
  		write_user_file(urel);
  		heap_close(urel, NoLock);
+ #if defined(WIN32) || defined(CYGWIN)
+ 		{
+ 			/* Rename active file while not holding an exclusive lock */
+ 			char *filename = user_getfilename(), *filename_new;
+ 
+ 			filename_new = palloc(strlen(filename) + 1 + strlen(".new")));
+ 			sprintf(filename_new, "%s.new", filename);
+ 			rename(filename_new, filename);
+ 			pfree(filename);
+ 			pfree(filename_new);
+ 		}
+ #endif
  	}
  
  	if (group_file_update_needed)
***************
*** 464,469 ****
--- 484,501 ----
  		group_file_update_needed = false;
  		write_group_file(grel);
  		heap_close(grel, NoLock);
+ #if defined(WIN32) || defined(CYGWIN)
+ 		{
+ 			/* Rename active file while not holding an exclusive lock */
+ 			char *filename = group_getfilename(), *filename_new;
+ 
+ 			filename_new = palloc(strlen(filename) + 1 + strlen(".new")));
+ 			sprintf(filename_new, "%s.new", filename);
+ 			rename(filename_new, filename);
+ 			pfree(filename);
+ 			pfree(filename_new);
+ 		}
+ #endif
  	}
  
  	/*
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/cache/relcache.c,v
retrieving revision 1.195
diff -c -c -r1.195 relcache.c
*** src/backend/utils/cache/relcache.c	26 Jan 2004 22:35:32 -0000	1.195
--- src/backend/utils/cache/relcache.c	27 Jan 2004 03:46:04 -0000
***************
*** 3358,3390 ****
  		/*
  		 * OK, rename the temp file to its final name, deleting any
  		 * previously-existing init file.
- 		 *
- 		 * Note: a failure here is possible under Cygwin, if some other
- 		 * backend is holding open an unlinked-but-not-yet-gone init file.
- 		 * So treat this as a noncritical failure.
  		 */
! 		if (rename(tempfilename, finalfilename) < 0)
  		{
! 			ereport(WARNING,
! 					(errcode_for_file_access(),
! 				errmsg("could not rename relation-cache initialization file \"%s\" to \"%s\": %m",
! 					   tempfilename, finalfilename),
! 					 errdetail("Continuing anyway, but there's something wrong.")));
! 
! 			/*
! 			 * If we fail, try to clean up the useless temp file; don't
! 			 * bother to complain if this fails too.
! 			 */
! 			unlink(tempfilename);
  		}
  	}
  	else
  	{
  		/* Delete the already-obsolete temp file */
  		unlink(tempfilename);
  	}
- 
- 	LWLockRelease(RelCacheInitLock);
  }
  
  /*
--- 3358,3385 ----
  		/*
  		 * OK, rename the temp file to its final name, deleting any
  		 * previously-existing init file.
  		 */
! #if defined(WIN32) || defined(CYGWIN)
! 		rename(tempfilename, finalfilename);
! 		LWLockRelease(RelCacheInitLock);
! #else
  		{
! 			char		finalfilename_new[MAXPGPATH];
! 	
! 			snprintf(finalfilename_new, sizeof(finalfilename_new), "%s.new", finalfilename);
! 			rename(tempfilename, finalfilename_new);
! 			LWLockRelease(RelCacheInitLock);
! 			/* Rename to active file after lock is released */
! 			rename(finalfilename_new, finalfilename);
  		}
+ #endif
  	}
  	else
  	{
  		/* Delete the already-obsolete temp file */
  		unlink(tempfilename);
+ 		LWLockRelease(RelCacheInitLock);
  	}
  }
  
  /*
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.181
diff -c -c -r1.181 guc.c
*** src/backend/utils/misc/guc.c	26 Jan 2004 22:35:32 -0000	1.181
--- src/backend/utils/misc/guc.c	27 Jan 2004 03:46:07 -0000
***************
*** 3981,3987 ****
  		return;
  	}
  
! 	/* Put new file in place, this could delay on Win32 */
  	rename(new_filename, filename);
  	free(new_filename);
  	free(filename);
--- 3981,3990 ----
  		return;
  	}
  
! 	/*
! 	 *	Put new file in place.  This could delay on Win32, but we don't hold
! 	 *	any exclusive locks.
! 	 */
  	rename(new_filename, filename);
  	free(new_filename);
  	free(filename);
Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.15
diff -c -c -r1.15 port.h
*** src/include/port.h	29 Nov 2003 22:40:53 -0000	1.15
--- src/include/port.h	27 Jan 2004 03:46:07 -0000
***************
*** 30,40 ****
  extern off_t ftello(FILE *stream);
  #endif
  
! #ifdef WIN32
  /*
   * Win32 doesn't have reliable rename/unlink during concurrent access
   */
- #ifndef FRONTEND
  extern int	pgrename(const char *from, const char *to);
  extern int	pgunlink(const char *path);
  
--- 30,39 ----
  extern off_t ftello(FILE *stream);
  #endif
  
! #if !defined(FRONTEND) && (defined(WIN32) || defined(CYGWIN))
  /*
   * Win32 doesn't have reliable rename/unlink during concurrent access
   */
  extern int	pgrename(const char *from, const char *to);
  extern int	pgunlink(const char *path);
  
***************
*** 42,47 ****
--- 41,47 ----
  #define unlink(path)		pgunlink(path)
  #endif
  
+ #ifdef WIN32
  extern int	copydir(char *fromdir, char *todir);
  
  /* Last parameter not used */
Index: src/port/dirmod.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/dirmod.c,v
retrieving revision 1.8
diff -c -c -r1.8 dirmod.c
*** src/port/dirmod.c	29 Nov 2003 19:52:13 -0000	1.8
--- src/port/dirmod.c	27 Jan 2004 03:46:08 -0000
***************
*** 27,35 ****
--- 27,45 ----
  {
  	int			loops = 0;
  
+ #ifdef WIN32
  	while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
+ #endif
+ #ifdef CYGWIN
+ 	while (rename(from, to) < 0)
+ #endif
  	{
+ #ifdef WIN32
  		if (GetLastError() != ERROR_ACCESS_DENIED)
+ #endif
+ #ifdef CYGWIN
+ 		if (errno != EACCES)
+ #endif
  			/* set errno? */
  			return -1;
  		Sleep(100);				/* ms */


Home | Main Index | Thread Index

Privacy Policy | About PostgreSQL
Copyright © 1996 – 2012 PostgreSQL Global Development Group