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

📄 bufmgr.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (rel->rd_myxactonly)	{		for (i = 0; i < NLocBuffer; i++)		{			buf = &LocalBufferDescriptors[i];			if (buf->tag.relId.relId == RelationGetRelid(rel) &&				buf->tag.blockNum >= block)			{				if (buf->flags & BM_DIRTY)				{					elog(NOTICE, "BlowawayRelationBuffers(%s (local), %u): block %u is dirty",					rel->rd_rel->relname.data, block, buf->tag.blockNum);					return -1;				}				if (LocalRefCount[i] > 0)				{					elog(NOTICE, "BlowawayRelationBuffers(%s (local), %u): block %u is referenced (%d)",						 rel->rd_rel->relname.data, block,						 buf->tag.blockNum, LocalRefCount[i]);					return -2;				}				buf->tag.relId.relId = InvalidOid;			}		}		return 0;	}	SpinAcquire(BufMgrLock);	for (i = 0; i < NBuffers; i++)	{		buf = &BufferDescriptors[i];		if (buf->tag.relId.dbId == MyDatabaseId &&			buf->tag.relId.relId == RelationGetRelid(rel) &&			buf->tag.blockNum >= block)		{			if (buf->flags & BM_DIRTY)			{				elog(NOTICE, "BlowawayRelationBuffers(%s, %u): block %u is dirty (private %d, last %d, global %d)",					 buf->sb_relname, block, buf->tag.blockNum,					 PrivateRefCount[i], LastRefCount[i], buf->refcount);				SpinRelease(BufMgrLock);				return -1;			}			if (!(buf->flags & BM_FREE))			{				elog(NOTICE, "BlowawayRelationBuffers(%s, %u): block %u is referenced (private %d, last %d, global %d)",					 buf->sb_relname, block, buf->tag.blockNum,					 PrivateRefCount[i], LastRefCount[i], buf->refcount);				SpinRelease(BufMgrLock);				return -2;			}			BufTableDelete(buf);		}	}	SpinRelease(BufMgrLock);	return 0;}#undef ReleaseBuffer/* * ReleaseBuffer -- remove the pin on a buffer without *		marking it dirty. * */intReleaseBuffer(Buffer buffer){	BufferDesc *bufHdr;	if (BufferIsLocal(buffer))	{		Assert(LocalRefCount[-buffer - 1] > 0);		LocalRefCount[-buffer - 1]--;		return STATUS_OK;	}	if (BAD_BUFFER_ID(buffer))		return STATUS_ERROR;	bufHdr = &BufferDescriptors[buffer - 1];	Assert(PrivateRefCount[buffer - 1] > 0);	PrivateRefCount[buffer - 1]--;	if (PrivateRefCount[buffer - 1] == 0 && LastRefCount[buffer - 1] == 0)	{		/*		 * only release buffer if it is not pinned in previous ExecMain		 * levels		 */		SpinAcquire(BufMgrLock);		bufHdr->refcount--;		if (bufHdr->refcount == 0)		{			AddBufferToFreelist(bufHdr);			bufHdr->flags |= BM_FREE;		}		if (CommitInfoNeedsSave[buffer - 1])		{			bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED);			CommitInfoNeedsSave[buffer - 1] = 0;		}		SpinRelease(BufMgrLock);	}	return STATUS_OK;}#ifdef NOT_USEDvoidIncrBufferRefCount_Debug(char *file, int line, Buffer buffer){	IncrBufferRefCount(buffer);	if (ShowPinTrace && !BufferIsLocal(buffer) && is_userbuffer(buffer))	{		BufferDesc *buf = &BufferDescriptors[buffer - 1];		fprintf(stderr, "PIN(Incr) %ld relname = %s, blockNum = %d, \refcount = %ld, file: %s, line: %d\n",				buffer, buf->sb_relname, buf->tag.blockNum,				PrivateRefCount[buffer - 1], file, line);	}}#endif#ifdef NOT_USEDvoidReleaseBuffer_Debug(char *file, int line, Buffer buffer){	ReleaseBuffer(buffer);	if (ShowPinTrace && !BufferIsLocal(buffer) && is_userbuffer(buffer))	{		BufferDesc *buf = &BufferDescriptors[buffer - 1];		fprintf(stderr, "UNPIN(Rel) %ld relname = %s, blockNum = %d, \refcount = %ld, file: %s, line: %d\n",				buffer, buf->sb_relname, buf->tag.blockNum,				PrivateRefCount[buffer - 1], file, line);	}}#endif#ifdef NOT_USEDintReleaseAndReadBuffer_Debug(char *file,						   int line,						   Buffer buffer,						   Relation relation,						   BlockNumber blockNum){	bool		bufferValid;	Buffer		b;	bufferValid = BufferIsValid(buffer);	b = ReleaseAndReadBuffer(buffer, relation, blockNum);	if (ShowPinTrace && bufferValid && BufferIsLocal(buffer)		&& is_userbuffer(buffer))	{		BufferDesc *buf = &BufferDescriptors[buffer - 1];		fprintf(stderr, "UNPIN(Rel&Rd) %ld relname = %s, blockNum = %d, \refcount = %ld, file: %s, line: %d\n",				buffer, buf->sb_relname, buf->tag.blockNum,				PrivateRefCount[buffer - 1], file, line);	}	if (ShowPinTrace && BufferIsLocal(buffer) && is_userbuffer(buffer))	{		BufferDesc *buf = &BufferDescriptors[b - 1];		fprintf(stderr, "PIN(Rel&Rd) %ld relname = %s, blockNum = %d, \refcount = %ld, file: %s, line: %d\n",				b, buf->sb_relname, buf->tag.blockNum,				PrivateRefCount[b - 1], file, line);	}	return b;}#endif#ifdef BMTRACE/* *	trace allocations and deallocations in a circular buffer in *	shared memory.	check the buffer before doing the allocation, *	and die if there's anything fishy. */_bm_trace(Oid dbId, Oid relId, int blkNo, int bufNo, int allocType){	long		start,				cur;	bmtrace    *tb;	start = *CurTraceBuf;	if (start > 0)		cur = start - 1;	else		cur = BMT_LIMIT - 1;	for (;;)	{		tb = &TraceBuf[cur];		if (tb->bmt_op != BMT_NOTUSED)		{			if (tb->bmt_buf == bufNo)			{				if ((tb->bmt_op == BMT_DEALLOC)					|| (tb->bmt_dbid == dbId && tb->bmt_relid == relId						&& tb->bmt_blkno == blkNo))					goto okay;				/* die holding the buffer lock */				_bm_die(dbId, relId, blkNo, bufNo, allocType, start, cur);			}		}		if (cur == start)			goto okay;		if (cur == 0)			cur = BMT_LIMIT - 1;		else			cur--;	}okay:	tb = &TraceBuf[start];	tb->bmt_pid = MyProcPid;	tb->bmt_buf = bufNo;	tb->bmt_dbid = dbId;	tb->bmt_relid = relId;	tb->bmt_blkno = blkNo;	tb->bmt_op = allocType;	*CurTraceBuf = (start + 1) % BMT_LIMIT;}_bm_die(Oid dbId, Oid relId, int blkNo, int bufNo,		int allocType, long start, long cur){	FILE	   *fp;	bmtrace    *tb;	int			i;	tb = &TraceBuf[cur];	if ((fp = AllocateFile("/tmp/death_notice", "w")) == NULL)		elog(FATAL, "buffer alloc trace error and can't open log file");	fprintf(fp, "buffer alloc trace detected the following error:\n\n");	fprintf(fp, "    buffer %d being %s inconsistently with a previous %s\n\n",		 bufNo, (allocType == BMT_DEALLOC ? "deallocated" : "allocated"),			(tb->bmt_op == BMT_DEALLOC ? "deallocation" : "allocation"));	fprintf(fp, "the trace buffer contains:\n");	i = start;	for (;;)	{		tb = &TraceBuf[i];		if (tb->bmt_op != BMT_NOTUSED)		{			fprintf(fp, "     [%3d]%spid %d buf %2d for <%d,%u,%d> ",					i, (i == cur ? " ---> " : "\t"),					tb->bmt_pid, tb->bmt_buf,					tb->bmt_dbid, tb->bmt_relid, tb->bmt_blkno);			switch (tb->bmt_op)			{				case BMT_ALLOCFND:					fprintf(fp, "allocate (found)\n");					break;				case BMT_ALLOCNOTFND:					fprintf(fp, "allocate (not found)\n");					break;				case BMT_DEALLOC:					fprintf(fp, "deallocate\n");					break;				default:					fprintf(fp, "unknown op type %d\n", tb->bmt_op);					break;			}		}		i = (i + 1) % BMT_LIMIT;		if (i == start)			break;	}	fprintf(fp, "\noperation causing error:\n");	fprintf(fp, "\tpid %d buf %d for <%d,%u,%d> ",			getpid(), bufNo, dbId, relId, blkNo);	switch (allocType)	{		case BMT_ALLOCFND:			fprintf(fp, "allocate (found)\n");			break;		case BMT_ALLOCNOTFND:			fprintf(fp, "allocate (not found)\n");			break;		case BMT_DEALLOC:			fprintf(fp, "deallocate\n");			break;		default:			fprintf(fp, "unknown op type %d\n", allocType);			break;	}	FreeFile(fp);	kill(getpid(), SIGILL);}#endif	 /* BMTRACE */voidBufferRefCountReset(int *refcountsave){	int			i;	for (i = 0; i < NBuffers; i++)	{		refcountsave[i] = PrivateRefCount[i];		LastRefCount[i] += PrivateRefCount[i];		PrivateRefCount[i] = 0;	}}voidBufferRefCountRestore(int *refcountsave){	int			i;	for (i = 0; i < NBuffers; i++)	{		PrivateRefCount[i] = refcountsave[i];		LastRefCount[i] -= refcountsave[i];		refcountsave[i] = 0;	}}intSetBufferWriteMode(int mode){	int			old;	old = WriteMode;	WriteMode = mode;	return old;}voidSetBufferCommitInfoNeedsSave(Buffer buffer){	if (!BufferIsLocal(buffer))		CommitInfoNeedsSave[buffer - 1]++;}voidUnlockBuffers(){	BufferDesc *buf;	int			i;	for (i = 0; i < NBuffers; i++)	{		if (BufferLocks[i] == 0)			continue;		Assert(BufferIsValid(i + 1));		buf = &(BufferDescriptors[i]);#ifdef HAS_TEST_AND_SET		S_LOCK(&(buf->cntx_lock));#else		IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);#endif		if (BufferLocks[i] & BL_R_LOCK)		{			Assert(buf->r_locks > 0);			(buf->r_locks)--;		}		if (BufferLocks[i] & BL_RI_LOCK)		{			/* 			 * Someone else could remove our RI lock when acquiring			 * W lock. This is possible if we came here from elog(ERROR)			 * from IpcSemaphore{Lock|Unlock}(WaitCLSemId). And so we			 * don't do Assert(buf->ri_lock) here.			 */			buf->ri_lock = false;		}		if (BufferLocks[i] & BL_W_LOCK)		{			Assert(buf->w_lock);			buf->w_lock = false;		}#ifdef HAS_TEST_AND_SET		S_UNLOCK(&(buf->cntx_lock));#else		IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);#endif		BufferLocks[i] = 0;	}}voidLockBuffer(Buffer buffer, int mode){	BufferDesc *buf;	Assert(BufferIsValid(buffer));	if (BufferIsLocal(buffer))		return;	buf = &(BufferDescriptors[buffer - 1]);#ifdef HAS_TEST_AND_SET	S_LOCK(&(buf->cntx_lock));#else	IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);#endif	if (mode == BUFFER_LOCK_UNLOCK)	{		if (BufferLocks[buffer - 1] & BL_R_LOCK)		{			Assert(buf->r_locks > 0);			Assert(!(buf->w_lock));			Assert(!(BufferLocks[buffer - 1] & (BL_W_LOCK | BL_RI_LOCK)))				(buf->r_locks)--;			BufferLocks[buffer - 1] &= ~BL_R_LOCK;		}		else if (BufferLocks[buffer - 1] & BL_W_LOCK)		{			Assert(buf->w_lock);			Assert(buf->r_locks == 0);			Assert(!(BufferLocks[buffer - 1] & (BL_R_LOCK | BL_RI_LOCK)))				buf->w_lock = false;			BufferLocks[buffer - 1] &= ~BL_W_LOCK;		}		else			elog(ERROR, "UNLockBuffer: buffer %u is not locked", buffer);	}	else if (mode == BUFFER_LOCK_SHARE)	{		unsigned	i = 0;		Assert(!(BufferLocks[buffer - 1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK)));		while (buf->ri_lock || buf->w_lock)		{#ifdef HAS_TEST_AND_SET			S_UNLOCK(&(buf->cntx_lock));			s_lock_sleep(i++);			S_LOCK(&(buf->cntx_lock));#else			IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);			s_lock_sleep(i++);			IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);#endif		}		(buf->r_locks)++;		BufferLocks[buffer - 1] |= BL_R_LOCK;	}	else if (mode == BUFFER_LOCK_EXCLUSIVE)	{		unsigned	i = 0;		Assert(!(BufferLocks[buffer - 1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK)));		while (buf->r_locks > 0 || buf->w_lock)		{			if (buf->r_locks > 3 || (BufferLocks[buffer - 1] & BL_RI_LOCK))			{				/*				 * Our RI lock might be removed by concurrent W lock				 * acquiring (see what we do with RI locks below				 * when our own W acquiring succeeded) and so				 * we set RI lock again if we already did this.				 */				BufferLocks[buffer - 1] |= BL_RI_LOCK;				buf->ri_lock = true;			}#ifdef HAS_TEST_AND_SET			S_UNLOCK(&(buf->cntx_lock));			s_lock_sleep(i++);			S_LOCK(&(buf->cntx_lock));#else			IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);			s_lock_sleep(i++);			IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);#endif		}		buf->w_lock = true;		BufferLocks[buffer - 1] |= BL_W_LOCK;		if (BufferLocks[buffer - 1] & BL_RI_LOCK)		{			/*			 * It's possible to remove RI locks acquired by another			 * W lockers here, but they'll take care about it.			 */			buf->ri_lock = false;			BufferLocks[buffer - 1] &= ~BL_RI_LOCK;		}	}	else		elog(ERROR, "LockBuffer: unknown lock mode %d", mode);#ifdef HAS_TEST_AND_SET	S_UNLOCK(&(buf->cntx_lock));#else	IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);#endif}

⌨️ 快捷键说明

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