Exemple #1
0
/*
 * closeAllVfds
 *
 * Force all VFDs into the physically-closed state, so that the fewest
 * possible number of kernel file descriptors are in use.  There is no
 * change in the logical state of the VFDs.
 */
void
closeAllVfds(void)
{
	Index		i;

	if (SizeVfdCache > 0)
	{
		Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */
		for (i = 1; i < SizeVfdCache; i++)
		{
			if (!FileIsNotOpen(i))
				LruDelete(i);
		}
	}
}
Exemple #2
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);
}
Exemple #3
0
/*
 *  Called when we get a shared invalidation message on some relation.
 */
void
FileInvalidate(File file)
{
    if (!FileIsNotOpen(file)) {
	LruDelete(file);
    }
}
Exemple #4
0
/*
 * Close temporary files and delete their underlying files.
 *
 * isProcExit: if true, this is being called as the backend process is
 * exiting. If that's the case, we should remove all temporary files; if
 * that's not the case, we are being called for transaction commit/abort
 * and should only remove transaction-local temp files.  In either case,
 * also clean up "allocated" stdio files and dirs.
 */
static void
CleanupTempFiles(bool isProcExit)
{
	Index		i;

	if (SizeVfdCache > 0)
	{
		Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */
		for (i = 1; i < SizeVfdCache; i++)
		{
			unsigned short fdstate = VfdCache[i].fdstate;

			/*
			 * If we're in the process of exiting a backend process, close
			 * all temporary files. Otherwise, only close temporary files
			 * local to the current transaction.
			 */
			if((fdstate & FD_CLOSE_AT_EOXACT)
			  	||
			   (isProcExit && (fdstate & FD_TEMPORARY))
			  )
			{
				AssertImply( (fdstate & FD_TEMPORARY), VfdCache[i].fileName != NULL);
				FileClose(i);
			}
		}
	}

	workfile_mgr_cleanup();

	while (numAllocatedDescs > 0)
		FreeDesc(&allocatedDescs[0]);
}
Exemple #5
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;
}
Exemple #6
0
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;
}
Exemple #7
0
void
FileInvalidate(File file)
{
	Assert(FileIsValid(file));
	if (!FileIsNotOpen(file))
		LruDelete(file);
}
Exemple #8
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);
}
Exemple #9
0
void
closeAllVfds()
{
    int i;
    for (i=0; i<SizeVfdCache; i++) {
	if (!FileIsNotOpen(i))
	    LruDelete(i);
    }
}
Exemple #10
0
/* returns 0 on success, -1 on re-open failure (with errno set) */
static int
LruInsert(File file)
{
	Vfd		   *vfdP;

	Assert(file != 0);

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

	vfdP = &VfdCache[file];

	if (FileIsNotOpen(file))
	{
		while (nfile + numAllocatedDescs >= max_safe_fds)
		{
			if (!ReleaseLruFile())
				break;
		}

		/*
		 * The open could still fail for lack of file descriptors, eg due to
		 * overall system file table being full.  So, be prepared to release
		 * another FD if necessary...
		 */
		vfdP->fd = BasicOpenFile(vfdP->fileName, vfdP->fileFlags,
								 vfdP->fileMode);
		if (vfdP->fd < 0)
		{
			DO_DB(elog(LOG, "RE_OPEN FAILED: %d", errno));
			return vfdP->fd;
		}
		else
		{
			DO_DB(elog(LOG, "RE_OPEN SUCCESS"));
			++nfile;
		}

		/* seek to the right position */
		if (vfdP->seekPos != INT64CONST(0))
		{
			int64		returnValue;

			returnValue = pg_lseek64(vfdP->fd, vfdP->seekPos, SEEK_SET);
			Assert(returnValue != INT64CONST(-1));
		}
	}

	/*
	 * put it at the head of the Lru ring
	 */

	Insert(file);

	return 0;
}
Exemple #11
0
/*
 * 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);
}
Exemple #12
0
void
FileClose(File file)
{
    int	returnValue;
    
    DO_DB(printf("DEBUG: FileClose: %d (%s)\n",
		 file, VfdCache[file].fileName));
    
    if (!FileIsNotOpen(file)) {
	
	/* remove the file from the lru ring */
	Delete(file);
	
	/* record the new free operating system file descriptor */
	FreeFd++;
	
	/* if we did any writes, sync the file before closing */
	if (VfdCache[file].fdstate & FD_DIRTY) {
	    returnValue = fsync(VfdCache[file].fd);
	    Assert(returnValue != -1);
	    VfdCache[file].fdstate &= ~FD_DIRTY;
	}
	
	/* close the file */
	returnValue = close(VfdCache[file].fd);
	Assert(returnValue != -1);
	
	--nfile;
	VfdCache[file].fd = VFD_CLOSED;
    }
    /*
     * Add the Vfd slot to the free list
     */
    FreeVfd(file);
    /*
     * Free the filename string
     */
    free(VfdCache[file].fileName);
}
Exemple #13
0
/*
 * AtEOSubXact_Files
 *
 * Take care of subtransaction commit/abort.  At abort, we close temp files
 * that the subtransaction may have opened.  At commit, we reassign the
 * files that were opened to the parent subtransaction.
 */
