⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fd.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		DO_DB(elog(DEBUG, "fileNameOpenFile: not enough descs, retry, er= %d",				   errno));		errno = 0;		ReleaseLruFile();		goto tryAgain;	}	if (vfdP->fd < 0)	{		FreeVfd(file);		return -1;	}	++nfile;	DO_DB(elog(DEBUG, "fileNameOpenFile: success %d",			   vfdP->fd));	Insert(file);	vfdP->fileName = malloc(strlen(fileName) + 1);	strcpy(vfdP->fileName, fileName);	vfdP->fileFlags = fileFlags & ~(O_TRUNC | O_EXCL);	vfdP->fileMode = fileMode;	vfdP->seekPos = 0;	vfdP->fdstate = 0x0;	return file;}/* * open a file in the database directory ($PGDATA/base/...) */FileFileNameOpenFile(FileName fileName, int fileFlags, int fileMode){	File		fd;	char	   *fname;	fname = filepath(fileName);	fd = fileNameOpenFile(fname, fileFlags, fileMode);	pfree(fname);	return fd;}/* * open a file in an arbitrary directory */FilePathNameOpenFile(FileName fileName, int fileFlags, int fileMode){	return fileNameOpenFile(fileName, fileFlags, fileMode);}/* * Open a temporary file that will disappear when we close it. * * This routine takes care of generating an appropriate tempfile name. * There's no need to pass in fileFlags or fileMode either, since only * one setting makes any sense for a temp file. */FileOpenTemporaryFile(void){	char		tempfilename[64];	File		file;	/*	 * Generate a tempfile name that's unique within the current	 * transaction	 */	snprintf(tempfilename, sizeof(tempfilename),			 "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);	/* Open the file */#ifndef __CYGWIN32__	file = FileNameOpenFile(tempfilename,							O_RDWR | O_CREAT | O_TRUNC, 0600);#else	file = FileNameOpenFile(tempfilename,							O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600);#endif	if (file <= 0)		elog(ERROR, "Failed to create temporary file %s", tempfilename);	/* Mark it for deletion at close or EOXact */	VfdCache[file].fdstate |= FD_TEMPORARY;	return file;}/* * close a file when done with it */voidFileClose(File file){	int			returnValue;	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileClose: %d (%s)",			   file, VfdCache[file].fileName));	if (!FileIsNotOpen(file))	{		/* remove the file from the lru ring */		Delete(file);		/* if we did any writes, sync the file before closing */		if (VfdCache[file].fdstate & FD_DIRTY)		{			returnValue = pg_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;	}	/*	 * Delete the file if it was temporary	 */	if (VfdCache[file].fdstate & FD_TEMPORARY)		unlink(VfdCache[file].fileName);	/*	 * Return the Vfd slot to the free list	 */	FreeVfd(file);}/* * close a file and forcibly delete the underlying Unix file */voidFileUnlink(File file){	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileUnlink: %d (%s)",			   file, VfdCache[file].fileName));	/* force FileClose to delete it */	VfdCache[file].fdstate |= FD_TEMPORARY;	FileClose(file);}intFileRead(File file, char *buffer, int amount){	int			returnCode;	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileRead: %d (%s) %d %p",			   file, VfdCache[file].fileName, amount, buffer));	FileAccess(file);	returnCode = read(VfdCache[file].fd, buffer, amount);	if (returnCode > 0)		VfdCache[file].seekPos += returnCode;	return returnCode;}intFileWrite(File file, char *buffer, int amount){	int			returnCode;	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileWrite: %d (%s) %d %p",			   file, VfdCache[file].fileName, amount, buffer));	FileAccess(file);	returnCode = write(VfdCache[file].fd, buffer, amount);	if (returnCode > 0)		VfdCache[file].seekPos += returnCode;	/* record the write */	VfdCache[file].fdstate |= FD_DIRTY;	return returnCode;}longFileSeek(File file, long offset, int whence){	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileSeek: %d (%s) %ld %d",			   file, VfdCache[file].fileName, offset, whence));	if (FileIsNotOpen(file))	{		switch (whence)		{			case SEEK_SET:				VfdCache[file].seekPos = offset;				break;			case SEEK_CUR:				VfdCache[file].seekPos += offset;				break;			case SEEK_END:				FileAccess(file);				VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);				break;			default:				elog(ERROR, "FileSeek: invalid whence: %d", whence);				break;		}	}	else		VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);	return VfdCache[file].seekPos;}/* * XXX not actually used but here for completeness */#ifdef NOT_USEDlongFileTell(File file){	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileTell %d (%s)",			   file, VfdCache[file].fileName));	return VfdCache[file].seekPos;}#endifintFileTruncate(File file, int offset){	int			returnCode;	Assert(FileIsValid(file));	DO_DB(elog(DEBUG, "FileTruncate %d (%s)",			   file, VfdCache[file].fileName));	FileSync(file);	FileAccess(file);	returnCode = ftruncate(VfdCache[file].fd, offset);	return returnCode;}intFileSync(File file){	int			returnCode;	Assert(FileIsValid(file));	/*	 * If the file isn't open, then we don't need to sync it; we always	 * sync files when we close them.  Also, if we haven't done any writes	 * that we haven't already synced, we can ignore the request.	 */	if (VfdCache[file].fd < 0 || !(VfdCache[file].fdstate & FD_DIRTY))		returnCode = 0;	else	{		returnCode = pg_fsync(VfdCache[file].fd);		VfdCache[file].fdstate &= ~FD_DIRTY;	}	return returnCode;}intFileNameUnlink(char *filename){	int			retval;	char	   *fname;	fname = filepath(filename);	retval = unlink(fname);	pfree(fname);	return retval;}/* * 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 elog(ERROR). */FILE *AllocateFile(char *name, char *mode){	FILE	   *file;	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 (errno == EMFILE || errno == ENFILE)		{			DO_DB(elog(DEBUG, "AllocateFile: not enough descs, retry, er= %d",					   errno));			errno = 0;			ReleaseLruFile();			goto TryAgain;		}	}	else		allocatedFiles[numAllocatedFiles++] = file;	return file;}voidFreeFile(FILE *file){	int			i;	DO_DB(elog(DEBUG, "FreeFile: Allocated %d.", numAllocatedFiles));	/* Remove file from list of allocated files, if it's present */	for (i = numAllocatedFiles; --i >= 0;)	{		if (allocatedFiles[i] == file)		{			allocatedFiles[i] = allocatedFiles[--numAllocatedFiles];			break;		}	}	if (i < 0)		elog(NOTICE, "FreeFile: file was not obtained from AllocateFile");	fclose(file);}/* * 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. */voidcloseAllVfds(){	Index		i;	if (SizeVfdCache > 0)	{		Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */		for (i = 1; i < SizeVfdCache; i++)		{			if (!FileIsNotOpen(i))				LruDelete(i);		}	}}/* * AtEOXact_Files * * This routine is called during transaction commit or abort (it doesn't * particularly care which).  All still-open temporary-file VFDs are closed, * which also causes the underlying files to be deleted.  Furthermore, * all "allocated" stdio files are closed. */voidAtEOXact_Files(void){	Index		i;	if (SizeVfdCache > 0)	{		Assert(FileIsNotOpen(0));		/* Make sure ring not corrupted */		for (i = 1; i < SizeVfdCache; i++)		{			if ((VfdCache[i].fdstate & FD_TEMPORARY) &&				VfdCache[i].fileName != NULL)				FileClose(i);		}	}	while (numAllocatedFiles > 0)		FreeFile(allocatedFiles[0]);	/*	 * Reset the tempfile name counter to 0; not really necessary, but	 * helps keep the names from growing unreasonably long.	 */	tempFileCounter = 0;}/* * Operations on BufFiles --- a very incomplete emulation of stdio * atop virtual Files.	Currently, we only support the buffered-I/O * aspect of stdio: a read or write of the low-level File occurs only * when the buffer is filled or emptied.  This is an even bigger win * for virtual Files than ordinary kernel files, since reducing the * frequency with which a virtual File is touched reduces "thrashing" * of opening/closing file descriptors. * * Note that BufFile structs are allocated with palloc(), and therefore * will go away automatically at transaction end.  If the underlying * virtual File is made with OpenTemporaryFile, then all resources for * the file are certain to be cleaned up even if processing is aborted * by elog(ERROR). */struct BufFile{	File		file;			/* the underlying virtual File */	bool		dirty;			/* does buffer need to be written? */	int			pos;			/* next read/write position in buffer */	int			nbytes;			/* total # of valid bytes in buffer */	char		buffer[BLCKSZ];};/* * Create a BufFile and attach it to an (already opened) virtual File. * * This is comparable to fdopen() in stdio. */BufFile    *BufFileCreate(File file){	BufFile    *bfile = (BufFile *) palloc(sizeof(BufFile));	bfile->file = file;	bfile->dirty = false;	bfile->pos = 0;	bfile->nbytes = 0;	return bfile;}/* * Close a BufFile * * Like fclose(), this also implicitly FileCloses the underlying File. */voidBufFileClose(BufFile *file){	/* flush any unwritten data */	BufFileFlush(file);	/* close the underlying (with delete if it's a temp file) */	FileClose(file->file);	/* release the buffer space */	pfree(file);}/* BufFileRead * * Like fread() except we assume 1-byte element size. */size_tBufFileRead(BufFile *file, void *ptr, size_t size){	size_t		nread = 0;	size_t		nthistime;	if (file->dirty)	{		elog(NOTICE, "BufFileRead: should have flushed after writing");		BufFileFlush(file);	}	while (size > 0)	{		if (file->pos >= file->nbytes)		{			/* Try to load more data into buffer */			file->pos = 0;			file->nbytes = FileRead(file->file, file->buffer,									sizeof(file->buffer));			if (file->nbytes < 0)				file->nbytes = 0;			if (file->nbytes <= 0)				break;			/* no more data available */		}		nthistime = file->nbytes - file->pos;		if (nthistime > size)			nthistime = size;		Assert(nthistime > 0);		memcpy(ptr, file->buffer + file->pos, nthistime);		file->pos += nthistime;		ptr = (void *) ((char *) ptr + nthistime);		size -= nthistime;		nread += nthistime;	}	return nread;}/* BufFileWrite * * Like fwrite() except we assume 1-byte element size. */size_tBufFileWrite(BufFile *file, void *ptr, size_t size){	size_t		nwritten = 0;	size_t		nthistime;	while (size > 0)	{		if (file->pos >= BLCKSZ)		{			/* Buffer full, dump it out */			if (file->dirty)			{				if (FileWrite(file->file, file->buffer, file->nbytes) < 0)					break;		/* I/O error */				file->dirty = false;			}			file->pos = 0;			file->nbytes = 0;		}		nthistime = BLCKSZ - file->pos;		if (nthistime > size)			nthistime = size;		Assert(nthistime > 0);		memcpy(file->buffer + file->pos, ptr, nthistime);		file->dirty = true;		file->pos += nthistime;		if (file->nbytes < file->pos)			file->nbytes = file->pos;		ptr = (void *) ((char *) ptr + nthistime);		size -= nthistime;		nwritten += nthistime;	}	return nwritten;}/* BufFileFlush * * Like fflush() */static intBufFileFlush(BufFile *file){	if (file->dirty)	{		if (FileWrite(file->file, file->buffer, file->nbytes) < 0)			return EOF;		file->dirty = false;	}	return 0;}/* BufFileSeek * * Like fseek(), or really more like lseek() since the return value is * the new file offset (or -1 in case of error). */longBufFileSeek(BufFile *file, long offset, int whence){	if (BufFileFlush(file) < 0)		return -1L;	file->pos = 0;	file->nbytes = 0;	return FileSeek(file->file, offset, whence);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -