1 /*-------------------------------------------------------------------------
4 * routines for mapping BufferTags to buffer indexes.
6 * Note: the routines in this file do no locking of their own. The caller
7 * must hold a suitable lock on the appropriate BufMappingLock, as specified
8 * in the comments. We can't do the locking inside these functions because
9 * in most cases the caller needs to adjust the buffer header contents
10 * before the lock is released (see notes in README).
13 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
18 * src/backend/storage/buffer/buf_table.c
20 *-------------------------------------------------------------------------
24 #include "storage/bufmgr.h"
25 #include "storage/buf_internals.h"
28 /* entry for buffer lookup hashtable */
31 BufferTag key; /* Tag of a disk page */
32 int id; /* Associated buffer ID */
35 static HTAB *SharedBufHash;
39 * Estimate space needed for mapping hashtable
40 * size is the desired hash table size (possibly more than NBuffers)
43 BufTableShmemSize(int size)
45 return hash_estimate_size(size, sizeof(BufferLookupEnt));
49 * Initialize shmem hash table for mapping buffers
50 * size is the desired hash table size (possibly more than NBuffers)
53 InitBufTable(int size)
57 /* assume no locking is needed yet */
59 /* BufferTag maps to Buffer */
60 info.keysize = sizeof(BufferTag);
61 info.entrysize = sizeof(BufferLookupEnt);
62 info.num_partitions = NUM_BUFFER_PARTITIONS;
64 SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
67 HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
72 * Compute the hash code associated with a BufferTag
74 * This must be passed to the lookup/insert/delete routines along with the
75 * tag. We do it like this because the callers need to know the hash code
76 * in order to determine which buffer partition to lock, and we don't want
77 * to do the hash computation twice (hash_any is a bit slow).
80 BufTableHashCode(BufferTag *tagPtr)
82 return get_hash_value(SharedBufHash, (void *) tagPtr);
87 * Lookup the given BufferTag; return buffer ID, or -1 if not found
89 * Caller must hold at least share lock on BufMappingLock for tag's partition
92 BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
94 BufferLookupEnt *result;
96 result = (BufferLookupEnt *)
97 hash_search_with_hash_value(SharedBufHash,
111 * Insert a hashtable entry for given tag and buffer ID,
112 * unless an entry already exists for that tag
114 * Returns -1 on successful insertion. If a conflicting entry exists
115 * already, returns the buffer ID in that entry.
117 * Caller must hold exclusive lock on BufMappingLock for tag's partition
120 BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
122 BufferLookupEnt *result;
125 Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
126 Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
128 result = (BufferLookupEnt *)
129 hash_search_with_hash_value(SharedBufHash,
135 if (found) /* found something already in the table */
145 * Delete the hashtable entry for given tag (which must exist)
147 * Caller must hold exclusive lock on BufMappingLock for tag's partition
150 BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
152 BufferLookupEnt *result;
154 result = (BufferLookupEnt *)
155 hash_search_with_hash_value(SharedBufHash,
161 if (!result) /* shouldn't happen */
162 elog(ERROR, "shared buffer hash table corrupted");