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

📄 smgr.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * It'd be nice to tell the stats collector to forget it immediately, too.	 * But we can't because we don't know the OID (and in cases involving	 * relfilenode swaps, it's not always clear which table OID to forget,	 * anyway).	 */	/*	 * And delete the physical files.	 *	 * Note: smgr_unlink must treat deletion failure as a WARNING, not an	 * ERROR, because we've already decided to commit or abort the current	 * xact.	 */	(*(smgrsw[which].smgr_unlink)) (rnode, isRedo);}/* *	smgrextend() -- Add a new block to a file. * *		The semantics are nearly the same as smgrwrite(): write at the *		specified position.  However, this is to be used for the case of *		extending a relation (i.e., blocknum is at or beyond the current *		EOF).  Note that we assume writing a block beyond current EOF *		causes intervening file space to become filled with zeroes. */voidsmgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp){	(*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer, isTemp);}/* *	smgrread() -- read a particular block from a relation into the supplied *				  buffer. * *		This routine is called from the buffer manager in order to *		instantiate pages in the shared buffer cache.  All storage managers *		return pages in the format that POSTGRES expects. */voidsmgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer){	(*(smgrsw[reln->smgr_which].smgr_read)) (reln, blocknum, buffer);}/* *	smgrwrite() -- Write the supplied buffer out. * *		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 smgrextend(). * *		This is not a synchronous write -- the block is not necessarily *		on disk at return, only dumped out to the kernel.  However, *		provisions will be made to fsync the write before the next checkpoint. * *		isTemp indicates that the relation is a temp table (ie, is managed *		by the local-buffer manager).  In this case no provisions need be *		made to fsync the write before checkpointing. */voidsmgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp){	(*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer, isTemp);}/* *	smgrnblocks() -- Calculate the number of blocks in the *					 supplied relation. */BlockNumbersmgrnblocks(SMgrRelation reln){	return (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln);}/* *	smgrtruncate() -- Truncate supplied relation to the specified number *					  of blocks */voidsmgrtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp){	/*	 * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will	 * just drop them without bothering to write the contents.	 */	DropRelFileNodeBuffers(reln->smgr_rnode, isTemp, nblocks);	/*	 * Tell the free space map to forget anything it may have stored for the	 * about-to-be-deleted blocks.	We want to be sure it won't return bogus	 * block numbers later on.	 */	FreeSpaceMapTruncateRel(&reln->smgr_rnode, nblocks);	/* Do the truncation */	(*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, nblocks, isTemp);	if (!isTemp)	{		/*		 * Make an XLOG entry showing the file truncation.		 */		XLogRecPtr	lsn;		XLogRecData rdata;		xl_smgr_truncate xlrec;		xlrec.blkno = nblocks;		xlrec.rnode = reln->smgr_rnode;		rdata.data = (char *) &xlrec;		rdata.len = sizeof(xlrec);		rdata.buffer = InvalidBuffer;		rdata.next = NULL;		lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE, &rdata);	}}/* *	smgrimmedsync() -- Force the specified relation to stable storage. * *		Synchronously force all previous writes to the specified relation *		down to disk. * *		This is useful for building completely new relations (eg, new *		indexes).  Instead of incrementally WAL-logging the index build *		steps, we can just write completed index pages to disk with smgrwrite *		or smgrextend, and then fsync the completed index file before *		committing the transaction.  (This is sufficient for purposes of *		crash recovery, since it effectively duplicates forcing a checkpoint *		for the completed index.  But it is *not* sufficient if one wishes *		to use the WAL log for PITR or replication purposes: in that case *		we have to make WAL entries as well.) * *		The preceding writes should specify isTemp = true to avoid *		duplicative fsyncs. * *		Note that you need to do FlushRelationBuffers() first if there is *		any possibility that there are dirty buffers for the relation; *		otherwise the sync is not very meaningful. */voidsmgrimmedsync(SMgrRelation reln){	(*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln);}/* *	PostPrepare_smgr -- Clean up after a successful PREPARE * * What we have to do here is throw away the in-memory state about pending * relation deletes.  It's all been recorded in the 2PC state file and * it's no longer smgr's job to worry about it. */voidPostPrepare_smgr(void){	PendingRelDelete *pending;	PendingRelDelete *next;	for (pending = pendingDeletes; pending != NULL; pending = next)	{		next = pending->next;		pendingDeletes = next;		/* must explicitly free the list entry */		pfree(pending);	}}/* *	smgrDoPendingDeletes() -- Take care of relation deletes at end of xact. * * This also runs when aborting a subxact; we want to clean up a failed * subxact immediately. */voidsmgrDoPendingDeletes(bool isCommit){	int			nestLevel = GetCurrentTransactionNestLevel();	PendingRelDelete *pending;	PendingRelDelete *prev;	PendingRelDelete *next;	prev = NULL;	for (pending = pendingDeletes; pending != NULL; pending = next)	{		next = pending->next;		if (pending->nestLevel < nestLevel)		{			/* outer-level entries should not be processed yet */			prev = pending;		}		else		{			/* unlink list entry first, so we don't retry on failure */			if (prev)				prev->next = next;			else				pendingDeletes = next;			/* do deletion if called for */			if (pending->atCommit == isCommit)				smgr_internal_unlink(pending->relnode,									 pending->which,									 pending->isTemp,									 false);			/* must explicitly free the list entry */			pfree(pending);			/* prev does not change */		}	}}/* * smgrGetPendingDeletes() -- Get a list of relations to be deleted. * * The return value is the number of relations scheduled for termination. * *ptr is set to point to a freshly-palloc'd array of RelFileNodes. * If there are no relations to be deleted, *ptr is set to NULL. * * If haveNonTemp isn't NULL, the bool it points to gets set to true if * there is any non-temp table pending to be deleted; false if not. * * Note that the list does not include anything scheduled for termination * by upper-level transactions. */intsmgrGetPendingDeletes(bool forCommit, RelFileNode **ptr, bool *haveNonTemp){	int			nestLevel = GetCurrentTransactionNestLevel();	int			nrels;	RelFileNode *rptr;	PendingRelDelete *pending;	nrels = 0;	if (haveNonTemp)		*haveNonTemp = false;	for (pending = pendingDeletes; pending != NULL; pending = pending->next)	{		if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)			nrels++;	}	if (nrels == 0)	{		*ptr = NULL;		return 0;	}	rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));	*ptr = rptr;	for (pending = pendingDeletes; pending != NULL; pending = pending->next)	{		if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)			*rptr++ = pending->relnode;		if (haveNonTemp && !pending->isTemp)			*haveNonTemp = true;	}	return nrels;}/* * AtSubCommit_smgr() --- Take care of subtransaction commit. * * Reassign all items in the pending-deletes list to the parent transaction. */voidAtSubCommit_smgr(void){	int			nestLevel = GetCurrentTransactionNestLevel();	PendingRelDelete *pending;	for (pending = pendingDeletes; pending != NULL; pending = pending->next)	{		if (pending->nestLevel >= nestLevel)			pending->nestLevel = nestLevel - 1;	}}/* * AtSubAbort_smgr() --- Take care of subtransaction abort. * * Delete created relations and forget about deleted relations. * We can execute these operations immediately because we know this * subtransaction will not commit. */voidAtSubAbort_smgr(void){	smgrDoPendingDeletes(false);}/* *	smgrcommit() -- Prepare to commit changes made during the current *					transaction. * *		This is called before we actually commit. */voidsmgrcommit(void){	int			i;	for (i = 0; i < NSmgr; i++)	{		if (smgrsw[i].smgr_commit)			(*(smgrsw[i].smgr_commit)) ();	}}/* *	smgrabort() -- Clean up after transaction abort. */voidsmgrabort(void){	int			i;	for (i = 0; i < NSmgr; i++)	{		if (smgrsw[i].smgr_abort)			(*(smgrsw[i].smgr_abort)) ();	}}/* *	smgrpreckpt() -- Prepare for checkpoint. */voidsmgrpreckpt(void){	int			i;	for (i = 0; i < NSmgr; i++)	{		if (smgrsw[i].smgr_pre_ckpt)			(*(smgrsw[i].smgr_pre_ckpt)) ();	}}/* *	smgrsync() -- Sync files to disk during checkpoint. */voidsmgrsync(void){	int			i;	for (i = 0; i < NSmgr; i++)	{		if (smgrsw[i].smgr_sync)			(*(smgrsw[i].smgr_sync)) ();	}}/* *	smgrpostckpt() -- Post-checkpoint cleanup. */voidsmgrpostckpt(void){	int			i;	for (i = 0; i < NSmgr; i++)	{		if (smgrsw[i].smgr_post_ckpt)			(*(smgrsw[i].smgr_post_ckpt)) ();	}}voidsmgr_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	if (info == XLOG_SMGR_CREATE)	{		xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);		SMgrRelation reln;		reln = smgropen(xlrec->rnode);		smgrcreate(reln, false, true);	}	else if (info == XLOG_SMGR_TRUNCATE)	{		xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);		SMgrRelation reln;		reln = smgropen(xlrec->rnode);		/*		 * Forcibly create relation if it doesn't exist (which suggests that		 * it was dropped somewhere later in the WAL sequence).  As in		 * XLogOpenRelation, we prefer to recreate the rel and replay the log		 * as best we can until the drop is seen.		 */		smgrcreate(reln, false, true);		/* Can't use smgrtruncate because it would try to xlog */		/*		 * First, force bufmgr to drop any buffers it has for the to-be-		 * truncated blocks.  We must do this, else subsequent XLogReadBuffer		 * operations will not re-extend the file properly.		 */		DropRelFileNodeBuffers(xlrec->rnode, false, xlrec->blkno);		/*		 * Tell the free space map to forget anything it may have stored for		 * the about-to-be-deleted blocks.	We want to be sure it won't return		 * bogus block numbers later on.		 */		FreeSpaceMapTruncateRel(&reln->smgr_rnode, xlrec->blkno);		/* Do the truncation */		(*(smgrsw[reln->smgr_which].smgr_truncate)) (reln,													 xlrec->blkno,													 false);		/* Also tell xlogutils.c about it */		XLogTruncateRelation(xlrec->rnode, xlrec->blkno);	}	else		elog(PANIC, "smgr_redo: unknown op code %u", info);}voidsmgr_desc(StringInfo buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	if (info == XLOG_SMGR_CREATE)	{		xl_smgr_create *xlrec = (xl_smgr_create *) rec;		appendStringInfo(buf, "file create: %u/%u/%u",						 xlrec->rnode.spcNode, xlrec->rnode.dbNode,						 xlrec->rnode.relNode);	}	else if (info == XLOG_SMGR_TRUNCATE)	{		xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;		appendStringInfo(buf, "file truncate: %u/%u/%u to %u blocks",						 xlrec->rnode.spcNode, xlrec->rnode.dbNode,						 xlrec->rnode.relNode, xlrec->blkno);	}	else		appendStringInfo(buf, "UNKNOWN");}

⌨️ 快捷键说明

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