Esempio n. 1
0
File: fd.c Progetto: huor/gpdb
int64
FileSeek(File file, int64 offset, int whence)
{
	int			returnCode;

	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileSeek: %d (%s) " INT64_FORMAT " " INT64_FORMAT " %d",
			   file, VfdCache[file].fileName,
			   VfdCache[file].seekPos, offset, whence));

	if (FileIsNotOpen(file))
	{
		switch (whence)
		{
			case SEEK_SET:
				Assert(offset >= INT64CONST(0));
				VfdCache[file].seekPos = offset;
				break;
			case SEEK_CUR:
				VfdCache[file].seekPos += offset;
				break;
			case SEEK_END:
				returnCode = FileAccess(file);
				if (returnCode < 0)
					return returnCode;
				VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd,
											   offset, whence);
				break;
			default:
				Assert(!"invalid whence");
				break;
		}
	}
	else
	{
		switch (whence)
		{
			case SEEK_SET:
				Assert(offset >= INT64CONST(0));
				if (VfdCache[file].seekPos != offset)
					VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd,
												   offset, whence);
				break;
			case SEEK_CUR:
				if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
					VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd,
												   offset, whence);
				break;
			case SEEK_END:
				VfdCache[file].seekPos = pg_lseek64(VfdCache[file].fd,
											   offset, whence);
				break;
			default:
				Assert(!"invalid whence");
				break;
		}
	}
	return VfdCache[file].seekPos;
}
Esempio n. 2
0
/*
 * XXX not actually used but here for completeness
 */
long
FileTell(File file)
{
    DO_DB(printf("DEBUG: FileTell %d (%s)\n",
		 file, VfdCache[file].fileName));
    return VfdCache[file].seekPos;
}
Esempio n. 3
0
/* returns 0 on success, -1 on re-open failure (with errno set) */
static int
FileAccess(File file)
{
    int			returnValue;

    DO_DB(elog(LOG, "FileAccess %d (%s)",
               file, VfdCache[file].fileName));

    /*
     * Is the file open?  If not, open it and put it at the head of the LRU
     * ring (possibly closing the least recently used file to get an FD).
     */

    if (FileIsNotOpen(file))
    {
        returnValue = LruInsert(file);
        if (returnValue != 0)
            return returnValue;
    }
    else if (VfdCache[0].lruLessRecently != 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);
    }

    return 0;
}
Esempio n. 4
0
long
FileSeek(File file, long offset, int whence)
{
    int	returnCode;
    
    DO_DB(printf("DEBUG: FileSeek: %d (%s) %d %d\n",
		 file, VfdCache[file].fileName, offset, whence));
    
    if (FileIsNotOpen(file)) {
	switch(whence) {
	case SEEK_SET:
	    VfdCache[file].seekPos = offset;
	    return offset;
	case SEEK_CUR:
	    VfdCache[file].seekPos = VfdCache[file].seekPos +offset;
	    return VfdCache[file].seekPos;
	case SEEK_END:
	    FileAccess(file);
	    returnCode = VfdCache[file].seekPos = 
		lseek(VfdCache[file].fd, offset, whence);
	    return returnCode;
	default:
	    elog(WARN, "FileSeek: invalid whence: %d", whence);
	    break;
	}
    } else {
	returnCode = VfdCache[file].seekPos = 
	    lseek(VfdCache[file].fd, offset, whence);
	return returnCode;
    }
    /*NOTREACHED*/
    return(-1L);
}
Esempio n. 5
0
static void
LruDelete(File file)
{
    Vfd		   *vfdP;

    Assert(file != 0);

    DO_DB(elog(LOG, "LruDelete %d (%s)",
               file, VfdCache[file].fileName));

    vfdP = &VfdCache[file];

    /* delete the vfd record from the LRU ring */
    Delete(file);

    /* save the seek position */
    vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
    Assert(vfdP->seekPos != -1L);

    /* close the file */
    if (close(vfdP->fd))
        elog(ERROR, "could not close file \"%s\": %m", vfdP->fileName);

    --nfile;
    vfdP->fd = VFD_CLOSED;
}
Esempio n. 6
0
void
AllocateFile()
{
    int fd;
    int fdleft;

    while ((fd = open(Nulldev,O_WRONLY,0)) < 0) {
	if (errno == EMFILE) {
	    errno = 0;
	    FreeFd = 0;
	    AssertLruRoom();
	} else {
	    elog(WARN,"Open: %s in %s line %d\n", Nulldev,
		 __FILE__, __LINE__);
	}
    }
    close(fd);
    ++allocatedFiles;
    fdleft = MAXFILES - allocatedFiles;
    if (fdleft < 6) {
	elog(DEBUG,"warning: few usable file descriptors left (%d)", fdleft);
    }
    
    DO_DB(printf("DEBUG: AllocatedFile.  FreeFd = %d\n",
		 FreeFd));
}
Esempio n. 7
0
/*
 * close a file when done with it
 */
