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