0001-Allow-PrefetchBuffer-to-be-called-with-a-SMgrRela-v4.patch
text/x-patch
Filename: 0001-Allow-PrefetchBuffer-to-be-called-with-a-SMgrRela-v4.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v4-0001
Subject: Allow PrefetchBuffer() to be called with a SMgrRelation.
| File | + | − |
|---|---|---|
| src/backend/storage/buffer/bufmgr.c | 50 | 34 |
| src/backend/storage/buffer/localbuf.c | 2 | 2 |
| src/include/storage/buf_internals.h | 1 | 1 |
| src/include/storage/bufmgr.h | 6 | 0 |
From 71641bcfed33c0a89f27b5246734eb4b8196485c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Tue, 17 Mar 2020 15:25:55 +1300
Subject: [PATCH 1/5] Allow PrefetchBuffer() to be called with a SMgrRelation.
Previously a Relation was required, but it's annoying to have
to create a "fake" one in recovery. A new function
PrefetchSharedBuffer() is provided that works with SMgrRelation, and
LocalPrefetchBuffer() is renamed to PrefetchLocalBuffer() to fit with
that more natural naming scheme.
Reviewed-by: Alvaro Herrera <alvherre@2ndquadrant.com>
Discussion: https://postgr.es/m/CA%2BhUKGJ4VJN8ttxScUFM8dOKX0BrBiboo5uz1cq%3DAovOddfHpA%40mail.gmail.com
---
src/backend/storage/buffer/bufmgr.c | 84 ++++++++++++++++-----------
src/backend/storage/buffer/localbuf.c | 4 +-
src/include/storage/buf_internals.h | 2 +-
src/include/storage/bufmgr.h | 6 ++
4 files changed, 59 insertions(+), 37 deletions(-)
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index e05e2b3456..d30aed6fd9 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -466,6 +466,53 @@ static int ckpt_buforder_comparator(const void *pa, const void *pb);
static int ts_ckpt_progress_comparator(Datum a, Datum b, void *arg);
+/*
+ * Implementation of PrefetchBuffer() for shared buffers.
+ */
+void
+PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
+ ForkNumber forkNum,
+ BlockNumber blockNum)
+{
+#ifdef USE_PREFETCH
+ BufferTag newTag; /* identity of requested block */
+ uint32 newHash; /* hash value for newTag */
+ LWLock *newPartitionLock; /* buffer partition lock for it */
+ int buf_id;
+
+ Assert(BlockNumberIsValid(blockNum));
+
+ /* create a tag so we can lookup the buffer */
+ INIT_BUFFERTAG(newTag, smgr_reln->smgr_rnode.node,
+ forkNum, blockNum);
+
+ /* determine its hash code and partition lock ID */
+ newHash = BufTableHashCode(&newTag);
+ newPartitionLock = BufMappingPartitionLock(newHash);
+
+ /* see if the block is in the buffer pool already */
+ LWLockAcquire(newPartitionLock, LW_SHARED);
+ buf_id = BufTableLookup(&newTag, newHash);
+ LWLockRelease(newPartitionLock);
+
+ /* If not in buffers, initiate prefetch */
+ if (buf_id < 0)
+ smgrprefetch(smgr_reln, forkNum, blockNum);
+
+ /*
+ * If the block *is* in buffers, we do nothing. This is not really ideal:
+ * the block might be just about to be evicted, which would be stupid
+ * since we know we are going to need it soon. But the only easy answer
+ * is to bump the usage_count, which does not seem like a great solution:
+ * when the caller does ultimately touch the block, usage_count would get
+ * bumped again, resulting in too much favoritism for blocks that are
+ * involved in a prefetch sequence. A real fix would involve some
+ * additional per-buffer state, and it's not clear that there's enough of
+ * a problem to justify that.
+ */
+#endif /* USE_PREFETCH */
+}
+
/*
* PrefetchBuffer -- initiate asynchronous read of a block of a relation
*
@@ -493,43 +540,12 @@ PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
errmsg("cannot access temporary tables of other sessions")));
/* pass it off to localbuf.c */
- LocalPrefetchBuffer(reln->rd_smgr, forkNum, blockNum);
+ PrefetchLocalBuffer(reln->rd_smgr, forkNum, blockNum);
}
else
{
- BufferTag newTag; /* identity of requested block */
- uint32 newHash; /* hash value for newTag */
- LWLock *newPartitionLock; /* buffer partition lock for it */
- int buf_id;
-
- /* create a tag so we can lookup the buffer */
- INIT_BUFFERTAG(newTag, reln->rd_smgr->smgr_rnode.node,
- forkNum, blockNum);
-
- /* determine its hash code and partition lock ID */
- newHash = BufTableHashCode(&newTag);
- newPartitionLock = BufMappingPartitionLock(newHash);
-
- /* see if the block is in the buffer pool already */
- LWLockAcquire(newPartitionLock, LW_SHARED);
- buf_id = BufTableLookup(&newTag, newHash);
- LWLockRelease(newPartitionLock);
-
- /* If not in buffers, initiate prefetch */
- if (buf_id < 0)
- smgrprefetch(reln->rd_smgr, forkNum, blockNum);
-
- /*
- * If the block *is* in buffers, we do nothing. This is not really
- * ideal: the block might be just about to be evicted, which would be
- * stupid since we know we are going to need it soon. But the only
- * easy answer is to bump the usage_count, which does not seem like a
- * great solution: when the caller does ultimately touch the block,
- * usage_count would get bumped again, resulting in too much
- * favoritism for blocks that are involved in a prefetch sequence. A
- * real fix would involve some additional per-buffer state, and it's
- * not clear that there's enough of a problem to justify that.
- */
+ /* pass it to the shared buffer version */
+ PrefetchSharedBuffer(reln->rd_smgr, forkNum, blockNum);
}
#endif /* USE_PREFETCH */
}
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index cac08e1b1a..b528bc9553 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -54,14 +54,14 @@ static Block GetLocalBufferStorage(void);
/*
- * LocalPrefetchBuffer -
+ * PrefetchLocalBuffer -
* initiate asynchronous read of a block of a relation
*
* Do PrefetchBuffer's work for temporary relations.
* No-op if prefetching isn't compiled in.
*/
void
-LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum,
+PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum)
{
#ifdef USE_PREFETCH
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index bf3b8ad340..166fe334c7 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -327,7 +327,7 @@ extern int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode);
/* localbuf.c */
-extern void LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum,
+extern void PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum);
extern BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
BlockNumber blockNum, bool *foundPtr);
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index d2a5b52f6e..e00dd3ffb7 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -49,6 +49,9 @@ typedef enum
/* forward declared, to avoid having to expose buf_internals.h here */
struct WritebackContext;
+/* forward declared, to avoid including smgr.h */
+struct SMgrRelationData;
+
/* in globals.c ... this duplicates miscadmin.h */
extern PGDLLIMPORT int NBuffers;
@@ -159,6 +162,9 @@ extern PGDLLIMPORT int32 *LocalRefCount;
/*
* prototypes for functions in bufmgr.c
*/
+extern void PrefetchSharedBuffer(struct SMgrRelationData *smgr_reln,
+ ForkNumber forkNum,
+ BlockNumber blockNum);
extern void PrefetchBuffer(Relation reln, ForkNumber forkNum,
BlockNumber blockNum);
extern Buffer ReadBuffer(Relation reln, BlockNumber blockNum);
--
2.20.1