void
FileClose(File file)
{
    Vfd		   *vfdP;
    struct stat filestats;

    Assert(FileIsValid(file));

    DO_DB(elog(LOG, "FileClose: %d (%s)",
               file, VfdCache[file].fileName));

    vfdP = &VfdCache[file];

    if (!FileIsNotOpen(file))
    {
        /* remove the file from the lru ring */
        Delete(file);

        /* close the file */
        if (close(vfdP->fd))
            elog(ERROR, "could not close file \"%s\": %m", vfdP->fileName);

        --nfile;
        vfdP->fd = VFD_CLOSED;
    }

    /*
     * Delete the file if it was temporary
     */
    if (vfdP->fdstate & FD_TEMPORARY)
    {
        /* reset flag so that die() interrupt won't cause problems */
        vfdP->fdstate &= ~FD_TEMPORARY;
        if (log_temp_files >= 0)
        {
            if (stat(vfdP->fileName, &filestats) == 0)
            {
                if (filestats.st_size >= log_temp_files)
                    ereport(LOG,
                            (errmsg("temporary file: path \"%s\", size %lu",
                                    vfdP->fileName,
                                    (unsigned long) filestats.st_size)));
            }
            else
                elog(LOG, "could not stat file \"%s\": %m", vfdP->fileName);
        }
        if (unlink(vfdP->fileName))
            elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
    }

    /* Unregister it from the resource owner */
    if (vfdP->resowner)
        ResourceOwnerForgetFile(vfdP->resowner, file);

    /*
     * Return the Vfd slot to the free list
     */
    FreeVfd(file);
}
Esempio n. 8
0
File: fd.c Progetto: hellower/gpdb
int64
FileTell(File file)
{
	Assert(FileIsValid(file));
	DO_DB(elog(LOG, "FileTell %d (%s)",
			   file, VfdCache[file].fileName));
	return VfdCache[file].seekPos;
}
Esempio n. 9
0
File: fd.c Progetto: hellower/gpdb
int
FileRead(File file, char *buffer, int amount)
{
	int			returnCode;

	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
			   file, VfdCache[file].fileName,
			   VfdCache[file].seekPos, amount, buffer));

	if (Debug_filerep_print)
		(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p",
			  file, VfdCache[file].fileName,
			  VfdCache[file].seekPos, amount, buffer));

	returnCode = FileAccess(file);
	if (returnCode < 0)
		return returnCode;

