From 7908fc24c5ad8ab21944c725cb4b2c2bdf1eed4b Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 14 Sep 2020 23:20:55 +1200 Subject: [PATCH v16 1/5] Provide ReadRecentBuffer() to re-pin buffers by ID. If you know the buffer ID that recently held a given block you would like to pin, this function will check if it's still there and pin it if the tag hasn't changed. Otherwise, you'll need to use the regular ReadBuffer() function. This will be used by later patches to avoid double lookup in some cases where it's very likely not to have moved. Discussion: https://postgr.es/m/CA+hUKGJ4VJN8ttxScUFM8dOKX0BrBiboo5uz1cq=AovOddfHpA@mail.gmail.com --- src/backend/storage/buffer/bufmgr.c | 43 +++++++++++++++++++++++++++++ src/include/storage/bufmgr.h | 2 ++ 2 files changed, 45 insertions(+) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 852138f9c9..0e5f92d92b 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -610,6 +610,49 @@ PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum) } } +/* + * ReadRecentBuffer -- try to refind a buffer that we suspect holds a given + * block + * + * Return true if the buffer is valid, has the correct tag, and we managed + * to pin it. + */ +bool +ReadRecentBuffer(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, + Buffer recent_buffer) +{ + BufferDesc *bufHdr; + BufferTag tag; + + Assert(BufferIsValid(recent_buffer)); + + /* Look up the header by index, and try to pin if shared. */ + if (BufferIsLocal(recent_buffer)) + bufHdr = GetBufferDescriptor(-recent_buffer - 1); + else + { + bufHdr = GetBufferDescriptor(recent_buffer - 1); + ResourceOwnerEnlargeBuffers(CurrentResourceOwner); + if (!PinBuffer(bufHdr, NULL)) + { + /* Not valid, couldn't pin it. */ + UnpinBuffer(bufHdr, true); + + return false; + } + } + + /* Does the tag still match? */ + INIT_BUFFERTAG(tag, rnode, forkNum, blockNum); + if (BUFFERTAGS_EQUAL(tag, bufHdr->tag)) + return true; + + /* Too late! Unpin if shared. */ + if (!BufferIsLocal(recent_buffer)) + UnpinBuffer(bufHdr, true); + + return false; +} /* * ReadBuffer -- a shorthand for ReadBufferExtended, for reading from main diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index fb00fda6a7..aa64fb42ec 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -176,6 +176,8 @@ extern PrefetchBufferResult PrefetchSharedBuffer(struct SMgrRelationData *smgr_r BlockNumber blockNum); extern PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum); +extern bool ReadRecentBuffer(RelFileNode rnode, ForkNumber forkNum, + BlockNumber blockNum, Buffer recent_buffer); extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum); extern Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, -- 2.30.1