PostgreSQL Source Code  git master
buf_table.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * buf_table.c
4  * routines for mapping BufferTags to buffer indexes.
5  *
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).
11  *
12  *
13  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
14  * Portions Copyright (c) 1994, Regents of the University of California
15  *
16  *
17  * IDENTIFICATION
18  * src/backend/storage/buffer/buf_table.c
19  *
20  *-------------------------------------------------------------------------
21  */
22 #include "postgres.h"
23 
24 #include "storage/buf_internals.h"
25 
26 /* entry for buffer lookup hashtable */
27 typedef struct
28 {
29  BufferTag key; /* Tag of a disk page */
30  int id; /* Associated buffer ID */
32 
34 
35 
36 /*
37  * Estimate space needed for mapping hashtable
38  * size is the desired hash table size (possibly more than NBuffers)
39  */
40 Size
42 {
43  return hash_estimate_size(size, sizeof(BufferLookupEnt));
44 }
45 
46 /*
47  * Initialize shmem hash table for mapping buffers
48  * size is the desired hash table size (possibly more than NBuffers)
49  */
50 void
52 {
53  HASHCTL info;
54 
55  /* assume no locking is needed yet */
56 
57  /* BufferTag maps to Buffer */
58  info.keysize = sizeof(BufferTag);
59  info.entrysize = sizeof(BufferLookupEnt);
61 
62  SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
63  size, size,
64  &info,
66 }
67 
68 /*
69  * BufTableHashCode
70  * Compute the hash code associated with a BufferTag
71  *
72  * This must be passed to the lookup/insert/delete routines along with the
73  * tag. We do it like this because the callers need to know the hash code
74  * in order to determine which buffer partition to lock, and we don't want
75  * to do the hash computation twice (hash_any is a bit slow).
76  */
77 uint32
79 {
80  return get_hash_value(SharedBufHash, (void *) tagPtr);
81 }
82 
83 /*
84  * BufTableLookup
85  * Lookup the given BufferTag; return buffer ID, or -1 if not found
86  *
87  * Caller must hold at least share lock on BufMappingLock for tag's partition
88  */
89 int
90 BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
91 {
92  BufferLookupEnt *result;
93 
94  result = (BufferLookupEnt *)
96  tagPtr,
97  hashcode,
98  HASH_FIND,
99  NULL);
100 
101  if (!result)
102  return -1;
103 
104  return result->id;
105 }
106 
107 /*
108  * BufTableInsert
109  * Insert a hashtable entry for given tag and buffer ID,
110  * unless an entry already exists for that tag
111  *
112  * Returns -1 on successful insertion. If a conflicting entry exists
113  * already, returns the buffer ID in that entry.
114  *
115  * Caller must hold exclusive lock on BufMappingLock for tag's partition
116  */
117 int
118 BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
119 {
120  BufferLookupEnt *result;
121  bool found;
122 
123  Assert(buf_id >= 0); /* -1 is reserved for not-in-table */
124  Assert(tagPtr->blockNum != P_NEW); /* invalid tag */
125 
126  result = (BufferLookupEnt *)
128  tagPtr,
129  hashcode,
130  HASH_ENTER,
131  &found);
132 
133  if (found) /* found something already in the table */
134  return result->id;
135 
136  result->id = buf_id;
137 
138  return -1;
139 }
140 
141 /*
142  * BufTableDelete
143  * Delete the hashtable entry for given tag (which must exist)
144  *
145  * Caller must hold exclusive lock on BufMappingLock for tag's partition
146  */
147 void
148 BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
149 {
150  BufferLookupEnt *result;
151 
152  result = (BufferLookupEnt *)
154  tagPtr,
155  hashcode,
156  HASH_REMOVE,
157  NULL);
158 
159  if (!result) /* shouldn't happen */
160  elog(ERROR, "shared buffer hash table corrupted");
161 }
struct buftag BufferTag
void BufTableDelete(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:148
static HTAB * SharedBufHash
Definition: buf_table.c:33
int BufTableLookup(BufferTag *tagPtr, uint32 hashcode)
Definition: buf_table.c:90
void InitBufTable(int size)
Definition: buf_table.c:51
Size BufTableShmemSize(int size)
Definition: buf_table.c:41
uint32 BufTableHashCode(BufferTag *tagPtr)
Definition: buf_table.c:78
int BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id)
Definition: buf_table.c:118
#define P_NEW
Definition: bufmgr.h:192
unsigned int uint32
Definition: c.h:506
#define Assert(condition)
Definition: c.h:858
size_t Size
Definition: c.h:605
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:783
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:911
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:968
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define HASH_PARTITION
Definition: hsearch.h:92
#define NUM_BUFFER_PARTITIONS
Definition: lwlock.h:93
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
static pg_noinline void Size size
Definition: slab.c:607
BufferTag key
Definition: buf_table.c:29
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
long num_partitions
Definition: hsearch.h:68
Definition: dynahash.c:220
BlockNumber blockNum
Definition: buf_internals.h:98