Change ReleaseLruFile() usage so that if we cannot release any more
authorTom Lane
Sun, 27 Aug 2000 21:48:00 +0000 (21:48 +0000)
committerTom Lane
Sun, 27 Aug 2000 21:48:00 +0000 (21:48 +0000)
virtual FDs, we just return the ENFILE/EMFILE error to the caller,
rather than immediate elog().  This allows more robust behavior in
the postmaster, which uses AllocateFile() but does not want elog().

src/backend/storage/file/fd.c

index 6a4ecb63dc26ac53506a640e3265c8b4d0cb57b9..de6ca57ca1a65a7274cd63e278dc23ea4b46b1f5 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.62 2000/07/05 21:10:05 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.63 2000/08/27 21:48:00 tgl Exp $
  *
  * NOTES:
  *
@@ -182,7 +182,7 @@ static void Delete(File file);
 static void LruDelete(File file);
 static void Insert(File file);
 static int LruInsert(File file);
-static void ReleaseLruFile(void);
+static bool ReleaseLruFile(void);
 static File AllocateVfd(void);
 static void FreeVfd(File file);
 
@@ -230,13 +230,16 @@ tryAgain:
    if (fd >= 0)
        return fd;              /* success! */
 
-   if ((errno == EMFILE || errno == ENFILE) && nfile > 0)
+   if (errno == EMFILE || errno == ENFILE)
    {
+       int     save_errno = errno;
+
        DO_DB(elog(DEBUG, "BasicOpenFile: not enough descs, retry, er= %d",
                   errno));
        errno = 0;
-       ReleaseLruFile();
-       goto tryAgain;
+       if (ReleaseLruFile())
+           goto tryAgain;
+       errno = save_errno;
    }
 
    return -1;                  /* failure */
@@ -278,7 +281,7 @@ pg_nofile(void)
 #if defined(FDDEBUG)
 
 static void
-_dump_lru()
+_dump_lru(void)
 {
    int         mru = VfdCache[0].lruLessRecently;
    Vfd        *vfdP = &VfdCache[mru];
@@ -389,7 +392,10 @@ LruInsert(File file)
    if (FileIsNotOpen(file))
    {
        while (nfile + numAllocatedFiles >= pg_nofile())
-           ReleaseLruFile();
+       {
+           if (! ReleaseLruFile())
+               break;
+       }
 
        /*
         * The open could still fail for lack of file descriptors, eg due
@@ -400,8 +406,7 @@ LruInsert(File file)
                                 vfdP->fileMode);
        if (vfdP->fd < 0)
        {
-           DO_DB(elog(DEBUG, "RE_OPEN FAILED: %d",
-                      errno));
+           DO_DB(elog(DEBUG, "RE_OPEN FAILED: %d", errno));
            return vfdP->fd;
        }
        else
@@ -427,24 +432,26 @@ LruInsert(File file)
    return 0;
 }
 
-static void
-ReleaseLruFile()
+static bool
+ReleaseLruFile(void)
 {
    DO_DB(elog(DEBUG, "ReleaseLruFile. Opened %d", nfile));
 
-   if (nfile <= 0)
-       elog(ERROR, "ReleaseLruFile: No open files available to be closed");
-
-   /*
-    * There are opened files and so there should be at least one used vfd
-    * in the ring.
-    */
-   Assert(VfdCache[0].lruMoreRecently != 0);
-   LruDelete(VfdCache[0].lruMoreRecently);
+   if (nfile > 0)
+   {
+       /*
+        * There are opened files and so there should be at least one used
+        * vfd in the ring.
+        */
+       Assert(VfdCache[0].lruMoreRecently != 0);
+       LruDelete(VfdCache[0].lruMoreRecently);
+       return true;            /* freed a file */
+   }
+   return false;               /* no files available to free */
 }
 
 static File
-AllocateVfd()
+AllocateVfd(void)
 {
    Index       i;
    File        file;
@@ -631,7 +638,10 @@ fileNameOpenFile(FileName fileName,
    vfdP = &VfdCache[file];
 
    while (nfile + numAllocatedFiles >= pg_nofile())
-       ReleaseLruFile();
+   {
+       if (! ReleaseLruFile())
+           break;
+   }
 
    vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);
 
@@ -1027,26 +1037,31 @@ AllocateFile(char *name, char *mode)
 {
    FILE       *file;
 
-   DO_DB(elog(DEBUG, "AllocateFile: Allocated %d.", numAllocatedFiles));
+   DO_DB(elog(DEBUG, "AllocateFile: Allocated %d", numAllocatedFiles));
 
    if (numAllocatedFiles >= MAX_ALLOCATED_FILES)
        elog(ERROR, "AllocateFile: too many private FDs demanded");
 
 TryAgain:
-   if ((file = fopen(name, mode)) == NULL)
+   if ((file = fopen(name, mode)) != NULL)
    {
-       if ((errno == EMFILE || errno == ENFILE) && nfile > 0)
-       {
-           DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
-                      errno));
-           errno = 0;
-           ReleaseLruFile();
+       allocatedFiles[numAllocatedFiles++] = file;
+       return file;
+   }
+
+   if (errno == EMFILE || errno == ENFILE)
+   {
+       int     save_errno = errno;
+
+       DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",
+                  errno));
+       errno = 0;
+       if (ReleaseLruFile())
            goto TryAgain;
-       }
+       errno = save_errno;
    }
-   else
-       allocatedFiles[numAllocatedFiles++] = file;
-   return file;
+
+   return NULL;
 }
 
 void
@@ -1054,7 +1069,7 @@ FreeFile(FILE *file)
 {
    int         i;
 
-   DO_DB(elog(DEBUG, "FreeFile: Allocated %d.", numAllocatedFiles));
+   DO_DB(elog(DEBUG, "FreeFile: Allocated %d", numAllocatedFiles));
 
    /* Remove file from list of allocated files, if it's present */
    for (i = numAllocatedFiles; --i >= 0;)
@@ -1079,7 +1094,7 @@ FreeFile(FILE *file)
  * change in the logical state of the VFDs.
  */
 void
-closeAllVfds()
+closeAllVfds(void)
 {
    Index       i;