void
AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
				  SubTransactionId parentSubid)
{
	Index		i;

	if (SizeVfdCache > 0)
	{
		Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */
		for (i = 1; i < SizeVfdCache; i++)
		{
			unsigned short fdstate = VfdCache[i].fdstate;

			if ((fdstate & FD_CLOSE_AT_EOXACT) &&
				VfdCache[i].create_subid == mySubid)
			{
				if (isCommit)
					VfdCache[i].create_subid = parentSubid;
				else if (VfdCache[i].fileName != NULL)
					FileClose(i);
			}
		}
	}

	for (i = 0; i < numAllocatedDescs; i++)
	{
		if (allocatedDescs[i].create_subid == mySubid)
		{
			if (isCommit)
				allocatedDescs[i].create_subid = parentSubid;
			else
			{
				/* have to recheck the item after FreeDesc (ugly) */
				FreeDesc(&allocatedDescs[i--]);
			}
		}
	}
}
Exemple #14
0
/*
 * Close temporary files and delete their underlying files.
 *
 * isProcExit: if true, this is being called as the backend process is
 * exiting. If that's the case, we should remove all temporary files; if
 * that's not the case, we are being called for transaction commit/abort
 * and should only remove transaction-local temp files.  In either case,
 * also clean up "allocated" stdio files and dirs.
 */