retry:
	returnCode = read(VfdCache[file].fd, buffer, amount);

	if (returnCode >= 0)
		VfdCache[file].seekPos += returnCode;
	else
	{
		/*
		 * Windows may run out of kernel buffers and return "Insufficient
		 * system resources" error.  Wait a bit and retry to solve it.
		 *
		 * It is rumored that EINTR is also possible on some Unix filesystems,
		 * in which case immediate retry is indicated.
		 */
#ifdef WIN32
		DWORD		error = GetLastError();

		switch (error)
		{
			case ERROR_NO_SYSTEM_RESOURCES:
				pg_usleep(1000L);
				errno = EINTR;
				break;
			default:
				_dosmaperr(error);
				break;
		}
#endif
		/* OK to retry if interrupted */
		if (errno == EINTR)
			goto retry;

		/* Trouble, so assume we don't know the file position anymore */
		VfdCache[file].seekPos = FileUnknownPos;
	}

	return returnCode;
}
Esempio n. 10
0
static void
FreeVfd(File file)
{
    DO_DB(printf("DB: FreeVfd: %d (%s)\n",
		 file, VfdCache[file].fileName));
    
    VfdCache[file].nextFree = VfdCache[0].nextFree;
    VfdCache[0].nextFree = file;
}
Esempio n. 11
0
static void
Insert(File file)
{
    Vfd	*vfdP;
    
    DO_DB(printf("DEBUG:	Insert %d (%s)\n",
		 file, VfdCache[file].fileName));
    DO_DB(_dump_lru());
    
    vfdP = &VfdCache[file];
    
    vfdP->lruMoreRecently = 0;
    vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
    VfdCache[0].lruLessRecently = file;
    VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;
    
    DO_DB(_dump_lru());
}
Esempio n. 12
0
File: fd.c Progetto: hellower/gpdb
static void
Delete(File file)
{
	Vfd		   *vfdP;

	Assert(file != 0);

	DO_DB(elog(LOG, "Delete %d (%s)",
			   file, VfdCache[file].fileName));
	DO_DB(_dump_lru());

	vfdP = &VfdCache[file];

	VfdCache[vfdP->lruLessRecently].lruMoreRecently = vfdP->lruMoreRecently;
	VfdCache[vfdP->lruMoreRecently].lruLessRecently = vfdP->lruLessRecently;

	DO_DB(_dump_lru());
}
Esempio n. 13
0
File: fd.c Progetto: hellower/gpdb
static File
AllocateVfd(void)
{
	Index		i;
	File		file;

	DO_DB(elog(LOG, "AllocateVfd. Size %lu", SizeVfdCache));

	Assert(SizeVfdCache > 0);	/* InitFileAccess not called? */

	if (VfdCache[0].nextFree == 0)
	{
		/*
		 * The free list is empty so it is time to increase the size of the
		 * array.  We choose to double it each time this happens. However,
		 * there's not much point in starting *real* small.
		 */
		Size		newCacheSize = SizeVfdCache * 2;
		Vfd		   *newVfdCache;

		if (newCacheSize < 32)
			newCacheSize = 32;

		/*
		 * Be careful not to clobber VfdCache ptr if realloc fails.
		 */
		newVfdCache = (Vfd *) realloc(VfdCache, sizeof(Vfd) * newCacheSize);
		if (newVfdCache == NULL)
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
		VfdCache = newVfdCache;

		/*
		 * Initialize the new entries and link them into the free list.
		 */
		for (i = SizeVfdCache; i < newCacheSize; i++)
		{
			MemSet((char *) &(VfdCache[i]), 0, sizeof(Vfd));
			VfdCache[i].nextFree = i + 1;
			VfdCache[i].fd = VFD_CLOSED;
		}
		VfdCache[newCacheSize - 1].nextFree = 0;
		VfdCache[0].nextFree = SizeVfdCache;

		/*
		 * Record the new size
		 */
		SizeVfdCache = newCacheSize;
	}

	file = VfdCache[0].nextFree;

	VfdCache[0].nextFree = VfdCache[file].nextFree;

	return file;
}
Esempio n. 14
0
static void
AssertLruRoom()
{
    DO_DB(printf("DEBUG:	AssertLruRoom (FreeFd = %d)\n",
		 FreeFd));
    
    if (FreeFd <= 0 || nfile >= MAXFILES) {
	LruDelete(VfdCache[0].lruMoreRecently);
    }
}
Esempio n. 15
0
/*
 * XXX What happens if FreeFile() is called without a previous
 * AllocateFile()?
 */
