WIP: Add FileOpenForFd().
authorAndres Freund <andres@anarazel.de>
Mon, 21 May 2018 22:43:30 +0000 (15:43 -0700)
committerAndres Freund <andres@anarazel.de>
Mon, 21 May 2018 22:43:30 +0000 (15:43 -0700)
Author: Andres Freund
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

src/backend/storage/file/fd.c
src/include/storage/fd.h

index 8ae13a51ec1ae32e59f2d19d55f25f73727e8563..50a1cb930f65ce5d74c1ee067a0cbc9484416dab 100644 (file)
@@ -180,6 +180,7 @@ int         max_safe_fds = 32;  /* default if not changed */
 #define FD_DELETE_AT_CLOSE (1 << 0)    /* T = delete when closed */
 #define FD_CLOSE_AT_EOXACT (1 << 1)    /* T = close at eoXact */
 #define FD_TEMP_FILE_LIMIT (1 << 2)    /* T = respect temp_file_limit */
+#define FD_NOT_IN_LRU      (1 << 3)    /* T = not in LRU */
 
 typedef struct vfd
 {
@@ -304,7 +305,6 @@ static void LruDelete(File file);
 static void Insert(File file);
 static int LruInsert(File file);
 static bool ReleaseLruFile(void);
-static void ReleaseLruFiles(void);
 static File AllocateVfd(void);
 static void FreeVfd(File file);
 
@@ -1176,7 +1176,7 @@ ReleaseLruFile(void)
  * Release kernel FDs as needed to get under the max_safe_fds limit.
  * After calling this, it's OK to try to open another file.
  */
-static void
+void
 ReleaseLruFiles(void)
 {
    while (nfile + numAllocatedDescs >= max_safe_fds)
@@ -1289,9 +1289,11 @@ FileAccess(File file)
         * We now know that the file is open and that it is not the last one
         * accessed, so we need to move it to the head of the Lru ring.
         */
-
-       Delete(file);
-       Insert(file);
+       if (!(VfdCache[file].fdstate & FD_NOT_IN_LRU))
+       {
+           Delete(file);
+           Insert(file);
+       }
    }
 
    return 0;
@@ -1414,6 +1416,56 @@ PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
    return file;
 }
 
+/*
+ * Open a File for a pre-existing file descriptor.
+ *
+ * Note that these files will not be closed in an LRU basis, therefore the
+ * caller is responsible for limiting the number of open file descriptors.
+ *
+ * The passed in name is purely for informational purposes.
+ */
+File
+FileOpenForFd(int fd, const char *fileName)
+{
+   char       *fnamecopy;
+   File        file;
+   Vfd        *vfdP;
+
+   /*
+    * We need a malloc'd copy of the file name; fail cleanly if no room.
+    */
+   fnamecopy = strdup(fileName);
+   if (fnamecopy == NULL)
+       ereport(ERROR,
+               (errcode(ERRCODE_OUT_OF_MEMORY),
+                errmsg("out of memory")));
+
+   file = AllocateVfd();
+   vfdP = &VfdCache[file];
+
+   /* Close excess kernel FDs. */
+   ReleaseLruFiles();
+
+   vfdP->fd = fd;
+   ++nfile;
+
+   DO_DB(elog(LOG, "FileOpenForFd: success %d/%d (%s)",
+              file, fd, fnamecopy));
+
+   /* NB: Explicitly not inserted into LRU! */
+
+   vfdP->fileName = fnamecopy;
+   /* Saved flags are adjusted to be OK for re-opening file */
+   vfdP->fileFlags = 0;
+   vfdP->fileMode = 0;
+   vfdP->seekPos = 0;
+   vfdP->fileSize = 0;
+   vfdP->fdstate = FD_NOT_IN_LRU;
+   vfdP->resowner = NULL;
+
+   return file;
+}
+
 /*
  * Create directory 'directory'.  If necessary, create 'basedir', which must
  * be the directory above it.  This is designed for creating the top-level
@@ -1760,7 +1812,11 @@ FileClose(File file)
        vfdP->fd = VFD_CLOSED;
 
        /* remove the file from the lru ring */
-       Delete(file);
+       if (!(vfdP->fdstate & FD_NOT_IN_LRU))
+       {
+           vfdP->fdstate &= ~FD_NOT_IN_LRU;
+           Delete(file);
+       }
    }
 
    if (vfdP->fdstate & FD_TEMP_FILE_LIMIT)
index 5e016d69a5a043825885df6bad917d015f494115..e96e8b13982f6407a10c5cae0865682641f17694 100644 (file)
@@ -65,6 +65,7 @@ extern int    max_safe_fds;
 /* Operations on virtual Files --- equivalent to Unix kernel file ops */
 extern File PathNameOpenFile(const char *fileName, int fileFlags);
 extern File PathNameOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode);
+extern File FileOpenForFd(int fd, const char *fileName);
 extern File OpenTemporaryFile(bool interXact);
 extern void FileClose(File file);
 extern int FilePrefetch(File file, off_t offset, int amount, uint32 wait_event_info);
@@ -127,6 +128,7 @@ extern void AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
                  SubTransactionId parentSubid);
 extern void RemovePgTempFiles(void);
 extern bool looks_like_temp_rel_name(const char *name);
+extern void ReleaseLruFiles(void);
 
 extern int pg_fsync(int fd);
 extern int pg_fsync_no_writethrough(int fd);