summaryrefslogtreecommitdiffstats
path: root/src/backend/storage/buffer/buf_table.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:19:15 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:19:15 +0000
commit6eb9c5a5657d1fe77b55cc261450f3538d35a94d (patch)
tree657d8194422a5daccecfd42d654b8a245ef7b4c8 /src/backend/storage/buffer/buf_table.c
parentInitial commit. (diff)
downloadpostgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.tar.xz
postgresql-13-6eb9c5a5657d1fe77b55cc261450f3538d35a94d.zip
Adding upstream version 13.4.upstream/13.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/storage/buffer/buf_table.c')
-rw-r--r--src/backend/storage/buffer/buf_table.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
new file mode 100644
index 0000000..4953ae9
--- /dev/null
+++ b/src/backend/storage/buffer/buf_table.c
@@ -0,0 +1,162 @@
+/*-------------------------------------------------------------------------
+ *
+ * buf_table.c
+ * routines for mapping BufferTags to buffer indexes.
+ *
+ * Note: the routines in this file do no locking of their own. The caller
+ * must hold a suitable lock on the appropriate BufMappingLock, as specified
+ * in the comments. We can't do the locking inside these functions because
+ * in most cases the caller needs to adjust the buffer header contents
+ * before the lock is released (see notes in README).
+ *
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/storage/buffer/buf_table.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "storage/buf_internals.h"
+#include "storage/bufmgr.h"
+
+/* entry for buffer lookup hashtable */
+typedef struct
+{
+ BufferTag key; /* Tag of a disk page */
+ int id; /* Associated buffer ID */
+} BufferLookupEnt;
+
+static HTAB *SharedBufHash;
+
+
+/*
+ * Estimate space needed for mapping hashtable
+ * size is the desired hash table size (possibly more than NBuffers)
+ */
+Size
+BufTableShmemSize(int size)
+{
+ return hash_estimate_size(size, sizeof(BufferLookupEnt));
+}
+
+/*
+ * Initialize shmem hash table for mapping buffers
+ * size is the desired hash table size (possibly more than NBuffers)
+ */
+void
+InitBufTable(int size)
+{
+ HASHCTL info;
+
+ /* assume no locking is needed yet */
+
+ /* BufferTag maps to Buffer */
+ info.keysize = sizeof(BufferTag);
+ info.entrysize = sizeof(BufferLookupEnt);
+ info.num_partitions = NUM_BUFFER_PARTITIONS;
+
+ SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
+ size, size,
+ &info,
+ HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
+}
+
+/*
+ * BufTableHashCode
+ * Compute the hash code associated with a BufferTag
+ *
+ * This must be passed to the lookup/insert/delete routines along with the
+ * tag. We do it like this because the callers need to know the hash code
+ * in order to determine which buffer partition to lock, and we don't want
+ * to do the hash computation twice (hash_any is a bit slow).
+ */
+uint32
+BufTableHashCode(BufferTag *tagPtr)
+{
+ return get_hash_value(SharedBufHash, (void *) tagPtr);
+}
+
+/*
+ * BufTableLookup
+ * Lookup the given BufferTag; return buffer ID, or -1 if not found
+ *
+ * Caller must hold at least share lock on BufMappingLock for tag's partition
+ */
+int
+BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
+{
+ BufferLookupEnt *result;
+
+ result = (BufferLookupEnt *)
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_FIND,
+ NULL);
+
+ if (!result)
+ return -1;
+
+ return result->id;
+}
+
+/*
+ * BufTableInsert
+ * Insert a hashtable entry for given tag and buffer ID,
+ * unless an entry already exists for that tag
+ *
+ * Returns -1 on successful insertion. If a conflicting entry exists
+ * already, returns the buffer ID in that entry.
+ *
+ * Caller must hold exclusive lock on BufMappingLock for tag's partition
+ */
+int
+BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
+{
+ BufferLookupEnt *result;
+ bool found;
+
+ Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
+ Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
+
+ result = (BufferLookupEnt *)
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_ENTER,
+ &found);
+
+ if (found) /* found something already in the table */
+ return result->id;
+
+ result->id = buf_id;
+
+ return -1;
+}
+
+/*
+ * BufTableDelete
+ * Delete the hashtable entry for given tag (which must exist)
+ *
+ * Caller must hold exclusive lock on BufMappingLock for tag's partition
+ */
+void
+BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
+{
+ BufferLookupEnt *result;
+
+ result = (BufferLookupEnt *)
+ hash_search_with_hash_value(SharedBufHash,
+ (void *) tagPtr,
+ hashcode,
+ HASH_REMOVE,
+ NULL);
+
+ if (!result) /* shouldn't happen */
+ elog(ERROR, "shared buffer hash table corrupted");
+}