static void
CleanupTempFiles(bool isProcExit)
{
    Index		i;

    if (SizeVfdCache > 0)
    {
        Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */
        for (i = 1; i < SizeVfdCache; i++)
        {
            unsigned short fdstate = VfdCache[i].fdstate;

            if ((fdstate & FD_TEMPORARY) && VfdCache[i].fileName != NULL)
            {
                /*
                 * If we're in the process of exiting a backend process, close
                 * all temporary files. Otherwise, only close temporary files
                 * local to the current transaction. They should be closed
                 * by the ResourceOwner mechanism already, so this is just
                 * a debugging cross-check.
                 */
                if (isProcExit)
                    FileClose(i);
                else if (fdstate & FD_XACT_TEMPORARY)
                {
                    elog(WARNING,
                         "temporary file %s not closed at end-of-transaction",
                         VfdCache[i].fileName);
                    FileClose(i);
                }
            }
        }
    }

    /* Clean up "allocated" stdio files and dirs. */
    while (numAllocatedDescs > 0)
        FreeDesc(&allocatedDescs[0]);
}
Exemple #15
0
long
FileSeek(File file, long offset, int whence)
{
    int			returnCode;

    Assert(FileIsValid(file));

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

    if (FileIsNotOpen(file))
    {
        switch (whence)
        {
        case SEEK_SET:
            if (offset < 0)
                elog(ERROR, "invalid seek offset: %ld", offset);
            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 = lseek(VfdCache[file].fd,
                                           offset, whence);
            break;
        default:
            elog(ERROR, "invalid whence: %d", whence);
            break;
        }
    }
    else
    {
        switch (whence)
        {
        case SEEK_SET:
            if (offset < 0)
                elog(ERROR, "invalid seek offset: %ld", offset);
            if (VfdCache[file].seekPos != offset)
                VfdCache[file].seekPos = lseek(VfdCache[file].fd,
                                               offset, whence);
            break;
        case SEEK_CUR:
            if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
                VfdCache[file].seekPos = lseek(VfdCache[file].fd,
                                               offset, whence);
            break;
        case SEEK_END:
            VfdCache[file].seekPos = lseek(VfdCache[file].fd,
                                           offset, whence);
            break;
        default:
            elog(ERROR, "invalid whence: %d", whence);
            break;
        }
    }
    return VfdCache[file].seekPos;
}
Exemple #16
0
static int
LruInsert (File file)
{
    Vfd	*vfdP;
    int	returnValue;
    
    DO_DB(printf("DEBUG:	LruInsert %d (%s)\n",
		 file, VfdCache[file].fileName));
    
    vfdP = &VfdCache[file];
    
    if (FileIsNotOpen(file)) {
	int tmpfd;
	
        /*
	 * Note, we check to see if there's a free file descriptor
	 * before attempting to open a file. One general way to do
	 * this is to try to open the null device which everybody
	 * should be able to open all the time. If this fails, we
	 * assume this is because there's no free file descriptors.
	 */
    tryAgain:
	tmpfd = open(Nulldev, O_CREAT|O_RDWR, 0666);
	if (tmpfd < 0) {
	    FreeFd = 0;
	    errno = 0;
	    AssertLruRoom();
	    goto tryAgain;
	} else {
	    close(tmpfd);
	}
	vfdP->fd = open(vfdP->fileName,vfdP->fileFlags,vfdP->fileMode);
	
	if (vfdP->fd < 0) {
	    DO_DB(printf("RE_OPEN FAILED: %d\n",
			 errno));
	    return (vfdP->fd);
	} else {
	    DO_DB(printf("RE_OPEN SUCCESS\n"));
	    ++nfile;
	}
	
	/* seek to the right position */
	if (vfdP->seekPos != 0L) {
	    returnValue =
		lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
	    Assert(returnValue != -1);
	}
	
	/* init state on open */
	vfdP->fdstate = 0x0;
	
	/* note that a file descriptor has been used up */
	if (FreeFd > 0)
	    FreeFd--;
    }
    
    /*
     * put it at the head of the Lru ring
     */
    
    Insert(file);
    
    return (0);
}
Exemple #17
0
static char *
filepath(char *filename)
{
    char *buf;
    char basename[16];
    int len;

#ifndef WIN32    
    if (*filename != Sep_char) {
#else
    if (!(filename[1] == ':' && filename[2] == Sep_char)) {
#endif /* WIN32 */	

	/* Either /base/ or \base\ */
	sprintf(basename, "%cbase%c", Sep_char, Sep_char);

	len = strlen(DataDir) + strlen(basename) + strlen(GetDatabaseName())
	    + strlen(filename) + 2;
	buf = (char*) palloc(len);
	sprintf(buf, "%s%s%s%c%s",
		DataDir, basename, GetDatabaseName(), Sep_char, filename);
    } else {
	buf = (char *) palloc(strlen(filename) + 1);
	strcpy(buf, filename);
    }
    
    return(buf);
}

static int
FileAccess(File file)
{
    int	returnValue;
    
    DO_DB(printf("DB: FileAccess %d (%s)\n",
		 file, VfdCache[file].fileName));
    
    /*
     * Is the file open?  If not, close the least recently used,
     * then open it and stick it at the head of the used ring
     */
    
    if (FileIsNotOpen(file)) {
	
	AssertLruRoom();
	
	returnValue = LruInsert(file);
	if (returnValue != 0)
	    return returnValue;
	
    } else {
	
	/*
	 * We now know that the file is open and that it is not the
	 * last one accessed, so we need to more it to the head of
	 * the Lru ring.
	 */
	
	Delete(file);
	Insert(file);
    }
    
    return (0);
}