From 6f2bd62a520dbf9249879afa174faf4ae063818d Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 14 Sep 2020 23:20:55 +1200 Subject: [PATCH v17 09/10] 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