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

📄 fd.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
static voidInsert(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());}static intLruInsert(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 + numAllocatedFiles + numAllocatedDirs >= 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 != 0L)		{			long		returnValue;			returnValue = (long) lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);			Assert(returnValue != -1L);		}	}	/*	 * put it at the head of the Lru ring	 */	Insert(file);	return 0;}static boolReleaseLruFile(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 */}static FileAllocateVfd(void){	Index		i;	File		file;	DO_DB(elog(LOG, "AllocateVfd. Size %d", SizeVfdCache));	if (SizeVfdCache == 0)	{		/* initialize header entry first time through */		VfdCache = (Vfd *) malloc(sizeof(Vfd));		if (VfdCache == NULL)			ereport(FATAL,					(errcode(ERRCODE_OUT_OF_MEMORY),					 errmsg("out of memory")));		MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));		VfdCache->fd = VFD_CLOSED;		SizeVfdCache = 1;		/*		 * register proc-exit call to ensure temp files are dropped at		 * exit		 */		on_proc_exit(AtProcExit_Files, 0);	}	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;}static voidFreeVfd(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;}/* filepath() * Convert given pathname to absolute. * * Result is a palloc'd string. * * (Generally, this isn't actually necessary, considering that we * should be cd'd into the database directory.  Presently it is only * necessary to do it in "bootstrap" mode.	Maybe we should change * bootstrap mode to do the cd, and save a few cycles/bytes here.) */static char *filepath(const char *filename){	char	   *buf;	/* Not an absolute path name? Then fill in with database path... */	if (!is_absolute_path(filename))	{		buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);		sprintf(buf, "%s/%s", DatabasePath, filename);	}	else		buf = pstrdup(filename);#ifdef FILEDEBUG	printf("filepath: path is %s\n", buf);#endif	return buf;}static intFileAccess(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;}/* *	Called when we get a shared invalidation message on some relation. */#ifdef NOT_USEDvoidFileInvalidate(File file){	Assert(FileIsValid(file));	if (!FileIsNotOpen(file))		LruDelete(file);}#endifstatic FilefileNameOpenFile(FileName fileName,				 int fileFlags,				 int fileMode){	char	   *fnamecopy;	File		file;	Vfd		   *vfdP;	DO_DB(elog(LOG, "fileNameOpenFile: %s %x %o",			   fileName, fileFlags, fileMode));	/*	 * 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];	while (nfile + numAllocatedFiles + numAllocatedDirs >= max_safe_fds)	{		if (!ReleaseLruFile())			break;	}	vfdP->fd = BasicOpenFile(fileName, fileFlags, fileMode);	if (vfdP->fd < 0)	{		FreeVfd(file);		free(fnamecopy);		return -1;	}	++nfile;	DO_DB(elog(LOG, "fileNameOpenFile: success %d",			   vfdP->fd));	Insert(file);	vfdP->fileName = fnamecopy;	/* Saved flags are adjusted to be OK for re-opening file */	vfdP->fileFlags = fileFlags & ~(O_CREAT | 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. * * interXact: if true, don't close the file at end-of-transaction. In * most cases, you don't want temporary files to outlive the transaction * that created them, so this should be false -- but if you need * "somewhat" temporary storage, this might be useful. In either case, * the file is removed when the File is explicitly closed. */FileOpenTemporaryFile(bool interXact){	char		tempfilepath[MAXPGPATH];	File		file;	/*	 * Generate a tempfile name that should be unique within the current	 * database instance.	 */	snprintf(tempfilepath, sizeof(tempfilepath),			 "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,			 MyProcPid, tempFileCounter++);	/*	 * Open the file.  Note: we don't use O_EXCL, in case there is an	 * orphaned temp file that can be reused.	 */	file = FileNameOpenFile(tempfilepath,							O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,							0600);	if (file <= 0)	{		char	   *dirpath;		/*		 * We might need to create the pg_tempfiles subdirectory, if no		 * one has yet done so.		 *		 * Don't check for error from mkdir; it could fail if someone else		 * just did the same thing.  If it doesn't work then we'll bomb		 * out on the second create attempt, instead.		 */		dirpath = filepath(PG_TEMP_FILES_DIR);		mkdir(dirpath, S_IRWXU);		pfree(dirpath);		file = FileNameOpenFile(tempfilepath,								O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,								0600);		if (file <= 0)			elog(ERROR, "could not create temporary file \"%s\": %m",				 tempfilepath);	}	/* Mark it for deletion at close */	VfdCache[file].fdstate |= FD_TEMPORARY;	/* Mark it for deletion at EOXact */	if (!interXact)		VfdCache[file].fdstate |= FD_XACT_TEMPORARY;	return file;}/* * close a file when done with it */voidFileClose(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 (close(vfdP->fd))			elog(LOG, "failed to close \"%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(LOG, "failed to unlink \"%s\": %m",				 vfdP->fileName);	}	/*	 * Return the Vfd slot to the free list	 */	FreeVfd(file);}/* * close a file and forcibly delete the underlying Unix file */voidFileUnlink(File file)

⌨️ 快捷键说明

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