void
FreeFile()
{
    DO_DB(printf("DEBUG: FreeFile.  FreeFd now %d\n",
		 FreeFd));
    FreeFd++;
    nfile++;			/* dangerous */
    Assert(allocatedFiles > 0);
    --allocatedFiles;
}
Esempio n. 16
0
static void
Delete(File file)
{
    Vfd	*fileP;
    
    DO_DB(printf("DEBUG:	Delete %d (%s)\n",
		 file, VfdCache[file].fileName));
    DO_DB(_dump_lru());
    
    Assert(file != 0);
    
    fileP = &VfdCache[file];

    VfdCache[fileP->lruLessRecently].lruMoreRecently =
	VfdCache[file].lruMoreRecently;
    VfdCache[fileP->lruMoreRecently].lruLessRecently =
	VfdCache[file].lruLessRecently;
    
    DO_DB(_dump_lru());
}
Esempio n. 17
0
int
FileWrite(File file, char *buffer, int amount)
{
    int			returnCode;

    Assert(FileIsValid(file));

    DO_DB(elog(LOG, "FileWrite: %d (%s) %ld %d %p",
               file, VfdCache[file].fileName,
               VfdCache[file].seekPos, amount, buffer));

    returnCode = FileAccess(file);
    if (returnCode < 0)
        return returnCode;

retry:
    errno = 0;
    returnCode = write(VfdCache[file].fd, buffer, amount);

    /* if write didn't set errno, assume problem is no disk space */
    if (returnCode != amount && errno == 0)
        errno = ENOSPC;

    if (returnCode >= 0)
        VfdCache[file].seekPos += returnCode;
    else
    {
        /*
         * See comments in FileRead()
         */
#ifdef WIN32
        DWORD		error = GetLastError();

        switch (error)
        {
        case ERROR_NO_SYSTEM_RESOURCES:
            pg_usleep(1000L);
            errno = EINTR;
            break;
        default:
            _dosmaperr(error);
            break;
        }
#endif
        /* OK to retry if interrupted */
        if (errno == EINTR)
            goto retry;

        /* Trouble, so assume we don't know the file position anymore */
        VfdCache[file].seekPos = FileUnknownPos;
    }

    return returnCode;
}
Esempio n. 18
0
File: fd.c Progetto: hellower/gpdb
static void
Insert(File file)
{
	Vfd		   *vfdP;

	Assert(file != 0);

	DO_DB(elog(LOG, "Insert %d (%s)",
			   file, VfdCache[file].fileName));
	DO_DB(_dump_lru());

	vfdP = &VfdCache[file];

	vfdP->lruMoreRecently = 0;
	vfdP->lruLessRecently = VfdCache[0].lruLessRecently;
	VfdCache[0].lruLessRecently = file;
	VfdCache[vfdP->lruLessRecently].lruMoreRecently = file;

	DO_DB(_dump_lru());
}
Esempio n. 19
0
int
FileTruncate(File file, int offset)
{
    int returnCode;

    DO_DB(printf("DEBUG: FileTruncate %d (%s)\n",
		 file, VfdCache[file].fileName));
    
    (void) FileSync(file);
    (void) FileAccess(file);
    returnCode = ftruncate(VfdCache[file].fd, offset);
    return(returnCode);
}
Esempio n. 20
0
File: fd.c Progetto: hellower/gpdb
/*
 * close a file and forcibly delete the underlying Unix file
 */
