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

📄 fd.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
{	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);}intFileRead(File file, char *buffer, int amount){	int			returnCode;	Assert(FileIsValid(file));	DO_DB(elog(LOG, "FileRead: %d (%s) %ld %d %p",			   file, VfdCache[file].fileName,			   VfdCache[file].seekPos, amount, buffer));	FileAccess(file);	returnCode = read(VfdCache[file].fd, buffer, amount);	if (returnCode > 0)		VfdCache[file].seekPos += returnCode;	else		VfdCache[file].seekPos = FileUnknownPos;	return returnCode;}intFileWrite(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));	FileAccess(file);	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		VfdCache[file].seekPos = FileUnknownPos;	return returnCode;}longFileSeek(File file, long offset, int whence){	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:				FileAccess(file);				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;}/* * XXX not actually used but here for completeness */#ifdef NOT_USEDlongFileTell(File file){	Assert(FileIsValid(file));	DO_DB(elog(LOG, "FileTell %d (%s)",			   file, VfdCache[file].fileName));	return VfdCache[file].seekPos;}#endifintFileTruncate(File file, long offset){	int			returnCode;	Assert(FileIsValid(file));	DO_DB(elog(LOG, "FileTruncate %d (%s)",			   file, VfdCache[file].fileName));	FileAccess(file);	returnCode = ftruncate(VfdCache[file].fd, (size_t) offset);	return returnCode;}/* * 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(char *name, char *mode){	FILE	   *file;	DO_DB(elog(LOG, "AllocateFile: Allocated %d", numAllocatedFiles));	/*	 * The test against MAX_ALLOCATED_FILES 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 (numAllocatedFiles >= MAX_ALLOCATED_FILES ||		numAllocatedFiles + numAllocatedDirs >= max_safe_fds - 1)		elog(ERROR, "too many private files demanded");TryAgain:	if ((file = fopen(name, mode)) != NULL)	{		allocatedFiles[numAllocatedFiles] = file;		numAllocatedFiles++;		return 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;}voidFreeFile(FILE *file){	int			i;	DO_DB(elog(LOG, "FreeFile: Allocated %d", numAllocatedFiles));	/* Remove file from list of allocated files, if it's present */	for (i = numAllocatedFiles; --i >= 0;)	{		if (allocatedFiles[i] == file)		{			numAllocatedFiles--;			allocatedFiles[i] = allocatedFiles[numAllocatedFiles];			break;		}	}	if (i < 0)		elog(WARNING, "file passed to FreeFile was not obtained from AllocateFile");	fclose(file);}/* * 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", numAllocatedDirs));	/*	 * The test against MAX_ALLOCATED_DIRS prevents us from overflowing	 * allocatedDirs[]; the test against max_safe_fds prevents AllocateDir	 * from hogging every one of the available FDs, which'd lead to infinite	 * looping.	 */	if (numAllocatedDirs >= MAX_ALLOCATED_DIRS ||		numAllocatedDirs + numAllocatedFiles >= max_safe_fds - 1)		elog(ERROR, "too many private dirs demanded");TryAgain:	if ((dir = opendir(dirname)) != NULL)	{		allocatedDirs[numAllocatedDirs] = dir;		numAllocatedDirs++;		return dir;	}	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;}/* * Close a directory opened with AllocateDir. * * Note we do not check closedir's return value --- it is up to the caller * to handle close errors. */intFreeDir(DIR *dir){	int			i;	DO_DB(elog(LOG, "FreeDir: Allocated %d", numAllocatedDirs));	/* Remove dir from list of allocated dirs, if it's present */	for (i = numAllocatedDirs; --i >= 0;)	{		if (allocatedDirs[i] == dir)		{			numAllocatedDirs--;			allocatedDirs[i] = allocatedDirs[numAllocatedDirs];			break;		}	}	if (i < 0)		elog(WARNING, "dir passed to FreeDir was not obtained from AllocateDir");	return closedir(dir);}/* * 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(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);		}	}}/* * AtEOXact_Files * * This routine is called during transaction commit or abort (it doesn't * particularly care which).  All still-open per-transaction temporary file * VFDs are closed, which also causes the underlying files to be * deleted. Furthermore, all "allocated" stdio files are closed. */voidAtEOXact_Files(void){	CleanupTempFiles(false);}/* * AtProcExit_Files * * on_proc_exit hook to clean up temp files during backend shutdown. * Here, we want to clean up *all* temp files including interXact ones. */static voidAtProcExit_Files(void){	CleanupTempFiles(true);}/* * 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 voidCleanupTempFiles(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.				 */				if (isProcExit || (fdstate & FD_XACT_TEMPORARY))					FileClose(i);			}		}	}	while (numAllocatedFiles > 0)		FreeFile(allocatedFiles[0]);	while (numAllocatedDirs > 0)		FreeDir(allocatedDirs[0]);}/* * Remove temporary files left over from a prior postmaster session * * This should be called during postmaster startup.  It will forcibly * remove any leftover files created by OpenTemporaryFile. * * NOTE: we could, but don't, call this during a post-backend-crash restart * cycle.  The argument for not doing it is that someone might want to examine * the temp files for debugging purposes.  This does however mean that * OpenTemporaryFile had better allow for collision with an existing temp * file name. */voidRemovePgTempFiles(void){	char		db_path[MAXPGPATH];	char		temp_path[MAXPGPATH];	char		rm_path[MAXPGPATH];	DIR		   *db_dir;	DIR		   *temp_dir;	struct dirent *db_de;	struct dirent *temp_de;	/*	 * Cycle through pg_tempfiles for all databases and remove old temp	 * files.	 */	snprintf(db_path, sizeof(db_path), "%s/base", DataDir);	if ((db_dir = AllocateDir(db_path)) != NULL)	{		while ((db_de = readdir(db_dir)) != NULL)		{			if (strcmp(db_de->d_name, ".") == 0 ||				strcmp(db_de->d_name, "..") == 0)				continue;			snprintf(temp_path, sizeof(temp_path),					 "%s/%s/%s",					 db_path, db_de->d_name,					 PG_TEMP_FILES_DIR);			if ((temp_dir = AllocateDir(temp_path)) != NULL)			{				while ((temp_de = readdir(temp_dir)) != NULL)				{					if (strcmp(temp_de->d_name, ".") == 0 ||						strcmp(temp_de->d_name, "..") == 0)						continue;					snprintf(rm_path, sizeof(temp_path),							 "%s/%s/%s/%s",							 db_path, db_de->d_name,							 PG_TEMP_FILES_DIR,							 temp_de->d_name);					if (strncmp(temp_de->d_name,								PG_TEMP_FILE_PREFIX,								strlen(PG_TEMP_FILE_PREFIX)) == 0)						unlink(rm_path);					else						elog(LOG,							 "unexpected file found in temporary-files directory: \"%s\"",							 rm_path);				}				FreeDir(temp_dir);			}		}		FreeDir(db_dir);	}}

⌨️ 快捷键说明

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