From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 27 Aug 2000 21:48:00 +0000 (+0000)
Subject: Change ReleaseLruFile() usage so that if we cannot release any more
X-Git-Tag: REL7_1_BETA~731
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ba9d8c2d45e745d72666b5befabea0300168daa;p=postgresql

Change ReleaseLruFile() usage so that if we cannot release any more
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().
---

diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 6a4ecb63dc..de6ca57ca1 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -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;