void
FileUnlink(File file)
{
	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileUnlink: %d (%s)",
	     file, VfdCache[file].fileName));

	/* force FileClose to delete it */
	VfdCache[file].fdstate |= FD_TEMPORARY;

	FileClose(file);
}
Esempio n. 21
0
int
FileRead(File file, char *buffer, int amount)
{
    int	returnCode;

    DO_DB(printf("DEBUG: FileRead: %d (%s) %d 0x%x\n",
		 file, VfdCache[file].fileName, amount, buffer));
    
    FileAccess(file);
    returnCode = read(VfdCache[file].fd, buffer, amount);
    if (returnCode > 0) {
	VfdCache[file].seekPos += returnCode;
    }
    
    return returnCode;
}
Esempio n. 22
0
int
FileSync(File file)
{
    int			returnCode;

    Assert(FileIsValid(file));

    DO_DB(elog(LOG, "FileSync: %d (%s)",
               file, VfdCache[file].fileName));

    returnCode = FileAccess(file);
    if (returnCode < 0)
        return returnCode;

    return pg_fsync(VfdCache[file].fd);
}
Esempio n. 23
0
int
FileTruncate(File file, long offset)
{
    int			returnCode;

    Assert(FileIsValid(file));

    DO_DB(elog(LOG, "FileTruncate %d (%s)",
               file, VfdCache[file].fileName));

    returnCode = FileAccess(file);
    if (returnCode < 0)
        return returnCode;

    returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);
    return returnCode;
}
Esempio n. 24
0
File: fd.c Progetto: hellower/gpdb
static bool
ReleaseLruFile(void)
{
	DO_DB(elog(LOG, "ReleaseLruFile. Opened %d", nfile));

	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 */
}
Esempio n. 25
0
File: fd.c Progetto: hellower/gpdb
int64
FileNonVirtualCurSeek(File file)
{
	int			returnCode;

	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileNonVirtualCurSeek: %d (%s) virtual position" INT64_FORMAT,
			   file, VfdCache[file].fileName,
			   VfdCache[file].seekPos));

	returnCode = FileAccess(file);
	if (returnCode < 0)
		return returnCode;

	return pg_lseek64(VfdCache[file].fd, 0, SEEK_CUR);
}
Esempio n. 26
0
File: fd.c Progetto: hellower/gpdb
int
FileSync(File file)
{
	int			returnCode;
	FileRepGpmonRecord_s gpmonRecord;
	FileRepGpmonStatType_e whichStat;

	if (fileRepRole == FileRepPrimaryRole)
	{
			whichStat = FileRepGpmonStatType_PrimaryFsyncSyscall;
			FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord);
	} else 
	{
			whichStat = FileRepGpmonStatType_MirrorFsyncSyscall;
			FileRepGpmonStat_OpenRecord(whichStat, &gpmonRecord);
	}
	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileSync: %d (%s)",
			   file, VfdCache[file].fileName));

	returnCode = FileAccess(file);
	if (returnCode < 0)
		return returnCode;

#ifdef FAULT_INJECTOR
	FaultInjector_InjectFaultIfSet(
								   FileRepFlush,
								   DDLNotSpecified,
								   "",	//databaseName
								   ""); // tableName
#endif								
	
	returnCode =  pg_fsync(VfdCache[file].fd);
	
	if (returnCode >= 0)
	{
			//only include stats if successful
			if ((fileRepRole == FileRepPrimaryRole) || 
				(fileRepRole == FileRepMirrorRole))
			{
					FileRepGpmonStat_CloseRecord(whichStat, &gpmonRecord);
			}
	}
	return returnCode;
}
Esempio n. 27
0
/*
 * Routines that want to use stdio (ie, FILE*) should use AllocateFile
 * rather than plain fopen().  This lets fd.c deal with freeing FDs if
 * necessary to open the file.	When done, call FreeFile rather than fclose.
 *
 * Note that files that will be open for any significant length of time
 * should NOT be handled this way, since they cannot share kernel file
 * descriptors with other files; there is grave risk of running out of FDs
 * if anyone locks down too many FDs.  Most callers of this routine are
 * simply reading a config file that they will read and close immediately.
 *
 * fd.c will automatically close all files opened with AllocateFile at
 * transaction commit or abort; this prevents FD leakage if a routine
 * that calls AllocateFile is terminated prematurely by ereport(ERROR).
 *
 * Ideally this should be the *only* direct call of fopen() in the backend.
 */
FILE *
AllocateFile(const char *name, const char *mode)
{
    FILE	   *file;

    DO_DB(elog(LOG, "AllocateFile: Allocated %d (%s)",
               numAllocatedDescs, name));

    /*
     * The test against MAX_ALLOCATED_DESCS prevents us from overflowing
     * allocatedFiles[]; the test against max_safe_fds prevents AllocateFile
     * from hogging every one of the available FDs, which'd lead to infinite
     * looping.
     */
    if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
            numAllocatedDescs >= max_safe_fds - 1)
        elog(ERROR, "too many private files demanded");

