📄 bufmgr.c
字号:
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 + -