Re: [HACKERS] What's left? - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [HACKERS] What's left?
Date
Msg-id 200401270401.i0R41h325617@candle.pha.pa.us
Whole thread Raw
List pgsql-patches
Bruce Momjian wrote:
> Tom Lane wrote:
> > Bruce Momjian <pgman@candle.pha.pa.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@candle.pha.pa.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 */

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Win32 signals patch
Next
From: Brian Moore
Date:
Subject: support for printing/exporting xml