TryAgain:
    if ((file = fopen(name, mode)) != NULL)
    {
        AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];

        desc->kind = AllocateDescFile;
        desc->desc.file = file;
        desc->create_subid = GetCurrentSubTransactionId();
        numAllocatedDescs++;
        return desc->desc.file;
    }

    if (errno == EMFILE || errno == ENFILE)
    {
        int			save_errno = errno;

        ereport(LOG,
                (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
                 errmsg("out of file descriptors: %m; release and retry")));
        errno = 0;
        if (ReleaseLruFile())
            goto TryAgain;
        errno = save_errno;
    }

    return NULL;
}
Esempio n. 28
0
File: fd.c Progetto: hellower/gpdb
/*
 * Routines that want to use <dirent.h> (ie, DIR*) should use AllocateDir
 * rather than plain opendir().  This lets fd.c deal with freeing FDs if
 * necessary to open the directory, and with closing it after an elog.
 * When done, call FreeDir rather than closedir.
 *
 * Ideally this should be the *only* direct call of opendir() in the backend.
 */
DIR *
AllocateDir(const char *dirname)
{
	DIR		   *dir;

	DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
			   numAllocatedDescs, dirname));

	/*
	 * The test against MAX_ALLOCATED_DESCS prevents us from overflowing
	 * allocatedDescs[]; the test against max_safe_fds prevents AllocateDir
	 * from hogging every one of the available FDs, which'd lead to infinite
	 * looping.
	 */
	if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
		numAllocatedDescs >= max_safe_fds - 1)
		elog(ERROR, "could not allocate directory: out of file handles");

TryAgain:
	if ((dir = opendir(dirname)) != NULL)
	{
		AllocateDesc *desc = &allocatedDescs[numAllocatedDescs];

		desc->kind = AllocateDescDir;
		desc->desc.dir = dir;
		desc->create_subid = GetCurrentSubTransactionId();
		numAllocatedDescs++;
		return desc->desc.dir;
	}

	if (errno == EMFILE || errno == ENFILE)
	{
		int			save_errno = errno;

		ereport(LOG,
				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
				 errmsg("out of file handles: %m; release and retry")));
		errno = 0;
		if (ReleaseLruFile())
			goto TryAgain;
		errno = save_errno;
	}

	return NULL;
}
Esempio n. 29
0
File: fd.c Progetto: hellower/gpdb
static void
FreeVfd(File file)
{
	Vfd		   *vfdP = &VfdCache[file];

	DO_DB(elog(LOG, "FreeVfd: %d (%s)",
			   file, vfdP->fileName ? vfdP->fileName : ""));

	if (vfdP->fileName != NULL)
	{
		free(vfdP->fileName);
		vfdP->fileName = NULL;
	}
	vfdP->fdstate = 0x0;

	vfdP->nextFree = VfdCache[0].nextFree;
	VfdCache[0].nextFree = file;
}
Esempio n. 30
0
File: fd.c Progetto: hellower/gpdb
/*
 * close a file when done with it
 */
void
FileClose(File file)
{
	Vfd		   *vfdP;

	Assert(FileIsValid(file));

	DO_DB(elog(LOG, "FileClose: %d (%s)",
			   file, VfdCache[file].fileName));

	vfdP = &VfdCache[file];

	if (!FileIsNotOpen(file))
	{
		/* remove the file from the lru ring */
		Delete(file);

		/* close the file */
		if (gp_retry_close(vfdP->fd))
			elog(ERROR, "could not close file \"%s\": %m",
				 vfdP->fileName);

		--nfile;
		vfdP->fd = VFD_CLOSED;
	}

	/*
	 * Delete the file if it was temporary
	 */
	if (vfdP->fdstate & FD_TEMPORARY)
	{
		/* reset flag so that die() interrupt won't cause problems */
		vfdP->fdstate &= ~FD_TEMPORARY;
		if (unlink(vfdP->fileName))
			elog(DEBUG1, "failed to unlink \"%s\": %m",
				 vfdP->fileName);
	}

	/*
	 * Return the Vfd slot to the free list
	 */
	FreeVfd(file);
}