diff options
Diffstat (limited to 'src/backend/storage/buffer/localbuf.c')
-rw-r--r-- | src/backend/storage/buffer/localbuf.c | 115 |
1 files changed, 64 insertions, 51 deletions
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 940b80d165e..c9ba5ee00ff 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -45,13 +45,14 @@ BufferDesc *LocalBufferDescriptors = NULL; Block *LocalBufferBlockPointers = NULL; int32 *LocalRefCount = NULL; -static int nextFreeLocalBuf = 0; +static int nextFreeLocalBufId = 0; static HTAB *LocalBufHash = NULL; static void InitLocalBuffers(void); static Block GetLocalBufferStorage(void); +static Buffer GetLocalVictimBuffer(void); /* @@ -113,10 +114,9 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, BufferTag newTag; /* identity of requested block */ LocalBufferLookupEnt *hresult; BufferDesc *bufHdr; - int b; - int trycounter; + Buffer victim_buffer; + int bufid; bool found; - uint32 buf_state; InitBufferTag(&newTag, &smgr->smgr_rlocator.locator, forkNum, blockNum); @@ -130,23 +130,51 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, if (hresult) { - b = hresult->id; - bufHdr = GetLocalBufferDescriptor(b); + bufid = hresult->id; + bufHdr = GetLocalBufferDescriptor(bufid); Assert(BufferTagsEqual(&bufHdr->tag, &newTag)); -#ifdef LBDEBUG - fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n", - smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum, -b - 1); -#endif *foundPtr = PinLocalBuffer(bufHdr, true); - return bufHdr; } + else + { + uint32 buf_state; -#ifdef LBDEBUG - fprintf(stderr, "LB ALLOC (%u,%d,%d) %d\n", - smgr->smgr_rlocator.locator.relNumber, forkNum, blockNum, - -nextFreeLocalBuf - 1); -#endif + victim_buffer = GetLocalVictimBuffer(); + bufid = -victim_buffer - 1; + bufHdr = GetLocalBufferDescriptor(bufid); + + hresult = (LocalBufferLookupEnt *) + hash_search(LocalBufHash, &newTag, HASH_ENTER, &found); + if (found) /* shouldn't happen */ + elog(ERROR, "local buffer hash table corrupted"); + hresult->id = bufid; + + /* + * it's all ours now. + */ + bufHdr->tag = newTag; + + buf_state = pg_atomic_read_u32(&bufHdr->state); + buf_state &= ~(BUF_FLAG_MASK | BUF_USAGECOUNT_MASK); + buf_state |= BM_TAG_VALID | BUF_USAGECOUNT_ONE; + pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); + + *foundPtr = false; + } + + return bufHdr; +} + +static Buffer +GetLocalVictimBuffer(void) +{ + int victim_bufid; + int trycounter; + uint32 buf_state; + BufferDesc *bufHdr; + + ResourceOwnerEnlargeBuffers(CurrentResourceOwner); /* * Need to get a new buffer. We use a clock sweep algorithm (essentially @@ -155,14 +183,14 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, trycounter = NLocBuffer; for (;;) { - b = nextFreeLocalBuf; + victim_bufid = nextFreeLocalBufId; - if (++nextFreeLocalBuf >= NLocBuffer) - nextFreeLocalBuf = 0; + if (++nextFreeLocalBufId >= NLocBuffer) + nextFreeLocalBufId = 0; - bufHdr = GetLocalBufferDescriptor(b); + bufHdr = GetLocalBufferDescriptor(victim_bufid); - if (LocalRefCount[b] == 0) + if (LocalRefCount[victim_bufid] == 0) { buf_state = pg_atomic_read_u32(&bufHdr->state); @@ -186,6 +214,15 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, } /* + * lazy memory allocation: allocate space on first use of a buffer. + */ + if (LocalBufHdrGetBlock(bufHdr) == NULL) + { + /* Set pointer for use by BufferGetBlock() macro */ + LocalBufHdrGetBlock(bufHdr) = GetLocalBufferStorage(); + } + + /* * this buffer is not referenced but it might still be dirty. if that's * the case, write it out before reusing it! */ @@ -216,48 +253,24 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, } /* - * lazy memory allocation: allocate space on first use of a buffer. - */ - if (LocalBufHdrGetBlock(bufHdr) == NULL) - { - /* Set pointer for use by BufferGetBlock() macro */ - LocalBufHdrGetBlock(bufHdr) = GetLocalBufferStorage(); - } - - /* - * Update the hash table: remove old entry, if any, and make new one. + * Remove the victim buffer from the hashtable and mark as invalid. */ if (buf_state & BM_TAG_VALID) { + LocalBufferLookupEnt *hresult; + hresult = (LocalBufferLookupEnt *) hash_search(LocalBufHash, &bufHdr->tag, HASH_REMOVE, NULL); if (!hresult) /* shouldn't happen */ elog(ERROR, "local buffer hash table corrupted"); /* mark buffer invalid just in case hash insert fails */ ClearBufferTag(&bufHdr->tag); - buf_state &= ~(BM_VALID | BM_TAG_VALID); + buf_state &= ~(BUF_FLAG_MASK | BUF_USAGECOUNT_MASK); pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); pgstat_count_io_op(IOOBJECT_TEMP_RELATION, IOCONTEXT_NORMAL, IOOP_EVICT); } - hresult = (LocalBufferLookupEnt *) - hash_search(LocalBufHash, &newTag, HASH_ENTER, &found); - if (found) /* shouldn't happen */ - elog(ERROR, "local buffer hash table corrupted"); - hresult->id = b; - - /* - * it's all ours now. - */ - bufHdr->tag = newTag; - buf_state &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_IO_ERROR); - buf_state |= BM_TAG_VALID; - buf_state &= ~BUF_USAGECOUNT_MASK; - buf_state += BUF_USAGECOUNT_ONE; - pg_atomic_unlocked_write_u32(&bufHdr->state, buf_state); - - *foundPtr = false; - return bufHdr; + return BufferDescriptorGetBuffer(bufHdr); } /* @@ -424,7 +437,7 @@ InitLocalBuffers(void) (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); - nextFreeLocalBuf = 0; + nextFreeLocalBufId = 0; /* initialize fields that need to start off nonzero */ for (i = 0; i < nbufs; i++) |