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

📄 md.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any	 * more --- we mustn't create a block whose number actually is	 * InvalidBlockNumber.	 */	if (blocknum == InvalidBlockNumber)		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("cannot extend relation %u/%u/%u beyond %u blocks",						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode,						InvalidBlockNumber)));	v = _mdfd_getseg(reln, blocknum, isTemp, EXTENSION_CREATE);#ifndef LET_OS_MANAGE_FILESIZE	seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));	Assert(seekpos < BLCKSZ * RELSEG_SIZE);#else	seekpos = (long) (BLCKSZ * (blocknum));#endif	/*	 * Note: because caller usually obtained blocknum by calling mdnblocks,	 * which did a seek(SEEK_END), this seek is often redundant and will be	 * optimized away by fd.c.	It's not redundant, however, if there is a	 * partial page at the end of the file. In that case we want to try to	 * overwrite the partial page with a full page.  It's also not redundant	 * if bufmgr.c had to dump another buffer of the same file to make room	 * for the new page's buffer.	 */	if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not seek to block %u of relation %u/%u/%u: %m",						blocknum,						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode)));	if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)	{		if (nbytes < 0)			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not extend relation %u/%u/%u: %m",							reln->smgr_rnode.spcNode,							reln->smgr_rnode.dbNode,							reln->smgr_rnode.relNode),					 errhint("Check free disk space.")));		/* short write: complain appropriately */		ereport(ERROR,				(errcode(ERRCODE_DISK_FULL),				 errmsg("could not extend relation %u/%u/%u: wrote only %d of %d bytes at block %u",						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode,						nbytes, BLCKSZ, blocknum),				 errhint("Check free disk space.")));	}	if (!isTemp)		register_dirty_segment(reln, v);#ifndef LET_OS_MANAGE_FILESIZE	Assert(_mdnblocks(reln, v) <= ((BlockNumber) RELSEG_SIZE));#endif}/* *	mdopen() -- Open the specified relation. * * Note we only open the first segment, when there are multiple segments. * * If first segment is not present, either ereport or return NULL according * to "behavior".  We treat EXTENSION_CREATE the same as EXTENSION_FAIL; * EXTENSION_CREATE means it's OK to extend an existing relation, not to * invent one out of whole cloth. */static MdfdVec *mdopen(SMgrRelation reln, ExtensionBehavior behavior){	MdfdVec    *mdfd;	char	   *path;	File		fd;	/* No work if already open */	if (reln->md_fd)		return reln->md_fd;	path = relpath(reln->smgr_rnode);	fd = PathNameOpenFile(path, O_RDWR | PG_BINARY, 0600);	if (fd < 0)	{		/*		 * During bootstrap, there are cases where a system relation will be		 * accessed (by internal backend processes) before the bootstrap		 * script nominally creates it.  Therefore, accept mdopen() as a		 * substitute for mdcreate() in bootstrap mode only. (See mdcreate)		 */		if (IsBootstrapProcessingMode())			fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600);		if (fd < 0)		{			pfree(path);			if (behavior == EXTENSION_RETURN_NULL &&				FILE_POSSIBLY_DELETED(errno))				return NULL;			ereport(ERROR,					(errcode_for_file_access(),					 errmsg("could not open relation %u/%u/%u: %m",							reln->smgr_rnode.spcNode,							reln->smgr_rnode.dbNode,							reln->smgr_rnode.relNode)));		}	}	pfree(path);	reln->md_fd = mdfd = _fdvec_alloc();	mdfd->mdfd_vfd = fd;	mdfd->mdfd_segno = 0;#ifndef LET_OS_MANAGE_FILESIZE	mdfd->mdfd_chain = NULL;	Assert(_mdnblocks(reln, mdfd) <= ((BlockNumber) RELSEG_SIZE));#endif	return mdfd;}/* *	mdclose() -- Close the specified relation, if it isn't closed already. */voidmdclose(SMgrRelation reln){	MdfdVec    *v = reln->md_fd;	/* No work if already closed */	if (v == NULL)		return;	reln->md_fd = NULL;			/* prevent dangling pointer after error */#ifndef LET_OS_MANAGE_FILESIZE	while (v != NULL)	{		MdfdVec    *ov = v;		/* if not closed already */		if (v->mdfd_vfd >= 0)			FileClose(v->mdfd_vfd);		/* Now free vector */		v = v->mdfd_chain;		pfree(ov);	}#else	if (v->mdfd_vfd >= 0)		FileClose(v->mdfd_vfd);	pfree(v);#endif}/* *	mdread() -- Read the specified block from a relation. */voidmdread(SMgrRelation reln, BlockNumber blocknum, char *buffer){	long		seekpos;	int			nbytes;	MdfdVec    *v;	v = _mdfd_getseg(reln, blocknum, false, EXTENSION_FAIL);#ifndef LET_OS_MANAGE_FILESIZE	seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));	Assert(seekpos < BLCKSZ * RELSEG_SIZE);#else	seekpos = (long) (BLCKSZ * (blocknum));#endif	if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not seek to block %u of relation %u/%u/%u: %m",						blocknum,						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode)));	if ((nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)	{		if (nbytes < 0)			ereport(ERROR,					(errcode_for_file_access(),				   errmsg("could not read block %u of relation %u/%u/%u: %m",						  blocknum,						  reln->smgr_rnode.spcNode,						  reln->smgr_rnode.dbNode,						  reln->smgr_rnode.relNode)));		/*		 * Short read: we are at or past EOF, or we read a partial block at		 * EOF.  Normally this is an error; upper levels should never try to		 * read a nonexistent block.  However, if zero_damaged_pages is ON or		 * we are InRecovery, we should instead return zeroes without		 * complaining.  This allows, for example, the case of trying to		 * update a block that was later truncated away.		 */		if (zero_damaged_pages || InRecovery)			MemSet(buffer, 0, BLCKSZ);		else			ereport(ERROR,					(errcode(ERRCODE_DATA_CORRUPTED),					 errmsg("could not read block %u of relation %u/%u/%u: read only %d of %d bytes",							blocknum,							reln->smgr_rnode.spcNode,							reln->smgr_rnode.dbNode,							reln->smgr_rnode.relNode,							nbytes, BLCKSZ)));	}}/* *	mdwrite() -- Write the supplied block at the appropriate location. * *		This is to be used only for updating already-existing blocks of a *		relation (ie, those before the current EOF).  To extend a relation, *		use mdextend(). */voidmdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp){	long		seekpos;	int			nbytes;	MdfdVec    *v;	/* This assert is too expensive to have on normally ... */#ifdef CHECK_WRITE_VS_EXTEND	Assert(blocknum < mdnblocks(reln));#endif	v = _mdfd_getseg(reln, blocknum, isTemp, EXTENSION_FAIL);#ifndef LET_OS_MANAGE_FILESIZE	seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)));	Assert(seekpos < BLCKSZ * RELSEG_SIZE);#else	seekpos = (long) (BLCKSZ * (blocknum));#endif	if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)		ereport(ERROR,				(errcode_for_file_access(),				 errmsg("could not seek to block %u of relation %u/%u/%u: %m",						blocknum,						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode)));	if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)	{		if (nbytes < 0)			ereport(ERROR,					(errcode_for_file_access(),				  errmsg("could not write block %u of relation %u/%u/%u: %m",						 blocknum,						 reln->smgr_rnode.spcNode,						 reln->smgr_rnode.dbNode,						 reln->smgr_rnode.relNode)));		/* short write: complain appropriately */		ereport(ERROR,				(errcode(ERRCODE_DISK_FULL),				 errmsg("could not write block %u of relation %u/%u/%u: wrote only %d of %d bytes",						blocknum,						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode,						nbytes, BLCKSZ),				 errhint("Check free disk space.")));	}	if (!isTemp)		register_dirty_segment(reln, v);}/* *	mdnblocks() -- Get the number of blocks stored in a relation. * *		Important side effect: all active segments of the relation are opened *		and added to the mdfd_chain list.  If this routine has not been *		called, then only segments up to the last one actually touched *		are present in the chain. */BlockNumbermdnblocks(SMgrRelation reln){	MdfdVec    *v = mdopen(reln, EXTENSION_FAIL);#ifndef LET_OS_MANAGE_FILESIZE	BlockNumber nblocks;	BlockNumber segno = 0;	/*	 * Skip through any segments that aren't the last one, to avoid redundant	 * seeks on them.  We have previously verified that these segments are	 * exactly RELSEG_SIZE long, and it's useless to recheck that each time.	 *	 * NOTE: this assumption could only be wrong if another backend has	 * truncated the relation.	We rely on higher code levels to handle that	 * scenario by closing and re-opening the md fd, which is handled via	 * relcache flush.	(Since the bgwriter doesn't participate in relcache	 * flush, it could have segment chain entries for inactive segments;	 * that's OK because the bgwriter never needs to compute relation size.)	 */	while (v->mdfd_chain != NULL)	{		segno++;		v = v->mdfd_chain;	}	for (;;)	{		nblocks = _mdnblocks(reln, v);		if (nblocks > ((BlockNumber) RELSEG_SIZE))			elog(FATAL, "segment too big");		if (nblocks < ((BlockNumber) RELSEG_SIZE))			return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;		/*		 * If segment is exactly RELSEG_SIZE, advance to next one.		 */		segno++;		if (v->mdfd_chain == NULL)		{			/*			 * Because we pass O_CREAT, we will create the next segment (with			 * zero length) immediately, if the last segment is of length			 * RELSEG_SIZE.  While perhaps not strictly necessary, this keeps			 * the logic simple.			 */			v->mdfd_chain = _mdfd_openseg(reln, segno, O_CREAT);			if (v->mdfd_chain == NULL)				ereport(ERROR,						(errcode_for_file_access(),				 errmsg("could not open segment %u of relation %u/%u/%u: %m",						segno,						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode)));		}		v = v->mdfd_chain;	}#else	return _mdnblocks(reln, v);#endif}/* *	mdtruncate() -- Truncate relation to specified number of blocks. */voidmdtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp){	MdfdVec    *v;	BlockNumber curnblk;#ifndef LET_OS_MANAGE_FILESIZE	BlockNumber priorblocks;#endif	/*	 * NOTE: mdnblocks makes sure we have opened all active segments, so that	 * truncation loop will get them all!	 */	curnblk = mdnblocks(reln);	if (nblocks > curnblk)	{		/* Bogus request ... but no complaint if InRecovery */		if (InRecovery)			return;		ereport(ERROR,				(errmsg("could not truncate relation %u/%u/%u to %u blocks: it's only %u blocks now",						reln->smgr_rnode.spcNode,						reln->smgr_rnode.dbNode,						reln->smgr_rnode.relNode,						nblocks, curnblk)));	}	if (nblocks == curnblk)		return;					/* no work */	v = mdopen(reln, EXTENSION_FAIL);#ifndef LET_OS_MANAGE_FILESIZE	priorblocks = 0;	while (v != NULL)	{		MdfdVec    *ov = v;		if (priorblocks > nblocks)		{

⌨️ 快捷键说明

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